/*
* WPA Supplicant
- * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include "includes.h"
#include "common.h"
+#include "crypto/random.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "eap_peer/eap.h"
#include "eap_server/eap_methods.h"
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi> and contributors";
const char *wpa_supplicant_license =
"This program is free software. You can distribute it and/or modify it\n"
continue;
set = 1;
- wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
- (u8 *) "\xff\xff\xff\xff\xff\xff",
- i, i == ssid->wep_tx_keyidx, (u8 *) "", 0,
+ wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
+ i, i == ssid->wep_tx_keyidx, NULL, 0,
ssid->wep_key[i], ssid->wep_key_len[i]);
}
* sending unicast and multicast packets. */
if (ssid->mode != WPAS_MODE_IBSS) {
- wpa_printf(MSG_INFO, "WPA: Invalid mode %d (not IBSS/ad-hoc) "
- "for WPA-None", ssid->mode);
+ wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
+ "IBSS/ad-hoc) for WPA-None", ssid->mode);
return -1;
}
if (!ssid->psk_set) {
- wpa_printf(MSG_INFO, "WPA: No PSK configured for WPA-None");
+ wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
+ "WPA-None");
return -1;
}
alg = WPA_ALG_TKIP;
break;
default:
- wpa_printf(MSG_INFO, "WPA: Invalid group cipher %d for "
- "WPA-None", wpa_s->group_cipher);
+ wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
+ "WPA-None", wpa_s->group_cipher);
return -1;
}
/* TODO: should actually remember the previously used seq#, both for TX
* and RX from each STA.. */
- return wpa_drv_set_key(wpa_s, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
- 0, 1, seq, 6, key, keylen);
+ return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
}
wpa_sm_notify_disassoc(wpa_s->wpa);
wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+ /*
+ * If we timed out, the AP or the local radio may be busy.
+ * So, wait a second until scanning again.
+ */
+ wpa_supplicant_req_scan(wpa_s, 1, 0);
}
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
return;
- wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
+ wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
"%d usec", sec, usec);
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
*/
void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
{
- wpa_msg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
wpa_blacklist_del(wpa_s, wpa_s->bssid);
}
rsn_preauth_deinit(wpa_s->wpa);
+#ifdef CONFIG_TDLS
+ wpa_tdls_deinit(wpa_s->wpa);
+#endif /* CONFIG_TDLS */
+
pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa);
wpa_s->wpa = NULL;
wpa_s->ibss_rsn = NULL;
#endif /* CONFIG_IBSS_RSN */
-#ifdef CONFIG_SME
- os_free(wpa_s->sme.ft_ies);
- wpa_s->sme.ft_ies = NULL;
- wpa_s->sme.ft_ies_len = 0;
-#endif /* CONFIG_SME */
+ sme_deinit(wpa_s);
#ifdef CONFIG_AP
wpa_supplicant_ap_deinit(wpa_s);
#ifdef CONFIG_P2P
wpas_p2p_deinit(wpa_s);
#endif /* CONFIG_P2P */
+
+ os_free(wpa_s->next_scan_freqs);
+ wpa_s->next_scan_freqs = NULL;
}
*/
void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
{
- u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff";
-
if (wpa_s->keys_cleared) {
/* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
* timing issues with keys being cleared just before new keys
* client not receiving the first encrypted packets correctly.
* Skipping some of the extra key clearing steps seems to help
* in completing group key handshake more reliably. */
- wpa_printf(MSG_DEBUG, "No keys have been configured - "
- "skip key clearing");
+ wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
+ "skip key clearing");
return;
}
/* MLME-DELETEKEYS.request */
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0);
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
#ifdef CONFIG_IEEE80211W
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 4, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 5, 0, NULL, 0, NULL, 0);
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
#endif /* CONFIG_IEEE80211W */
if (addr) {
wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
}
+#ifdef CONFIG_BGSCAN
+
+static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
+ return;
+
+ bgscan_deinit(wpa_s);
+ if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) {
+ if (bgscan_init(wpa_s, wpa_s->current_ssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
+ "bgscan");
+ /*
+ * Live without bgscan; it is only used as a roaming
+ * optimization, so the initial connection is not
+ * affected.
+ */
+ } else
+ wpa_s->bgscan_ssid = wpa_s->current_ssid;
+ } else
+ wpa_s->bgscan_ssid = NULL;
+}
+
+
+static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->bgscan_ssid != NULL) {
+ bgscan_deinit(wpa_s);
+ wpa_s->bgscan_ssid = NULL;
+ }
+}
+
+#endif /* CONFIG_BGSCAN */
+
+
/**
* wpa_supplicant_set_state - Set current connection state
* @wpa_s: Pointer to wpa_supplicant data
{
enum wpa_states old_state = wpa_s->wpa_state;
- wpa_printf(MSG_DEBUG, "State: %s -> %s",
- wpa_supplicant_state_txt(wpa_s->wpa_state),
- wpa_supplicant_state_txt(state));
+ wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
+ wpa_supplicant_state_txt(wpa_s->wpa_state),
+ wpa_supplicant_state_txt(state));
if (state != WPA_SCANNING)
wpa_supplicant_notify_scanning(wpa_s, 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);
+#endif /* IEEE8021X_EAPOL */
wpa_s->after_wps = 0;
#ifdef CONFIG_P2P
wpas_p2p_completed(wpa_s);
state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
wpa_drv_set_operstate(wpa_s, 0);
+#ifndef IEEE8021X_EAPOL
+ wpa_drv_set_supp_port(wpa_s, 0);
+#endif /* IEEE8021X_EAPOL */
}
wpa_s->wpa_state = state;
- if (wpa_s->wpa_state != old_state)
+#ifdef CONFIG_BGSCAN
+ if (state == WPA_COMPLETED)
+ wpa_supplicant_start_bgscan(wpa_s);
+ else
+ wpa_supplicant_stop_bgscan(wpa_s);
+#endif /* CONFIG_BGSCAN */
+
+ if (wpa_s->wpa_state != old_state) {
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
+
+ if (wpa_s->wpa_state == WPA_COMPLETED ||
+ old_state == WPA_COMPLETED)
+ wpas_notify_auth_changed(wpa_s);
+ }
}
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
- wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
return 0;
}
{
struct wpa_global *global = signal_ctx;
struct wpa_supplicant *wpa_s;
- wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig);
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
+ sig);
if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
wpa_supplicant_terminate_proc(global);
}
return -1;
}
- wpa_printf(MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set cipher "
- "suites");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
+ "cipher suites");
if (!(ie->group_cipher & ssid->group_cipher)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
"cipher 0x%x (mask 0x%x) - reject",
(ie.group_cipher & ssid->group_cipher) &&
(ie.pairwise_cipher & ssid->pairwise_cipher) &&
(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_msg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
proto = WPA_PROTO_RSN;
} else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
(ie.group_cipher & ssid->group_cipher) &&
(ie.pairwise_cipher & ssid->pairwise_cipher) &&
(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA;
} else if (bss) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
WPA_CIPHER_AES_128_CMAC : 0;
#endif /* CONFIG_IEEE80211W */
- wpa_printf(MSG_DEBUG, "WPA: Set cipher suites based "
- "on configuration");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
+ "based on configuration");
} else
proto = ie.proto;
}
- wpa_printf(MSG_DEBUG, "WPA: Selected cipher suites: group %d "
- "pairwise %d key_mgmt %d proto %d",
- ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
+ "pairwise %d key_mgmt %d proto %d",
+ ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
#ifdef CONFIG_IEEE80211W
if (ssid->ieee80211w) {
- wpa_printf(MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
- ie.mgmt_group_cipher);
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
+ ie.mgmt_group_cipher);
}
#endif /* CONFIG_IEEE80211W */
sel = ie.group_cipher & ssid->group_cipher;
if (sel & WPA_CIPHER_CCMP) {
wpa_s->group_cipher = WPA_CIPHER_CCMP;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK 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_msg(wpa_s, MSG_DEBUG, "WPA: using GTK 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_msg(wpa_s, MSG_DEBUG, "WPA: using GTK 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_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40");
} else {
- wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher.");
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
+ "cipher");
return -1;
}
sel = ie.pairwise_cipher & ssid->pairwise_cipher;
if (sel & WPA_CIPHER_CCMP) {
wpa_s->pairwise_cipher = WPA_CIPHER_CCMP;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK 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_msg(wpa_s, MSG_DEBUG, "WPA: using PTK 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_msg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE");
} else {
- wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
- "cipher.");
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
+ "cipher");
return -1;
}
#ifdef CONFIG_IEEE80211R
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
} else if (sel & WPA_KEY_MGMT_FT_PSK) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
- wpa_msg(wpa_s, MSG_DEBUG,
+ wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT 802.1X with SHA256");
} else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
- wpa_msg(wpa_s, MSG_DEBUG,
+ wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT PSK with SHA256");
#endif /* CONFIG_IEEE80211W */
} else if (sel & WPA_KEY_MGMT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
} else if (sel & WPA_KEY_MGMT_PSK) {
wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
} else if (sel & WPA_KEY_MGMT_WPA_NONE) {
wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
} else {
- wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated "
- "key management type.");
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
+ "authenticated key management type");
return -1;
}
sel = 0;
if (sel & WPA_CIPHER_AES_128_CMAC) {
wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
"AES-128-CMAC");
} else {
wpa_s->mgmt_group_cipher = 0;
- wpa_msg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
}
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
wpa_s->mgmt_group_cipher);
#endif /* CONFIG_IEEE80211W */
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
- wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE.");
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
return -1;
}
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
+#ifdef CONFIG_IBSS_RSN
+ ibss_rsn_deinit(wpa_s->ibss_rsn);
+ wpa_s->ibss_rsn = NULL;
+#endif /* CONFIG_IBSS_RSN */
+
if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
#ifdef CONFIG_AP
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
- wpa_printf(MSG_INFO, "Driver does not support AP "
- "mode");
+ wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
+ "mode");
return;
}
wpa_supplicant_create_ap(wpa_s, ssid);
wpa_s->current_bss = bss;
#else /* CONFIG_AP */
- wpa_printf(MSG_ERROR, "AP mode support not included in the "
- "build");
+ wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
+ "the build");
#endif /* CONFIG_AP */
return;
}
+#ifdef CONFIG_TDLS
+ if (bss)
+ wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
+ bss->ie_len);
+#endif /* CONFIG_TDLS */
+
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
ssid->mode == IEEE80211_MODE_INFRA) {
sme_authenticate(wpa_s, bss, ssid);
}
}
#endif /* IEEE8021X_EAPOL */
- wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
if (ssid->auth_alg) {
algs = ssid->auth_alg;
- wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x",
- algs);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
+ "0x%x", algs);
}
if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len)) {
- wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
- "management and encryption suites");
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
+ "key management and encryption suites");
return;
}
} else if (ssid->key_mgmt &
wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
wpa_ie, &wpa_ie_len)) {
- wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
- "management and encryption suites (no scan "
- "results)");
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
+ "key management and encryption suites (no "
+ "scan results)");
return;
}
#ifdef CONFIG_WPS
wpa_s->cross_connect_disallowed =
p2p_get_cross_connect_disallowed(p2p);
wpabuf_free(p2p);
- wpa_printf(MSG_DEBUG, "P2P: WLAN AP %s cross "
- "connection",
- wpa_s->cross_connect_disallowed ?
- "disallows" : "allows");
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
+ "connection",
+ wpa_s->cross_connect_disallowed ?
+ "disallows" : "allows");
}
}
#endif /* CONFIG_P2P */
if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
ie.capabilities &
(WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
- wpa_printf(MSG_DEBUG, "WPA: Selected AP supports MFP: "
- "require MFP");
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
+ "MFP: require MFP");
params.mgmt_frame_protection =
MGMT_FRAME_PROTECTION_REQUIRED;
}
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
"failed");
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
+ /*
+ * The driver is known to mean what is saying, so we
+ * can stop right here; the association will not
+ * succeed.
+ */
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ return;
+ }
/* try to continue anyway; new association will be tried again
* after timeout */
assoc_failed = 1;
} else if (ssid->mode == WPAS_MODE_IBSS &&
wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
- ibss_rsn_set_psk(wpa_s->ibss_rsn, ssid->psk);
/*
* RSN IBSS authentication is per-STA and we can disable the
* per-BSSID authentication.
}
+/**
+ * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @expire_age: Expiration age in seconds
+ * Returns: 0 if succeed or -1 if expire_age has an invalid value
+ *
+ */
+int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
+ unsigned int bss_expire_age)
+{
+ if (bss_expire_age < 10) {
+ wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
+ bss_expire_age);
+ return -1;
+ }
+ wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
+ bss_expire_age);
+ wpa_s->conf->bss_expiration_age = bss_expire_age;
+
+ return 0;
+}
+
+
+/**
+ * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @expire_count: number of scans after which an unseen BSS is reclaimed
+ * Returns: 0 if succeed or -1 if expire_count has an invalid value
+ *
+ */
+int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
+ unsigned int bss_expire_count)
+{
+ if (bss_expire_count < 1) {
+ wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
+ bss_expire_count);
+ return -1;
+ }
+ wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
+ bss_expire_count);
+ wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
+
+ return 0;
+}
+
+
/**
* wpa_supplicant_set_debug_params - Set global debug params
* @global: wpa_global structure
int old_level, old_timestamp, old_show_keys;
/* check for allowed debuglevels */
- if (debug_level != MSG_MSGDUMP &&
+ if (debug_level != MSG_EXCESSIVE &&
+ debug_level != MSG_MSGDUMP &&
debug_level != MSG_DEBUG &&
debug_level != MSG_INFO &&
debug_level != MSG_WARNING &&
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) {
if (ieee80211_sta_get_ssid(wpa_s, ssid, &ssid_len)) {
- wpa_printf(MSG_WARNING, "Could not read SSID from "
- "MLME.");
+ wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
+ "MLME");
return NULL;
}
} else {
res = wpa_drv_get_ssid(wpa_s, ssid);
if (res < 0) {
- wpa_printf(MSG_WARNING, "Could not read SSID from "
- "driver.");
+ wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
+ "driver");
return NULL;
}
ssid_len = res;
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
else if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
- wpa_printf(MSG_WARNING, "Could not read BSSID from driver.");
+ wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
+ "driver");
return NULL;
}
{
int i;
size_t len;
- const char *pos;
+ const char *pos, *driver = name;
if (wpa_s == NULL)
return -1;
if (wpa_drivers[0] == NULL) {
- wpa_printf(MSG_ERROR, "No driver interfaces build into "
- "wpa_supplicant.");
+ wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
+ "wpa_supplicant");
return -1;
}
return 0;
}
- pos = os_strchr(name, ',');
- if (pos)
- len = pos - name;
- else
- len = os_strlen(name);
- for (i = 0; wpa_drivers[i]; i++) {
- if (os_strlen(wpa_drivers[i]->name) == len &&
- os_strncmp(name, wpa_drivers[i]->name, len) ==
- 0) {
- wpa_s->driver = wpa_drivers[i];
- wpa_s->global_drv_priv = wpa_s->global->drv_priv[i];
- return 0;
+ do {
+ pos = os_strchr(driver, ',');
+ if (pos)
+ len = pos - driver;
+ else
+ len = os_strlen(driver);
+
+ for (i = 0; wpa_drivers[i]; i++) {
+ if (os_strlen(wpa_drivers[i]->name) == len &&
+ os_strncmp(driver, wpa_drivers[i]->name, len) ==
+ 0) {
+ wpa_s->driver = wpa_drivers[i];
+ wpa_s->global_drv_priv =
+ wpa_s->global->drv_priv[i];
+ return 0;
+ }
}
- }
- wpa_printf(MSG_ERROR, "Unsupported driver '%s'.", name);
+ driver = pos + 1;
+ } while (pos);
+
+ wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
return -1;
}
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
+ 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) {
* association information, lets queue it for processing until
* the association event is received.
*/
- wpa_printf(MSG_DEBUG, "Not associated - Delay processing of "
- "received EAPOL frame");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
+ "of received EAPOL frame");
wpabuf_free(wpa_s->pending_eapol_rx);
wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
if (wpa_s->pending_eapol_rx) {
#endif /* CONFIG_AP */
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
- wpa_printf(MSG_DEBUG, "Ignored received EAPOL frame since "
- "no key management is configured");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
+ "no key management is configured");
return;
}
wpa_s->eapol_received++;
if (wpa_s->countermeasures) {
- wpa_printf(MSG_INFO, "WPA: Countermeasures - dropped EAPOL "
- "packet");
+ wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
+ "EAPOL packet");
return;
}
}
if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
- wpa_printf(MSG_ERROR, "Failed to get own L2 address");
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
return -1;
}
- wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR,
- MAC2STR(wpa_s->own_addr));
+ wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
+ MAC2STR(wpa_s->own_addr));
if (wpa_s->bridge_ifname[0]) {
- wpa_printf(MSG_DEBUG, "Receiving packets from bridge interface"
- " '%s'", wpa_s->bridge_ifname);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
+ "interface '%s'", wpa_s->bridge_ifname);
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);
if (wpa_s->l2_br == NULL) {
- wpa_printf(MSG_ERROR, "Failed to open l2_packet "
- "connection for the bridge interface '%s'",
- wpa_s->bridge_ifname);
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
+ "connection for the bridge interface '%s'",
+ wpa_s->bridge_ifname);
return -1;
}
}
* happen if wpa_supplicant is killed during countermeasures. */
wpa_drv_set_countermeasures(wpa_s, 0);
- wpa_printf(MSG_DEBUG, "RSN: flushing PMKID list in the driver");
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
wpa_drv_flush_pmkid(wpa_s);
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
if (wpa_s == NULL)
return NULL;
wpa_s->scan_req = 1;
+ wpa_s->scan_interval = 5;
wpa_s->new_connection = 1;
wpa_s->parent = wpa_s;
const char *pos;
pos = driver ? os_strchr(driver, ',') : NULL;
if (pos) {
- wpa_printf(MSG_DEBUG, "Failed to initialize driver "
- "interface - try next driver wrapper");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
+ "driver interface - try next driver wrapper");
driver = pos + 1;
goto next_driver;
}
- wpa_printf(MSG_ERROR, "Failed to initialize driver interface");
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
+ "interface");
return -1;
}
if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
- wpa_printf(MSG_ERROR, "Driver interface rejected "
- "driver_param '%s'", wpa_s->conf->driver_param);
+ wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
+ "driver_param '%s'", wpa_s->conf->driver_param);
return -1;
}
ifname = wpa_drv_get_ifname(wpa_s);
if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
- wpa_printf(MSG_DEBUG, "Driver interface replaced interface "
- "name with '%s'", ifname);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
+ "interface name with '%s'", ifname);
os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
}
if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
- wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
- "dot11RSNAConfigPMKLifetime");
+ wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
+ "dot11RSNAConfigPMKLifetime");
return -1;
}
if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
- wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+ wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
"dot11RSNAConfigPMKReauthThreshold");
return -1;
}
if (wpa_s->conf->dot11RSNAConfigSATimeout &&
wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
wpa_s->conf->dot11RSNAConfigSATimeout)) {
- wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
- "dot11RSNAConfigSATimeout");
+ wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
+ "dot11RSNAConfigSATimeout");
return -1;
}
}
wpa_s->max_scan_ssids = capa.max_scan_ssids;
wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
+ wpa_s->max_stations = capa.max_stations;
}
if (wpa_s->max_remain_on_chan == 0)
wpa_s->max_remain_on_chan = 1000;
if (wpa_supplicant_driver_init(wpa_s) < 0)
return -1;
+#ifdef CONFIG_TDLS
+ if (wpa_tdls_init(wpa_s->wpa))
+ return -1;
+#endif /* CONFIG_TDLS */
+
if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
- wpa_printf(MSG_DEBUG, "Failed to set country");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
return -1;
}
return -1;
}
-#ifdef CONFIG_IBSS_RSN
- wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
- if (!wpa_s->ibss_rsn) {
- wpa_printf(MSG_DEBUG, "Failed to init IBSS RSN");
- return -1;
- }
-#endif /* CONFIG_IBSS_RSN */
-
#ifdef CONFIG_P2P
if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
- wpa_printf(MSG_ERROR, "Failed to init P2P");
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
return -1;
}
#endif /* CONFIG_P2P */
wpa_s->next = global->ifaces;
global->ifaces = wpa_s;
- wpa_printf(MSG_DEBUG, "Added interface %s", wpa_s->ifname);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
return wpa_s;
}
prev->next = wpa_s->next;
}
- wpa_printf(MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
if (global->p2p_group_formation == wpa_s)
global->p2p_group_formation = NULL;
}
+/**
+ * wpa_supplicant_get_eap_mode - Get the current EAP mode
+ * @wpa_s: Pointer to the network interface
+ * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
+ */
+const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
+{
+ const char *eapol_method;
+
+ if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+ return "NO-EAP";
+ }
+
+ eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
+ if (eapol_method == NULL)
+ return "UNKNOWN-EAP";
+
+ return eapol_method;
+}
+
+
/**
* wpa_supplicant_get_iface - Get a new network interface
* @global: Pointer to global data from wpa_supplicant_init()
}
+#ifndef CONFIG_NO_WPA_MSG
+static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ if (wpa_s == NULL)
+ return NULL;
+ return wpa_s->ifname;
+}
+#endif /* CONFIG_NO_WPA_MSG */
+
+
/**
* wpa_supplicant_init - Initialize %wpa_supplicant
* @params: Parameters for %wpa_supplicant
if (params == NULL)
return NULL;
+#ifndef CONFIG_NO_WPA_MSG
+ wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
+#endif /* CONFIG_NO_WPA_MSG */
+
wpa_debug_open_file(params->wpa_debug_file_path);
if (params->wpa_debug_syslog)
wpa_debug_open_syslog();
wpa_debug_timestamp = global->params.wpa_debug_timestamp =
params->wpa_debug_timestamp;
+ wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
+
if (eloop_init()) {
wpa_printf(MSG_ERROR, "Failed to initialize event loop");
wpa_supplicant_deinit(global);
return NULL;
}
+ random_init(params->entropy_file);
+
global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
if (global->ctrl_iface == NULL) {
wpa_supplicant_deinit(global);
}
os_free(global->drv_priv);
+ random_deinit();
+
eloop_destroy();
if (global->params.pid_file) {
void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
{
+ if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
+ wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
+ char country[3];
+ country[0] = wpa_s->conf->country[0];
+ country[1] = wpa_s->conf->country[1];
+ country[2] = '\0';
+ if (wpa_drv_set_country(wpa_s, country) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to set country code "
+ "'%s'", country);
+ }
+ }
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
wpa_s->conf->changed_parameters = 0;
}
+
+
+void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
+ size_t num_hw_features)
+{
+ size_t i;
+
+ if (hw_features == NULL)
+ return;
+
+ for (i = 0; i < num_hw_features; i++) {
+ os_free(hw_features[i].channels);
+ os_free(hw_features[i].rates);
+ }
+
+ os_free(hw_features);
+}
+
+
+static void add_freq(int *freqs, int *num_freqs, int freq)
+{
+ int i;
+
+ for (i = 0; i < *num_freqs; i++) {
+ if (freqs[i] == freq)
+ return;
+ }
+
+ freqs[*num_freqs] = freq;
+ (*num_freqs)++;
+}
+
+
+static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss *bss, *cbss;
+ const int max_freqs = 10;
+ int *freqs;
+ int num_freqs = 0;
+
+ freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
+ if (freqs == NULL)
+ return NULL;
+
+ cbss = wpa_s->current_bss;
+
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ if (bss == cbss)
+ continue;
+ if (bss->ssid_len == cbss->ssid_len &&
+ os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
+ wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
+ add_freq(freqs, &num_freqs, bss->freq);
+ if (num_freqs == max_freqs)
+ break;
+ }
+ }
+
+ if (num_freqs == 0) {
+ os_free(freqs);
+ freqs = NULL;
+ }
+
+ return freqs;
+}
+
+
+void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+ int timeout;
+ int count;
+ int *freqs = NULL;
+
+ /*
+ * Add the failed BSSID into the blacklist and speed up next scan
+ * attempt if there could be other APs that could accept association.
+ * The current blacklist count indicates how many times we have tried
+ * connecting to this AP and multiple attempts mean that other APs are
+ * either not available or has already been tried, so that we can start
+ * increasing the delay here to avoid constant scanning.
+ */
+ count = wpa_blacklist_add(wpa_s, bssid);
+ if (count == 1 && wpa_s->current_bss) {
+ /*
+ * This BSS was not in the blacklist before. If there is
+ * another BSS available for the same ESS, we should try that
+ * next. Otherwise, we may as well try this one once more
+ * before allowing other, likely worse, ESSes to be considered.
+ */
+ freqs = get_bss_freqs_in_ess(wpa_s);
+ if (freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
+ "has been seen; try it next");
+ wpa_blacklist_add(wpa_s, bssid);
+ /*
+ * On the next scan, go through only the known channels
+ * used in this ESS based on previous scans to speed up
+ * common load balancing use case.
+ */
+ os_free(wpa_s->next_scan_freqs);
+ wpa_s->next_scan_freqs = freqs;
+ }
+ }
+
+ switch (count) {
+ case 1:
+ timeout = 100;
+ break;
+ case 2:
+ timeout = 500;
+ break;
+ case 3:
+ timeout = 1000;
+ break;
+ default:
+ timeout = 5000;
+ }
+
+ /*
+ * 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));
+}