#include "rsn_supp/wpa.h"
#include "eloop.h"
#include "config.h"
+#include "utils/ext_password.h"
#include "l2_packet/l2_packet.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "gas_query.h"
#include "ap.h"
#include "p2p_supplicant.h"
+#include "wifi_display.h"
#include "notify.h"
#include "bgscan.h"
+#include "autoscan.h"
#include "bss.h"
#include "scan.h"
#include "offchannel.h"
+#include "hs20_supplicant.h"
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> and contributors";
const char *wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
keylen = 16;
alg = WPA_ALG_CCMP;
break;
+ case WPA_CIPHER_GCMP:
+ os_memcpy(key, ssid->psk, 16);
+ keylen = 16;
+ alg = WPA_ALG_GCMP;
+ break;
case WPA_CIPHER_TKIP:
/* WPA-None uses the same Michael MIC key for both TX and RX */
os_memcpy(key, ssid->psk, 16 + 8);
MAC2STR(bssid));
wpa_blacklist_add(wpa_s, bssid);
wpa_sm_notify_disassoc(wpa_s->wpa);
- wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
wpa_s->reassociate = 1;
/*
* So, wait a second until scanning again.
*/
wpa_supplicant_req_scan(wpa_s, 1, 0);
+
+#ifdef CONFIG_P2P
+ if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
+ wpa_s->global->p2p != NULL) {
+ wpa_s->global->p2p_cb_on_scan_complete = 0;
+ if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
+ "continued after timed out authentication");
+ }
+ }
+#endif /* CONFIG_P2P */
}
}
-static void free_hw_features(struct wpa_supplicant *wpa_s)
+void free_hw_features(struct wpa_supplicant *wpa_s)
{
int i;
if (wpa_s->hw.modes == NULL)
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
bgscan_deinit(wpa_s);
+ autoscan_deinit(wpa_s);
scard_deinit(wpa_s->scard);
wpa_s->scard = NULL;
wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
wpa_s->gas = NULL;
free_hw_features(wpa_s);
+
+ os_free(wpa_s->bssid_filter);
+ wpa_s->bssid_filter = NULL;
+
+ os_free(wpa_s->disallow_aps_bssid);
+ wpa_s->disallow_aps_bssid = NULL;
+ os_free(wpa_s->disallow_aps_ssid);
+ wpa_s->disallow_aps_ssid = NULL;
+
+ wnm_bss_keep_alive_deinit(wpa_s);
+
+ ext_password_deinit(wpa_s->ext_pw);
+ wpa_s->ext_pw = NULL;
+
+ wpabuf_free(wpa_s->last_gas_resp);
+
+ os_free(wpa_s->last_scan_res);
+ wpa_s->last_scan_res = NULL;
}
* optimization, so the initial connection is not
* affected.
*/
- } else
+ } else {
+ struct wpa_scan_results *scan_res;
wpa_s->bgscan_ssid = wpa_s->current_ssid;
+ scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
+ 0);
+ if (scan_res) {
+ bgscan_notify_scan(wpa_s, scan_res);
+ wpa_scan_results_free(scan_res);
+ }
+ }
} else
wpa_s->bgscan_ssid = NULL;
}
#endif /* CONFIG_BGSCAN */
+static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
+{
+ if (autoscan_init(wpa_s, 0))
+ wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
+}
+
+
+static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
+{
+ autoscan_deinit(wpa_s);
+}
+
+
+void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->wpa_state == WPA_DISCONNECTED ||
+ wpa_s->wpa_state == WPA_SCANNING) {
+ autoscan_deinit(wpa_s);
+ wpa_supplicant_start_autoscan(wpa_s);
+ }
+}
+
+
/**
* wpa_supplicant_set_state - Set current connection state
* @wpa_s: Pointer to wpa_supplicant data
struct wpa_ssid *ssid = wpa_s->current_ssid;
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
MACSTR " completed %s [id=%d id_str=%s]",
- MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ?
- "(reauth)" : "(auth)",
+ MAC2STR(wpa_s->bssid), "(auth)",
ssid ? ssid->id : -1,
ssid && ssid->id_str ? ssid->id_str : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+ wpas_clear_temp_disabled(wpa_s, ssid, 1);
+ wpa_s->extra_blacklist_count = 0;
wpa_s->new_connection = 0;
- wpa_s->reassociated_connection = 1;
wpa_drv_set_operstate(wpa_s, 1);
#ifndef IEEE8021X_EAPOL
wpa_drv_set_supp_port(wpa_s, 1);
#ifdef CONFIG_P2P
wpas_p2p_completed(wpa_s);
#endif /* CONFIG_P2P */
+
+ sme_sched_obss_scan(wpa_s, 1);
} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
#ifndef IEEE8021X_EAPOL
wpa_drv_set_supp_port(wpa_s, 0);
#endif /* IEEE8021X_EAPOL */
+ sme_sched_obss_scan(wpa_s, 0);
}
wpa_s->wpa_state = state;
wpa_supplicant_stop_bgscan(wpa_s);
#endif /* CONFIG_BGSCAN */
+ if (state == WPA_AUTHENTICATING)
+ wpa_supplicant_stop_autoscan(wpa_s);
+
+ if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
+ wpa_supplicant_start_autoscan(wpa_s);
+
if (wpa_s->wpa_state != old_state) {
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
wpa_s->mgmt_group_cipher = 0;
wpa_s->key_mgmt = 0;
if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
- wpa_s->wpa_state = WPA_DISCONNECTED;
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
if (wpa_s->wpa_state != old_state)
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
wpa_supplicant_update_config(wpa_s);
wpa_supplicant_clear_status(wpa_s);
- if (wpa_supplicant_enabled_networks(wpa_s->conf)) {
+ if (wpa_supplicant_enabled_networks(wpa_s)) {
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
}
-enum wpa_cipher cipher_suite2driver(int cipher)
-{
- switch (cipher) {
- case WPA_CIPHER_NONE:
- return CIPHER_NONE;
- case WPA_CIPHER_WEP40:
- return CIPHER_WEP40;
- case WPA_CIPHER_WEP104:
- return CIPHER_WEP104;
- case WPA_CIPHER_CCMP:
- return CIPHER_CCMP;
- case WPA_CIPHER_TKIP:
- default:
- return CIPHER_TKIP;
- }
-}
-
-
enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
{
switch (key_mgmt) {
#ifdef CONFIG_IEEE80211W
if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
- ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
+ (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
+ wpa_s->conf->pmf : ssid->ieee80211w) ==
+ MGMT_FRAME_PROTECTION_REQUIRED) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
"that does not support management frame protection - "
"reject");
}
sel = ie.group_cipher & ssid->group_cipher;
- if (sel & WPA_CIPHER_CCMP) {
- wpa_s->group_cipher = WPA_CIPHER_CCMP;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP");
- } else if (sel & WPA_CIPHER_TKIP) {
- wpa_s->group_cipher = WPA_CIPHER_TKIP;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP");
- } else if (sel & WPA_CIPHER_WEP104) {
- wpa_s->group_cipher = WPA_CIPHER_WEP104;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP104");
- } else if (sel & WPA_CIPHER_WEP40) {
- wpa_s->group_cipher = WPA_CIPHER_WEP40;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40");
- } else {
+ wpa_s->group_cipher = wpa_pick_group_cipher(sel);
+ if (wpa_s->group_cipher < 0) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
"cipher");
return -1;
}
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
+ wpa_cipher_txt(wpa_s->group_cipher));
sel = ie.pairwise_cipher & ssid->pairwise_cipher;
- if (sel & WPA_CIPHER_CCMP) {
- wpa_s->pairwise_cipher = WPA_CIPHER_CCMP;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP");
- } else if (sel & WPA_CIPHER_TKIP) {
- wpa_s->pairwise_cipher = WPA_CIPHER_TKIP;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP");
- } else if (sel & WPA_CIPHER_NONE) {
- wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE");
- } else {
+ wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
+ if (wpa_s->pairwise_cipher < 0) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
"cipher");
return -1;
}
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
+ wpa_cipher_txt(wpa_s->pairwise_cipher));
sel = ie.key_mgmt & ssid->key_mgmt;
+#ifdef CONFIG_SAE
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
+ sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
+#endif /* CONFIG_SAE */
if (0) {
#ifdef CONFIG_IEEE80211R
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ } else if (sel & WPA_KEY_MGMT_SAE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
+ } else if (sel & WPA_KEY_MGMT_FT_SAE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
+#endif /* CONFIG_SAE */
#ifdef CONFIG_IEEE80211W
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
#ifdef CONFIG_IEEE80211W
sel = ie.mgmt_group_cipher;
- if (ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION ||
+ if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
+ wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
!(ie.capabilities & WPA_CAPABILITY_MFPC))
sel = 0;
if (sel & WPA_CIPHER_AES_128_CMAC) {
}
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
wpa_s->mgmt_group_cipher);
- wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, ssid->ieee80211w);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
+ (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
+ wpa_s->conf->pmf : ssid->ieee80211w));
#endif /* CONFIG_IEEE80211W */
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
ssid->passphrase) {
u8 psk[PMK_LEN];
- pbkdf2_sha1(ssid->passphrase, (char *) bss->ssid,
- bss->ssid_len, 4096, psk, PMK_LEN);
+ pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
+ 4096, psk, PMK_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
}
#endif /* CONFIG_NO_PBKDF2 */
+#ifdef CONFIG_EXT_PASSWORD
+ if (ssid->ext_psk) {
+ struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
+ ssid->ext_psk);
+ char pw_str[64 + 1];
+ u8 psk[PMK_LEN];
+
+ if (pw == NULL) {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
+ "found from external storage");
+ return -1;
+ }
+
+ if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
+ "PSK length %d in external storage",
+ (int) wpabuf_len(pw));
+ ext_password_free(pw);
+ return -1;
+ }
+
+ os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
+ pw_str[wpabuf_len(pw)] = '\0';
+
+#ifndef CONFIG_NO_PBKDF2
+ if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
+ {
+ pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
+ 4096, psk, PMK_LEN);
+ os_memset(pw_str, 0, sizeof(pw_str));
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
+ "external passphrase)",
+ psk, PMK_LEN);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
+ } else
+#endif /* CONFIG_NO_PBKDF2 */
+ if (wpabuf_len(pw) == 2 * PMK_LEN) {
+ if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
+ "Invalid PSK hex string");
+ os_memset(pw_str, 0, sizeof(pw_str));
+ ext_password_free(pw);
+ return -1;
+ }
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
+ "PSK available");
+ os_memset(pw_str, 0, sizeof(pw_str));
+ ext_password_free(pw);
+ return -1;
+ }
+
+ os_memset(pw_str, 0, sizeof(pw_str));
+ ext_password_free(pw);
+ }
+#endif /* CONFIG_EXT_PASSWORD */
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
}
+int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
+{
+ u32 ext_capab = 0;
+ u8 *pos = buf;
+
+#ifdef CONFIG_INTERWORKING
+ if (wpa_s->conf->interworking)
+ ext_capab |= BIT(31); /* Interworking */
+#endif /* CONFIG_INTERWORKING */
+
+#ifdef CONFIG_WNM
+ ext_capab |= BIT(17); /* WNM-Sleep Mode */
+ ext_capab |= BIT(19); /* BSS Transition */
+#endif /* CONFIG_WNM */
+
+ if (!ext_capab)
+ return 0;
+
+ *pos++ = WLAN_EID_EXT_CAPAB;
+ *pos++ = 4;
+ WPA_PUT_LE32(pos, ext_capab);
+ pos += 4;
+
+ return pos - buf;
+}
+
+
/**
* wpa_supplicant_associate - Request association
* @wpa_s: Pointer to wpa_supplicant data
struct wpa_driver_capa capa;
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
+ u8 ext_capab[10];
+ int ext_capab_len;
#ifdef CONFIG_HT_OVERRIDES
struct ieee80211_ht_capabilities htcaps;
struct ieee80211_ht_capabilities htcaps_mask;
"mode");
return;
}
- wpa_supplicant_create_ap(wpa_s, ssid);
+ if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+ return;
+ }
wpa_s->current_bss = bss;
#else /* CONFIG_AP */
wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
/* Use ap_scan==1 style network selection to find the network
*/
- wpa_s->scan_req = 2;
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
return;
wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt)) {
int try_opportunistic;
- try_opportunistic = ssid->proactive_key_caching &&
+ try_opportunistic = (ssid->proactive_key_caching < 0 ?
+ wpa_s->conf->okc :
+ ssid->proactive_key_caching) &&
(ssid->proto & WPA_PROTO_RSN);
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
wpa_s->current_ssid,
"key management and encryption suites");
return;
}
+ } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
+ wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
+ /*
+ * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
+ * use non-WPA since the scan results did not indicate that the
+ * AP is using WPA or WPA2.
+ */
+ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
+ wpa_ie_len = 0;
+ wpa_s->wpa_proto = 0;
} else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
u8 *pos;
size_t len;
int res;
- int p2p_group;
- p2p_group = wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE;
pos = wpa_ie + wpa_ie_len;
len = sizeof(wpa_ie) - wpa_ie_len;
- res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, p2p_group);
+ res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
+ ssid->p2p_group);
if (res >= 0)
wpa_ie_len += res;
}
}
#endif /* CONFIG_P2P */
-#ifdef CONFIG_INTERWORKING
- if (wpa_s->conf->interworking) {
+#ifdef CONFIG_HS20
+ if (wpa_s->conf->hs20) {
+ struct wpabuf *hs20;
+ hs20 = wpabuf_alloc(20);
+ if (hs20) {
+ wpas_hs20_add_indication(hs20);
+ os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
+ wpabuf_len(hs20));
+ wpa_ie_len += wpabuf_len(hs20);
+ wpabuf_free(hs20);
+ }
+ }
+#endif /* CONFIG_HS20 */
+
+ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
+ if (ext_capab_len > 0) {
u8 *pos = wpa_ie;
if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
pos += 2 + pos[1];
- os_memmove(pos + 6, pos, wpa_ie_len - (pos - wpa_ie));
- wpa_ie_len += 6;
- *pos++ = WLAN_EID_EXT_CAPAB;
- *pos++ = 4;
- *pos++ = 0x00;
- *pos++ = 0x00;
- *pos++ = 0x00;
- *pos++ = 0x80; /* Bit 31 - Interworking */
+ os_memmove(pos + ext_capab_len, pos,
+ wpa_ie_len - (pos - wpa_ie));
+ wpa_ie_len += ext_capab_len;
+ os_memcpy(pos, ext_capab, ext_capab_len);
}
-#endif /* CONFIG_INTERWORKING */
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
- cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher);
- cipher_group = cipher_suite2driver(wpa_s->group_cipher);
+ cipher_pairwise = wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
+ cipher_group = wpa_cipher_to_suite_driver(wpa_s->group_cipher);
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
if (bss) {
params.ssid = bss->ssid;
params.ssid_len = bss->ssid_len;
- if (!wpas_driver_bss_selection(wpa_s)) {
+ if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
+ wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
+ MACSTR " freq=%u MHz based on scan results "
+ "(bssid_set=%d)",
+ MAC2STR(bss->bssid), bss->freq,
+ ssid->bssid_set);
params.bssid = bss->bssid;
params.freq = bss->freq;
}
params.wpa_proto = wpa_s->wpa_proto;
params.auth_alg = algs;
params.mode = ssid->mode;
+ params.bg_scan_period = ssid->bg_scan_period;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (ssid->wep_key_len[i])
params.wep_key[i] = ssid->wep_key[i];
params.drop_unencrypted = use_crypt;
#ifdef CONFIG_IEEE80211W
- params.mgmt_frame_protection = ssid->ieee80211w;
- if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION && bss) {
+ params.mgmt_frame_protection =
+ ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
+ wpa_s->conf->pmf : ssid->ieee80211w;
+ if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
struct wpa_ie_data ie;
if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) {
wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)"
, freq, params.freq);
- if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) < 0) {
- /* Handling conflicts failed. Disable the current connect req and
- * notify the userspace to take appropriate action */
- wpa_printf(MSG_DEBUG, "proiritize is not set. Notifying user space to handle the case");
- wpa_supplicant_disable_network(wpa_s, ssid);
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
- " id=%d", ssid->id);
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0)
return;
- }
}
#endif
ret = wpa_drv_associate(wpa_s, ¶ms);
* succeed.
*/
wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
return;
}
struct wpa_ssid *old_ssid;
wpa_clear_keys(wpa_s, addr);
- wpa_supplicant_mark_disassoc(wpa_s);
old_ssid = wpa_s->current_ssid;
- wpa_s->current_ssid = NULL;
- wpa_s->current_bss = NULL;
+ wpa_supplicant_mark_disassoc(wpa_s);
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
if (old_ssid != wpa_s->current_ssid)
/**
- * wpa_supplicant_disassociate - Disassociate the current connection
- * @wpa_s: Pointer to wpa_supplicant data
- * @reason_code: IEEE 802.11 reason code for the disassociate frame
- *
- * This function is used to request %wpa_supplicant to disassociate with the
- * current AP.
- */
-void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
- int reason_code)
-{
- u8 *addr = NULL;
-
- if (!is_zero_ether_addr(wpa_s->bssid)) {
- wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
- addr = wpa_s->bssid;
- }
-
- wpa_supplicant_clear_connection(wpa_s, addr);
-}
-
-
-/**
* wpa_supplicant_deauthenticate - Deauthenticate the current connection
* @wpa_s: Pointer to wpa_supplicant data
* @reason_code: IEEE 802.11 reason code for the deauthenticate frame
int reason_code)
{
u8 *addr = NULL;
+ union wpa_event_data event;
+ int zero_addr = 0;
- if (!is_zero_ether_addr(wpa_s->bssid)) {
- wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, reason_code);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
+ " pending_bssid=" MACSTR " reason=%d state=%s",
+ MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
+ reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
+
+ if (!is_zero_ether_addr(wpa_s->bssid))
+ addr = wpa_s->bssid;
+ else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
+ (wpa_s->wpa_state == WPA_AUTHENTICATING ||
+ wpa_s->wpa_state == WPA_ASSOCIATING))
+ addr = wpa_s->pending_bssid;
+ else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
+ /*
+ * When using driver-based BSS selection, we may not know the
+ * BSSID with which we are currently trying to associate. We
+ * need to notify the driver of this disconnection even in such
+ * a case, so use the all zeros address here.
+ */
addr = wpa_s->bssid;
+ zero_addr = 1;
+ }
+
+ if (addr) {
+ wpa_drv_deauthenticate(wpa_s, addr, reason_code);
+ os_memset(&event, 0, sizeof(event));
+ event.deauth_info.reason_code = (u16) reason_code;
+ event.deauth_info.locally_generated = 1;
+ wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
+ if (zero_addr)
+ addr = NULL;
}
wpa_supplicant_clear_connection(wpa_s, addr);
was_disabled = other_ssid->disabled;
other_ssid->disabled = 0;
+ if (was_disabled)
+ wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
if (was_disabled != other_ssid->disabled)
wpas_notify_network_enabled_changed(
was_disabled = ssid->disabled;
ssid->disabled = 0;
+ wpas_clear_temp_disabled(wpa_s, ssid, 1);
if (was_disabled != ssid->disabled)
wpas_notify_network_enabled_changed(wpa_s, ssid);
wpa_s, other_ssid);
}
if (wpa_s->current_ssid)
- wpa_supplicant_disassociate(
+ wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
} else if (ssid->disabled != 2) {
if (ssid == wpa_s->current_ssid)
- wpa_supplicant_disassociate(
+ wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
was_disabled = ssid->disabled;
int disconnected = 0;
if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
- wpa_supplicant_disassociate(
+ wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
disconnected = 1;
}
+ if (ssid)
+ wpas_clear_temp_disabled(wpa_s, ssid, 1);
+
/*
* Mark all other networks disabled or mark all networks enabled if no
* network specified.
continue; /* do not change persistent P2P group data */
other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
+ if (was_disabled && !other_ssid->disabled)
+ wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
if (was_disabled != other_ssid->disabled)
wpas_notify_network_enabled_changed(wpa_s, other_ssid);
/**
+ * wpa_supplicant_set_scan_interval - Set scan interval
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @scan_interval: scan interval in seconds
+ * Returns: 0 if succeed or -1 if scan_interval has an invalid value
+ *
+ */
+int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
+ int scan_interval)
+{
+ if (scan_interval < 0) {
+ wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
+ scan_interval);
+ return -1;
+ }
+ wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
+ scan_interval);
+ wpa_s->scan_interval = scan_interval;
+
+ return 0;
+}
+
+
+/**
* wpa_supplicant_set_debug_params - Set global debug params
* @global: wpa_global structure
* @debug_level: debug level
entry = wpa_s->conf->ssid;
while (entry) {
- if (!entry->disabled &&
+ if (!wpas_network_disabled(wpa_s, entry) &&
((ssid_len == entry->ssid_len &&
os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
(!entry->bssid_set ||
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
return entry;
#ifdef CONFIG_WPS
- if (!entry->disabled &&
+ if (!wpas_network_disabled(wpa_s, entry) &&
(entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
(entry->ssid == NULL || entry->ssid_len == 0) &&
(!entry->bssid_set ||
return entry;
#endif /* CONFIG_WPS */
- if (!entry->disabled && entry->bssid_set &&
+ if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
entry->ssid_len == 0 &&
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
return entry;
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
- if (wpa_s->wpa_state < WPA_ASSOCIATED) {
+ if (wpa_s->wpa_state < WPA_ASSOCIATED ||
+ (wpa_s->last_eapol_matches_bssid &&
+#ifdef CONFIG_AP
+ !wpa_s->ap_iface &&
+#endif /* CONFIG_AP */
+ os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
/*
* There is possible race condition between receiving the
* association event and the EAPOL frame since they are coming
* through different paths from the driver. In order to avoid
* issues in trying to process the EAPOL frame before receiving
* association information, lets queue it for processing until
- * the association event is received.
+ * the association event is received. This may also be needed in
+ * driver-based roaming case, so also use src_addr != BSSID as a
+ * trigger if we have previously confirmed that the
+ * Authenticator uses BSSID as the src_addr (which is not the
+ * case with wired IEEE 802.1X).
*/
wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
- "of received EAPOL frame");
+ "of received EAPOL frame (state=%s bssid=" MACSTR ")",
+ wpa_supplicant_state_txt(wpa_s->wpa_state),
+ MAC2STR(wpa_s->bssid));
wpabuf_free(wpa_s->pending_eapol_rx);
wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
if (wpa_s->pending_eapol_rx) {
return;
}
+ wpa_s->last_eapol_matches_bssid =
+ os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
+
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
}
+static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
+ const u8 *buf, size_t len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ const struct l2_ethhdr *eth;
+
+ if (len < sizeof(*eth))
+ return;
+ eth = (const struct l2_ethhdr *) buf;
+
+ if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
+ !(eth->h_dest[0] & 0x01)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
+ " (bridge - not for this interface - ignore)",
+ MAC2STR(src_addr), MAC2STR(eth->h_dest));
+ return;
+ }
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
+ " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
+ wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
+ len - sizeof(*eth));
+}
+
+
/**
* wpa_supplicant_driver_init - Initialize driver interface parameters
* @wpa_s: Pointer to wpa_supplicant data
wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
wpa_s->own_addr,
ETH_P_EAPOL,
- wpa_supplicant_rx_eapol, wpa_s,
- 0);
+ wpa_supplicant_rx_eapol_bridge,
+ wpa_s, 1);
if (wpa_s->l2_br == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
"connection for the bridge interface '%s'",
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
wpa_s->prev_scan_wildcard = 0;
- if (wpa_supplicant_enabled_networks(wpa_s->conf)) {
+ if (wpa_supplicant_enabled_networks(wpa_s)) {
if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
100000))
wpa_supplicant_req_scan(wpa_s, interface_count,
wpa_s = os_zalloc(sizeof(*wpa_s));
if (wpa_s == NULL)
return NULL;
- wpa_s->scan_req = 1;
+ wpa_s->scan_req = INITIAL_SCAN_REQ;
wpa_s->scan_interval = 5;
wpa_s->new_connection = 1;
wpa_s->parent = wpa_s;
}
+static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
+ struct ieee80211_ht_capabilities *htcaps,
+ struct ieee80211_ht_capabilities *htcaps_mask,
+ int disabled)
+{
+ /* Masking these out disables SGI */
+ u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
+ HT_CAP_INFO_SHORT_GI40MHZ);
+
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
+
+ if (disabled)
+ htcaps->ht_capabilities_info &= ~msk;
+ else
+ htcaps->ht_capabilities_info |= msk;
+
+ htcaps_mask->ht_capabilities_info |= msk;
+
+ return 0;
+}
+
+
void wpa_supplicant_apply_ht_overrides(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_driver_associate_params *params)
wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
+ wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
}
#endif /* CONFIG_HT_OVERRIDES */
+static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
+{
+#ifdef PCSC_FUNCS
+ size_t len;
+
+ if (!wpa_s->conf->pcsc_reader)
+ return 0;
+
+ wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
+ if (!wpa_s->scard)
+ return 1;
+
+ if (wpa_s->conf->pcsc_pin &&
+ scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
+ scard_deinit(wpa_s->scard);
+ wpa_s->scard = NULL;
+ wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
+ return -1;
+ }
+
+ len = sizeof(wpa_s->imsi) - 1;
+ if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
+ scard_deinit(wpa_s->scard);
+ wpa_s->scard = NULL;
+ wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
+ return -1;
+ }
+ wpa_s->imsi[len] = '\0';
+
+ wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
+
+ wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
+ wpa_s->imsi, wpa_s->mnc_len);
+
+ wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
+ eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
+#endif /* PCSC_FUNCS */
+
+ return 0;
+}
+
+
+int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
+{
+ char *val, *pos;
+
+ ext_password_deinit(wpa_s->ext_pw);
+ wpa_s->ext_pw = NULL;
+ eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
+
+ if (!wpa_s->conf->ext_password_backend)
+ return 0;
+
+ val = os_strdup(wpa_s->conf->ext_password_backend);
+ if (val == NULL)
+ return -1;
+ pos = os_strchr(val, ':');
+ if (pos)
+ *pos++ = '\0';
+
+ wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
+
+ wpa_s->ext_pw = ext_password_init(val, pos);
+ os_free(val);
+ if (wpa_s->ext_pw == NULL) {
+ wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
+ return -1;
+ }
+ eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
+
+ return 0;
+}
+
+
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
struct wpa_interface *iface)
{
if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
wpa_s->drv_capa_known = 1;
wpa_s->drv_flags = capa.flags;
+ wpa_s->drv_enc = capa.enc;
wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
wpa_s->max_scan_ssids = capa.max_scan_ssids;
wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
if (wpa_bss_init(wpa_s) < 0)
return -1;
+ if (pcsc_reader_init(wpa_s) < 0)
+ return -1;
+
+ if (wpas_init_ext_pw(wpa_s) < 0)
+ return -1;
+
return 0;
}
wpa_supplicant_cleanup(wpa_s);
+#ifdef CONFIG_P2P
+ if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
+ "the management interface is being removed");
+ wpas_p2p_deinit_global(wpa_s->global);
+ }
+#endif /* CONFIG_P2P */
+
if (wpa_s->drv_priv)
wpa_drv_deinit(wpa_s);
global->ifaces = wpa_s;
wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
return wpa_s;
}
wpa_debug_open_file(params->wpa_debug_file_path);
if (params->wpa_debug_syslog)
wpa_debug_open_syslog();
+ if (params->wpa_debug_tracing) {
+ ret = wpa_debug_open_linux_tracing();
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "Failed to enable trace logging");
+ return NULL;
+ }
+ }
ret = eap_register_methods();
if (ret) {
return NULL;
}
+#ifdef CONFIG_WIFI_DISPLAY
+ if (wifi_display_init(global) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
+ wpa_supplicant_deinit(global);
+ return NULL;
+ }
+#endif /* CONFIG_WIFI_DISPLAY */
+
return global;
}
if (global == NULL)
return;
+#ifdef CONFIG_WIFI_DISPLAY
+ wifi_display_deinit(global);
+#endif /* CONFIG_WIFI_DISPLAY */
#ifdef CONFIG_P2P
wpas_p2p_deinit_global(global);
#endif /* CONFIG_P2P */
os_free(global->params.override_driver);
os_free(global->params.override_ctrl_interface);
+ os_free(global->p2p_disallow_freq);
+
os_free(global);
wpa_debug_close_syslog();
wpa_debug_close_file();
+ wpa_debug_close_linux_tracing();
}
}
}
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
+ wpas_init_ext_pw(wpa_s);
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
}
}
+ /*
+ * Add previous failure count in case the temporary blacklist was
+ * cleared due to no other BSSes being available.
+ */
+ count += wpa_s->extra_blacklist_count;
+
switch (count) {
case 1:
timeout = 100;
case 3:
timeout = 1000;
break;
- default:
+ case 4:
timeout = 5000;
+ break;
+ default:
+ timeout = 10000;
+ break;
}
+ wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
+ "ms", count, timeout);
+
/*
* TODO: if more than one possible AP is available in scan results,
* could try the other ones before requesting a new scan.
*/
wpa_supplicant_req_scan(wpa_s, timeout / 1000,
1000 * (timeout % 1000));
+
+#ifdef CONFIG_P2P
+ if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
+ wpa_s->global->p2p != NULL) {
+ wpa_s->global->p2p_cb_on_scan_complete = 0;
+ if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
+ "continued after failed association");
+ }
+ }
+#endif /* CONFIG_P2P */
}
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
}
-#ifdef ANDROID_P2P
+
+#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
+int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ const char *field,
+ const char *value)
+{
+#ifdef IEEE8021X_EAPOL
+ struct eap_peer_config *eap = &ssid->eap;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
+ wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
+ (const u8 *) value, os_strlen(value));
+
+ switch (wpa_supplicant_ctrl_req_from_string(field)) {
+ case WPA_CTRL_REQ_EAP_IDENTITY:
+ os_free(eap->identity);
+ eap->identity = (u8 *) os_strdup(value);
+ eap->identity_len = os_strlen(value);
+ eap->pending_req_identity = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
+ break;
+ case WPA_CTRL_REQ_EAP_PASSWORD:
+ os_free(eap->password);
+ eap->password = (u8 *) os_strdup(value);
+ eap->password_len = os_strlen(value);
+ eap->pending_req_password = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
+ break;
+ case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
+ os_free(eap->new_password);
+ eap->new_password = (u8 *) os_strdup(value);
+ eap->new_password_len = os_strlen(value);
+ eap->pending_req_new_password = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
+ break;
+ case WPA_CTRL_REQ_EAP_PIN:
+ os_free(eap->pin);
+ eap->pin = os_strdup(value);
+ eap->pending_req_pin = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
+ break;
+ case WPA_CTRL_REQ_EAP_OTP:
+ os_free(eap->otp);
+ eap->otp = (u8 *) os_strdup(value);
+ eap->otp_len = os_strlen(value);
+ os_free(eap->pending_req_otp);
+ eap->pending_req_otp = NULL;
+ eap->pending_req_otp_len = 0;
+ break;
+ case WPA_CTRL_REQ_EAP_PASSPHRASE:
+ os_free(eap->private_key_passwd);
+ eap->private_key_passwd = (u8 *) os_strdup(value);
+ eap->pending_req_passphrase = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
+ return -1;
+ }
+
+ return 0;
+#else /* IEEE8021X_EAPOL */
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
+ return -1;
+#endif /* IEEE8021X_EAPOL */
+}
+#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
+
+
+int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ int i;
+ unsigned int drv_enc;
+
+ if (ssid == NULL)
+ return 1;
+
+ if (ssid->disabled)
+ return 1;
+
+ if (wpa_s && wpa_s->drv_capa_known)
+ drv_enc = wpa_s->drv_enc;
+ else
+ drv_enc = (unsigned int) -1;
+
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ size_t len = ssid->wep_key_len[i];
+ if (len == 0)
+ continue;
+ if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
+ continue;
+ if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
+ continue;
+ if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
+ continue;
+ return 1; /* invalid WEP key */
+ }
+
+ if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
+ !ssid->ext_psk)
+ return 1;
+
+ return 0;
+}
+
+
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
{
if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
return 1;
if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
return 0;
-
- /* IF conc_priority is not set, return -1 */
return -1;
}
-#endif
+
+
+void wpas_auth_failed(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ int dur;
+ struct os_time now;
+
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "Authentication failure but no known "
+ "SSID block");
+ return;
+ }
+
+ if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
+ return;
+
+ ssid->auth_failures++;
+ if (ssid->auth_failures > 50)
+ dur = 300;
+ else if (ssid->auth_failures > 20)
+ dur = 120;
+ else if (ssid->auth_failures > 10)
+ dur = 60;
+ else if (ssid->auth_failures > 5)
+ dur = 30;
+ else if (ssid->auth_failures > 1)
+ dur = 20;
+ else
+ dur = 10;
+
+ os_get_time(&now);
+ if (now.sec + dur <= ssid->disabled_until.sec)
+ return;
+
+ ssid->disabled_until.sec = now.sec + dur;
+
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
+ "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
+ ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->auth_failures, dur);
+}
+
+
+void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid, int clear_failures)
+{
+ if (ssid == NULL)
+ return;
+
+ if (ssid->disabled_until.sec) {
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
+ "id=%d ssid=\"%s\"",
+ ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ }
+ ssid->disabled_until.sec = 0;
+ ssid->disabled_until.usec = 0;
+ if (clear_failures)
+ ssid->auth_failures = 0;
+}
+
+
+int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+ size_t i;
+
+ if (wpa_s->disallow_aps_bssid == NULL)
+ return 0;
+
+ for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
+ if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
+ bssid, ETH_ALEN) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
+ size_t ssid_len)
+{
+ size_t i;
+
+ if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
+ return 0;
+
+ for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
+ struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
+ if (ssid_len == s->ssid_len &&
+ os_memcmp(ssid, s->ssid, ssid_len) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * wpas_request_connection - Request a new connection
+ * @wpa_s: Pointer to the network interface
+ *
+ * This function is used to request a new connection to be found. It will mark
+ * the interface to allow reassociation and request a new scan to find a
+ * suitable network to connect to.
+ */
+void wpas_request_connection(struct wpa_supplicant *wpa_s)
+{
+ wpa_s->normal_scans = 0;
+ wpa_supplicant_reinit_autoscan(wpa_s);
+ wpa_s->extra_blacklist_count = 0;
+ wpa_s->disconnected = 0;
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+}