Cumulative patch from commit efc64886b8a285440e9954b5395a5370d8c5f84f
efc6488 nl80211: Pass station supported channel and oper class info
3ed9727 TDLS: Pass peer's Supported channel and oper class info during sta_add
eed65aa hostapd: DFS setup seg0 correctly for HT40-
25592b2 hostapd: DFS/CSA check if CSA in progress
b19ef32 Android: Remove hostapd dump_file functionality
c48414a P2P: Limit join-a-group scans based on SSID from invitation
78f0c93 Flush secondary device types on FLUSH command
2b38410 P2P: Allow requested device type to be specified with p2p_find
d9bb282 Clear configuration blobs on FLUSH command
c60ba9f Skip network disabling on expected EAP failure
7185e16 EAP-FAST peer: Make debug clearer on missing pac_file configuration
7b88b64 EXT PW: Fix hash return in password fetching
08081ad hostapd: Skip full AP configuration validation on SET command
1785d2e P2P: Wait on GO Negotiation Confirm transmit
472fa21 P2P: Cancel action frame offchan wait after recv GO Neg Conf
bfdc2a3 bsd: Fix NULL pointer dereference on error path
38bbd06 bsd: Prepare event buffer on init process
3043b4f nl80211: Document how to configure for libnl 2.0 and 3.2
Change-Id: Ia592bc948eaa43dbfaf0b4a20231efca61acb11f
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index 08d39e2..7354bbf 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -72,7 +72,8 @@
Device Discovery
p2p_find [timeout in seconds] [type=<social|progressive>] \
- [dev_id=<addr>] [delay=<search delay in ms>]
+ [dev_id=<addr>] [dev_type=<device type>] \
+ [delay=<search delay in ms>]
The default behavior is to run a single full scan in the beginning and
then scan only social channels. type=social will scan only social
@@ -87,6 +88,10 @@
delay to be used between search iterations (e.g., to free up radio
resources for concurrent operations).
+The optional dev_type option can be used to specify a single device type
+(primary or secondary) to search for, e.g.,
+"p2p_find dev_type=1-0050F204-1".
+
p2p_listen [timeout in seconds]
Start Listen-only state (become discoverable without searching for
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 5301ed7..884acf6 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1926,6 +1926,22 @@
}
+void wpa_config_flush_blobs(struct wpa_config *config)
+{
+#ifndef CONFIG_NO_CONFIG_BLOBS
+ struct wpa_config_blob *blob, *prev;
+
+ blob = config->blobs;
+ config->blobs = NULL;
+ while (blob) {
+ prev = blob;
+ blob = blob->next;
+ wpa_config_free_blob(prev);
+ }
+#endif /* CONFIG_NO_CONFIG_BLOBS */
+}
+
+
/**
* wpa_config_free - Free configuration data
* @config: Configuration data from wpa_config_read()
@@ -1935,9 +1951,6 @@
*/
void wpa_config_free(struct wpa_config *config)
{
-#ifndef CONFIG_NO_CONFIG_BLOBS
- struct wpa_config_blob *blob, *prevblob;
-#endif /* CONFIG_NO_CONFIG_BLOBS */
struct wpa_ssid *ssid, *prev = NULL;
struct wpa_cred *cred, *cprev;
@@ -1955,15 +1968,7 @@
wpa_config_free_cred(cprev);
}
-#ifndef CONFIG_NO_CONFIG_BLOBS
- blob = config->blobs;
- prevblob = NULL;
- while (blob) {
- prevblob = blob;
- blob = blob->next;
- wpa_config_free_blob(prevblob);
- }
-#endif /* CONFIG_NO_CONFIG_BLOBS */
+ wpa_config_flush_blobs(config);
wpabuf_free(config->wps_vendor_ext_m1);
os_free(config->ctrl_interface);
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index e24772d..a98a5aa 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -979,6 +979,7 @@
struct wpa_config_blob *blob);
void wpa_config_free_blob(struct wpa_config_blob *blob);
int wpa_config_remove_blob(struct wpa_config *config, const char *name);
+void wpa_config_flush_blobs(struct wpa_config *config);
struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id);
struct wpa_cred * wpa_config_add_cred(struct wpa_config *config);
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index cb299db..de97368 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3652,6 +3652,7 @@
unsigned int timeout = atoi(cmd);
enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
u8 dev_id[ETH_ALEN], *_dev_id = NULL;
+ u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
char *pos;
unsigned int search_delay;
@@ -3668,6 +3669,14 @@
_dev_id = dev_id;
}
+ pos = os_strstr(cmd, "dev_type=");
+ if (pos) {
+ pos += 9;
+ if (wps_dev_type_str2bin(pos, dev_type) < 0)
+ return -1;
+ _dev_type = dev_type;
+ }
+
pos = os_strstr(cmd, "delay=");
if (pos) {
pos += 6;
@@ -3675,8 +3684,8 @@
} else
search_delay = wpas_p2p_search_delay(wpa_s);
- return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id,
- search_delay);
+ return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
+ _dev_id, search_delay);
}
@@ -5252,6 +5261,7 @@
wpas_p2p_service_flush(wpa_s);
wpa_s->global->p2p_disabled = 0;
wpa_s->global->p2p_per_sta_psk = 0;
+ wpa_s->conf->num_sec_device_types = 0;
#endif /* CONFIG_P2P */
#ifdef CONFIG_WPS_TESTING
@@ -5296,6 +5306,7 @@
wpa_s->extra_blacklist_count = 0;
wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
+ wpa_config_flush_blobs(wpa_s->conf);
wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 0627661..6684782 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -31,6 +31,19 @@
# Driver interface for Linux drivers using the nl80211 kernel interface
CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+#CONFIG_LIBNL32=y
+
+
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index cb71475..ac0ab0b 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -365,10 +365,11 @@
}
-static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx)
+static void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
+ void *ctx)
{
struct eapol_test_data *e = ctx;
- printf("eapol_sm_cb: success=%d\n", success);
+ printf("eapol_sm_cb: result=%d\n", result);
e->eapol_test_num_reauths--;
if (e->eapol_test_num_reauths < 0)
eloop_terminate();
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 49c4058..fa265bc 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2551,10 +2551,11 @@
wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated);
- if (reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
- ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
- (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
- eapol_sm_failed(wpa_s->eapol)))
+ if (((reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
+ ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
+ (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
+ eapol_sm_failed(wpa_s->eapol))) &&
+ !wpa_s->eap_expected_failure))
wpas_auth_failed(wpa_s);
#ifdef CONFIG_P2P
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 41d5102..3ac6713 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -104,11 +104,12 @@
wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
int go);
static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
-static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq);
+static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
+ const u8 *ssid, size_t ssid_len);
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
const u8 *dev_addr, enum p2p_wps_method wps_method,
- int auto_join);
+ int auto_join, const u8 *ssid, size_t ssid_len);
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -2868,7 +2869,8 @@
if (!persistent_group) {
wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
- " to join an active group", MAC2STR(sa));
+ " to join an active group (SSID: %s)",
+ MAC2STR(sa), wpa_ssid_txt(ssid, ssid_len));
if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
(os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
== 0 ||
@@ -2991,8 +2993,8 @@
if (status == P2P_SC_SUCCESS) {
wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
- " was accepted; op_freq=%d MHz",
- MAC2STR(sa), op_freq);
+ " was accepted; op_freq=%d MHz, SSID=%s",
+ MAC2STR(sa), op_freq, wpa_ssid_txt(ssid, ssid_len));
if (s) {
int go = s->mode == WPAS_MODE_P2P_GO;
wpas_p2p_group_add_persistent(
@@ -3001,7 +3003,8 @@
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpas_p2p_join(wpa_s, bssid, go_dev_addr,
- wpa_s->p2p_wps_method, 0);
+ wpa_s->p2p_wps_method, 0,
+ ssid, ssid_len);
}
return;
}
@@ -4037,7 +4040,7 @@
static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
- struct wpa_bss *bss;
+ struct wpa_bss *bss = NULL;
int freq;
u8 iface_addr[ETH_ALEN];
@@ -4069,7 +4072,7 @@
MAC2STR(wpa_s->
pending_join_dev_addr),
freq);
- wpas_p2p_join_scan_req(wpa_s, freq);
+ wpas_p2p_join_scan_req(wpa_s, freq, NULL, 0);
return;
}
}
@@ -4142,7 +4145,22 @@
wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
"from P2P peer table: %d MHz", freq);
}
- bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
+ if (wpa_s->p2p_join_ssid_len) {
+ wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
+ MACSTR " and SSID %s",
+ MAC2STR(wpa_s->pending_join_iface_addr),
+ wpa_ssid_txt(wpa_s->p2p_join_ssid,
+ wpa_s->p2p_join_ssid_len));
+ bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
+ wpa_s->p2p_join_ssid,
+ wpa_s->p2p_join_ssid_len);
+ }
+ if (!bss) {
+ wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
+ MACSTR, MAC2STR(wpa_s->pending_join_iface_addr));
+ bss = wpa_bss_get_bssid_latest(wpa_s,
+ wpa_s->pending_join_iface_addr);
+ }
if (bss) {
freq = bss->freq;
wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
@@ -4219,7 +4237,8 @@
}
-static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq)
+static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
+ const u8 *ssid, size_t ssid_len)
{
int ret;
struct wpa_driver_scan_params params;
@@ -4241,8 +4260,16 @@
/* P2P Wildcard SSID */
params.num_ssids = 1;
- params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
- params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+ if (ssid && ssid_len) {
+ params.ssids[0].ssid = ssid;
+ params.ssids[0].ssid_len = ssid_len;
+ os_memcpy(wpa_s->p2p_join_ssid, ssid, ssid_len);
+ wpa_s->p2p_join_ssid_len = ssid_len;
+ } else {
+ params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
+ params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+ wpa_s->p2p_join_ssid_len = 0;
+ }
wpa_s->wps->dev.p2p = 1;
wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
@@ -4299,18 +4326,22 @@
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
- wpas_p2p_join_scan_req(wpa_s, 0);
+ wpas_p2p_join_scan_req(wpa_s, 0, NULL, 0);
}
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
const u8 *dev_addr, enum p2p_wps_method wps_method,
- int auto_join)
+ int auto_join, const u8 *ssid, size_t ssid_len)
{
wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
MACSTR " dev " MACSTR ")%s",
MAC2STR(iface_addr), MAC2STR(dev_addr),
auto_join ? " (auto_join)" : "");
+ if (ssid && ssid_len) {
+ wpa_printf(MSG_DEBUG, "P2P: Group SSID specified: %s",
+ wpa_ssid_txt(ssid, ssid_len));
+ }
wpa_s->p2p_auto_pd = 0;
wpa_s->p2p_auto_join = !!auto_join;
@@ -4322,7 +4353,7 @@
wpas_p2p_stop_find(wpa_s);
wpa_s->p2p_join_scan_count = 0;
- wpas_p2p_join_scan(wpa_s, NULL);
+ wpas_p2p_join_scan_req(wpa_s, 0, ssid, ssid_len);
return 0;
}
@@ -4577,7 +4608,7 @@
}
wpa_s->user_initiated_pd = 1;
if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
- auto_join) < 0)
+ auto_join, NULL, 0) < 0)
return -1;
return ret;
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 187e5d9..78e2749 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1410,6 +1410,7 @@
os_memset(¶ms, 0, sizeof(params));
wpa_s->reassociate = 0;
+ wpa_s->eap_expected_failure = 0;
if (bss && !wpas_driver_bss_selection(wpa_s)) {
#ifdef CONFIG_IEEE80211R
const u8 *ie, *md = NULL;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index d1ea77b..3a28534 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -571,6 +571,7 @@
struct os_reltime pending_eapol_rx_time;
u8 pending_eapol_rx_src[ETH_ALEN];
unsigned int last_eapol_matches_bssid:1;
+ unsigned int eap_expected_failure:1;
struct ibss_rsn *ibss_rsn;
@@ -669,6 +670,8 @@
u8 pending_join_iface_addr[ETH_ALEN];
u8 pending_join_dev_addr[ETH_ALEN];
int pending_join_wps_method;
+ u8 p2p_join_ssid[32];
+ size_t p2p_join_ssid_len;
int p2p_join_scan_count;
int auto_pd_scan_retry;
int force_long_sd;
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index ab6cdca..ad0895b 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -216,20 +216,38 @@
}
-static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
+static const char * result_str(enum eapol_supp_result result)
+{
+ switch (result) {
+ case EAPOL_SUPP_RESULT_FAILURE:
+ return "FAILURE";
+ case EAPOL_SUPP_RESULT_SUCCESS:
+ return "SUCCESS";
+ case EAPOL_SUPP_RESULT_EXPECTED_FAILURE:
+ return "EXPECTED_FAILURE";
+ }
+ return "?";
+}
+
+
+static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
+ enum eapol_supp_result result,
void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
int res, pmk_len;
u8 pmk[PMK_LEN];
- wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
- success ? "" : "un");
+ wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s",
+ result_str(result));
if (wpas_wps_eapol_cb(wpa_s) > 0)
return;
- if (!success) {
+ wpa_s->eap_expected_failure = result ==
+ EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
+
+ if (result != EAPOL_SUPP_RESULT_SUCCESS) {
/*
* Make sure we do not get stuck here waiting for long EAPOL
* timeout if the AP does not disconnect in case of
@@ -238,7 +256,8 @@
wpa_supplicant_req_auth_timeout(wpa_s, 2, 0);
}
- if (!success || !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+ if (result != EAPOL_SUPP_RESULT_SUCCESS ||
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
return;
if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
@@ -560,7 +579,9 @@
const u8 *supp_rates, size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
- u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
+ u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
+ const u8 *supp_channels, size_t supp_channels_len,
+ const u8 *supp_oper_classes, size_t supp_oper_classes_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct hostapd_sta_add_params params;
@@ -588,6 +609,10 @@
params.set = !add;
params.ext_capab = ext_capab;
params.ext_capab_len = ext_capab_len;
+ params.supp_channels = supp_channels;
+ params.supp_channels_len = supp_channels_len;
+ params.supp_oper_classes = supp_oper_classes;
+ params.supp_oper_classes_len = supp_oper_classes_len;
return wpa_drv_sta_add(wpa_s, ¶ms);
}