Cumulative patch from commit 31ded52e7084976c5f84caae6cb55e632dd8b013
31ded52 SME: Add more debug prints for OBSS scans and 20/40 MHz co-ex report
7f8eb34 SME: Fix OBSS scan result processing for 20/40 MHz co-ex report
b7a8d67 Allow hostapd to advertise 40 MHz intolerant HT capability
692ec30 FT: Add support for postponing FT response
6ace13a P2P: Clean up channel selection code to use helper functions
70c3523 WPS: Comment out unused AP WEP config write with WPS 2.0
c3ba70f P2P: Update op_reg_class in random social channel case
70634ee hostapd: Check driver DFS offload capability for channel disablement
65d645c nl80211: Fetch DFS offload capability from driver
a500f31 WPS: Comment out unused AP WEP config update with WPS 2.0
be4e5af Add SAE and FT-SAE key_mgmt to hostapd GET_CONFIG
1d4fe3b Remove unnecessary parameter validation
94b84bc P2P: Avoid unsafe pre-configured channel as channel preference
d3c9c35 Add freq= parameter to 'set pno' command
b998236 dbus: Implement P2P Peers info IEs buffer getter
c6f356f dbus: Export the peer's device address as a property
442adfd dbus: Declare properly ServiceDiscoveryRequest method
8903741 dbus: Cancelling a service request always reply by an error
13494c4 dbus: Remove duplicate signal declaration
513dcec Don't overwrite channel on hostapd config reload
5eae87a P2P: Fix GO failed interface init
c46235a wpa_supplicant: Fix radio_remove_interface
2ce7e4f Android: Enable CONFIG_EAP_AKA_PRIME option
95bf699 Add get_radio_name() driver wrapper for wpa_supplicant
d06ecab D-Bus: Make p2p_no_group_iface configurable
8b6b6d8 Fix hostapd.conf description of HT40+
Change-Id: I5e776f71050a106195a39e96d0c38930a387a806
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 814468d..e1f8b20 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1067,6 +1067,8 @@
conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
if (os_strstr(capab, "[PSMP]"))
conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP;
+ if (os_strstr(capab, "[40-INTOLERANT]"))
+ conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index dbdc8c6..29d5d8b 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -940,6 +940,14 @@
return pos - buf;
pos += ret;
}
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
+ ret = os_snprintf(pos, end - pos, "FT-SAE ");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
@@ -955,6 +963,14 @@
pos += ret;
}
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
+ ret = os_snprintf(pos, end - pos, "SAE ");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
ret = os_snprintf(pos, end - pos, "\n");
if (ret < 0 || ret >= end - pos)
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 23ee1e5..b5770a4 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -453,7 +453,7 @@
# LDPC coding capability: [LDPC] = supported
# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz
-# with secondary channel below the primary channel
+# with secondary channel above the primary channel
# (20 MHz only if neither is set)
# Note: There are limits on which channels can be used with HT40- and
# HT40+. Following table shows the channels that may be available for
@@ -481,6 +481,7 @@
# set)
# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)
# PSMP support: [PSMP] (disabled if not set)
+# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set)
# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 11351c4..e1020a6 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -469,9 +469,6 @@
{
char *end;
- if (!settings)
- return -1;
-
os_memset(settings, 0, sizeof(*settings));
settings->cs_count = strtol(pos, &end, 10);
if (pos == end) {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 4ed718c..2ecaec8 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -171,6 +171,16 @@
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
hapd->iconf = newconf;
+ hapd->iconf->channel = oldconf->channel;
+ hapd->iconf->ieee80211n = oldconf->ieee80211n;
+ hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
+ hapd->iconf->ht_capab = oldconf->ht_capab;
+ hapd->iconf->vht_capab = oldconf->vht_capab;
+ hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth;
+ hapd->iconf->vht_oper_centr_freq_seg0_idx =
+ oldconf->vht_oper_centr_freq_seg0_idx;
+ hapd->iconf->vht_oper_centr_freq_seg1_idx =
+ oldconf->vht_oper_centr_freq_seg1_idx;
hapd->conf = newconf->bss[j];
hostapd_reload_bss(hapd);
}
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index d319ce0..54a79b0 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -111,10 +111,13 @@
if ((feature->channels[j].flag &
HOSTAPD_CHAN_RADAR) && dfs_enabled) {
dfs = 1;
- } else if (feature->channels[j].flag &
- (HOSTAPD_CHAN_NO_IBSS |
- HOSTAPD_CHAN_PASSIVE_SCAN |
- HOSTAPD_CHAN_RADAR)) {
+ } else if (((feature->channels[j].flag &
+ HOSTAPD_CHAN_RADAR) &&
+ !(iface->drv_flags &
+ WPA_DRIVER_FLAGS_DFS_OFFLOAD)) ||
+ (feature->channels[j].flag &
+ (HOSTAPD_CHAN_NO_IBSS |
+ HOSTAPD_CHAN_PASSIVE_SCAN))) {
feature->channels[j].flag |=
HOSTAPD_CHAN_DISABLED;
}
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 4d19bb0..77e7858 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -621,6 +621,7 @@
}
#ifdef CONFIG_IEEE80211R
os_free(sm->assoc_resp_ftie);
+ wpabuf_free(sm->ft_pending_req_ies);
#endif /* CONFIG_IEEE80211R */
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 3ab3e3d..929a253 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -42,6 +42,7 @@
#define FT_R0KH_R1KH_PULL_DATA_LEN 44
#define FT_R0KH_R1KH_RESP_DATA_LEN 76
#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
+#define FT_R0KH_R1KH_PULL_NONCE_LEN 16
struct ft_r0kh_r1kh_pull_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
@@ -49,7 +50,7 @@
le16 data_length; /* little endian length of data (44) */
u8 ap_address[ETH_ALEN];
- u8 nonce[16];
+ u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
u8 r1kh_id[FT_R1KH_ID_LEN];
u8 s1kh_id[ETH_ALEN];
@@ -63,7 +64,7 @@
le16 data_length; /* little endian length of data (76) */
u8 ap_address[ETH_ALEN];
- u8 nonce[16]; /* copied from pull */
+ u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
u8 s1kh_id[ETH_ALEN]; /* copied from pull */
u8 pmk_r1[PMK_LEN];
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index c22c4cc..7701596 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1,6 +1,6 @@
/*
* hostapd - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,6 +9,7 @@
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "crypto/aes_wrap.h"
@@ -22,6 +23,12 @@
#ifdef CONFIG_IEEE80211R
+static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
+ const u8 *current_ap, const u8 *sta_addr,
+ u16 status, const u8 *resp_ies,
+ size_t resp_ies_len);
+
+
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
const u8 *data, size_t data_len)
{
@@ -293,22 +300,25 @@
}
-static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
- const u8 *s1kh_id, const u8 *r0kh_id,
- size_t r0kh_id_len, const u8 *pmk_r0_name)
+static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
+ const u8 *ies, size_t ies_len,
+ const u8 *pmk_r0_name)
{
struct ft_remote_r0kh *r0kh;
struct ft_r0kh_r1kh_pull_frame frame, f;
- r0kh = wpa_auth->conf.r0kh_list;
+ r0kh = sm->wpa_auth->conf.r0kh_list;
while (r0kh) {
- if (r0kh->id_len == r0kh_id_len &&
- os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0)
+ if (r0kh->id_len == sm->r0kh_id_len &&
+ os_memcmp(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) == 0)
break;
r0kh = r0kh->next;
}
- if (r0kh == NULL)
+ if (r0kh == NULL) {
+ wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
+ sm->r0kh_id, sm->r0kh_id_len);
return -1;
+ }
wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
"address " MACSTR, MAC2STR(r0kh->addr));
@@ -317,25 +327,32 @@
frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
frame.packet_type = FT_PACKET_R0KH_R1KH_PULL;
frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN);
- os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);
+ os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN);
/* aes_wrap() does not support inplace encryption, so use a temporary
* buffer for the data. */
- if (random_get_bytes(f.nonce, sizeof(f.nonce))) {
+ if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) {
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
"nonce");
return -1;
}
+ os_memcpy(sm->ft_pending_pull_nonce, f.nonce,
+ FT_R0KH_R1KH_PULL_NONCE_LEN);
os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
- os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
- os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
+ os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
+ os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
os_memset(f.pad, 0, sizeof(f.pad));
if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
f.nonce, frame.nonce) < 0)
return -1;
- wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
+ wpabuf_free(sm->ft_pending_req_ies);
+ sm->ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
+ if (sm->ft_pending_req_ies == NULL)
+ return -1;
+
+ wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
return 0;
}
@@ -777,7 +794,7 @@
}
-static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
+static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
const u8 *ies, size_t ies_len,
u8 **resp_ies, size_t *resp_ies_len)
{
@@ -848,19 +865,13 @@
if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1,
&pairwise) < 0) {
- if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id,
- sm->r0kh_id_len, parse.rsn_pmkid) < 0) {
+ if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) {
wpa_printf(MSG_DEBUG, "FT: Did not have matching "
"PMK-R1 and unknown R0KH-ID");
return WLAN_STATUS_INVALID_PMKID;
}
- /*
- * TODO: Should return "status pending" (and the caller should
- * not send out response now). The real response will be sent
- * once the response from R0KH is received.
- */
- return WLAN_STATUS_INVALID_PMKID;
+ return -1; /* Status pending */
}
wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN);
@@ -940,6 +951,7 @@
u16 status;
u8 *resp_ies;
size_t resp_ies_len;
+ int res;
if (sm == NULL) {
wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but "
@@ -950,8 +962,16 @@
wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR
" BSSID=" MACSTR " transaction=%d",
MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);
- status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
- &resp_ies_len);
+ sm->ft_pending_cb = cb;
+ sm->ft_pending_cb_ctx = ctx;
+ sm->ft_pending_auth_transaction = auth_transaction;
+ res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
+ &resp_ies_len);
+ if (res < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Callback postponed until response is available");
+ return;
+ }
+ status = res;
wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR
" auth_transaction=%d status=%d",
@@ -1182,15 +1202,27 @@
}
+static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
+ u16 auth_transaction, u16 resp,
+ const u8 *ies, size_t ies_len)
+{
+ struct wpa_state_machine *sm = ctx;
+ wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR,
+ MAC2STR(sm->addr));
+ wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr,
+ WLAN_STATUS_SUCCESS, ies, ies_len);
+}
+
+
static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
const u8 *current_ap, const u8 *sta_addr,
const u8 *body, size_t len)
{
struct wpa_state_machine *sm;
u16 status;
- u8 *resp_ies, *pos;
- size_t resp_ies_len, rlen;
- struct ft_rrb_frame *frame;
+ u8 *resp_ies;
+ size_t resp_ies_len;
+ int res;
sm = wpa_ft_add_sta(wpa_auth, sta_addr);
if (sm == NULL) {
@@ -1201,8 +1233,33 @@
wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len);
- status = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
- &resp_ies_len);
+ sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb;
+ sm->ft_pending_cb_ctx = sm;
+ os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN);
+ res = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
+ &resp_ies_len);
+ if (res < 0) {
+ wpa_printf(MSG_DEBUG, "FT: No immediate response available - wait for pull response");
+ return 0;
+ }
+ status = res;
+
+ res = wpa_ft_send_rrb_auth_resp(sm, current_ap, sta_addr, status,
+ resp_ies, resp_ies_len);
+ os_free(resp_ies);
+ return res;
+}
+
+
+static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
+ const u8 *current_ap, const u8 *sta_addr,
+ u16 status, const u8 *resp_ies,
+ size_t resp_ies_len)
+{
+ struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+ size_t rlen;
+ struct ft_rrb_frame *frame;
+ u8 *pos;
wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR
" CurrentAP=" MACSTR " status=%d",
@@ -1218,10 +1275,8 @@
rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len;
frame = os_malloc(sizeof(*frame) + rlen);
- if (frame == NULL) {
- os_free(resp_ies);
+ if (frame == NULL)
return -1;
- }
frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
frame->packet_type = FT_PACKET_RESPONSE;
frame->action_length = host_to_le16(rlen);
@@ -1235,10 +1290,8 @@
pos += ETH_ALEN;
WPA_PUT_LE16(pos, status);
pos += 2;
- if (resp_ies) {
+ if (resp_ies)
os_memcpy(pos, resp_ies, resp_ies_len);
- os_free(resp_ies);
- }
wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame,
sizeof(*frame) + rlen);
@@ -1290,7 +1343,7 @@
f.nonce, sizeof(f.nonce));
wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
f.pmk_r0_name, WPA_PMK_NAME_LEN);
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
os_memset(&resp, 0, sizeof(resp));
@@ -1333,13 +1386,58 @@
}
+static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_state_machine *sm = eloop_ctx;
+ int res;
+ u8 *resp_ies;
+ size_t resp_ies_len;
+ u16 status;
+
+ res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies),
+ wpabuf_len(sm->ft_pending_req_ies),
+ &resp_ies, &resp_ies_len);
+ wpabuf_free(sm->ft_pending_req_ies);
+ sm->ft_pending_req_ies = NULL;
+ if (res < 0)
+ res = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ status = res;
+ wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
+ " - status %u", MAC2STR(sm->addr), status);
+
+ sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr,
+ sm->ft_pending_auth_transaction + 1, status,
+ resp_ies, resp_ies_len);
+ os_free(resp_ies);
+}
+
+
+static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
+{
+ struct ft_r0kh_r1kh_resp_frame *frame = ctx;
+
+ if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0)
+ return 0;
+ if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce,
+ FT_R0KH_R1KH_PULL_NONCE_LEN) != 0)
+ return 0;
+ if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for "
+ MACSTR " - process from timeout", MAC2STR(sm->addr));
+ eloop_register_timeout(0, 0, ft_pull_resp_cb_finish, sm, NULL);
+ return 1;
+}
+
+
static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
const u8 *data, size_t data_len)
{
struct ft_r0kh_r1kh_resp_frame *frame, f;
struct ft_remote_r0kh *r0kh;
- int pairwise;
+ int pairwise, res;
wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
@@ -1376,14 +1474,10 @@
return -1;
}
- /* TODO: verify that <nonce,s1kh_id> matches with a pending request
- * and call this requests callback function to finish request
- * processing */
-
pairwise = le_to_host16(f.pairwise);
wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
f.nonce, sizeof(f.nonce));
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
MACSTR " pairwise=0x%x",
MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
@@ -1391,11 +1485,13 @@
wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
f.pmk_r1_name, WPA_PMK_NAME_LEN);
- wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
- pairwise);
+ res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
+ pairwise);
+ wpa_printf(MSG_DEBUG, "FT: Look for pending pull request");
+ wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &f);
os_memset(f.pmk_r1, 0, PMK_LEN);
- return 0;
+ return res ? 0 : -1;
}
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 2e1bdcf..6960ff3 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -118,6 +118,15 @@
u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
* message 2/4 */
u8 *assoc_resp_ftie;
+
+ void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid,
+ u16 auth_transaction, u16 status,
+ const u8 *ies, size_t ies_len);
+ void *ft_pending_cb_ctx;
+ struct wpabuf *ft_pending_req_ies;
+ u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
+ u8 ft_pending_auth_transaction;
+ u8 ft_pending_current_ap[ETH_ALEN];
#endif /* CONFIG_IEEE80211R */
int pending_1_of_4_timeout;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 62cd03c..e0033ce 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -378,6 +378,13 @@
}
bss->auth_algs = 1;
} else {
+#ifdef CONFIG_WPS2
+ /*
+ * WPS 2.0 does not allow WEP to be configured, so no need to
+ * process that option here either.
+ */
+ bss->auth_algs = 1;
+#else /* CONFIG_WPS2 */
if ((cred->auth_type & WPS_AUTH_OPEN) &&
(cred->auth_type & WPS_AUTH_SHARED))
bss->auth_algs = 3;
@@ -412,6 +419,7 @@
}
wep->keys_set = 1;
}
+#endif /* CONFIG_WPS2 */
}
/* Schedule configuration reload after short period of time to allow
@@ -586,6 +594,13 @@
fprintf(nconf, "auth_algs=1\n");
} else {
+#ifdef CONFIG_WPS2
+ /*
+ * WPS 2.0 does not allow WEP to be configured, so no need to
+ * process that option here either.
+ */
+ fprintf(nconf, "auth_algs=1\n");
+#else /* CONFIG_WPS2 */
if ((cred->auth_type & WPS_AUTH_OPEN) &&
(cred->auth_type & WPS_AUTH_SHARED))
fprintf(nconf, "auth_algs=3\n");
@@ -611,6 +626,7 @@
}
fprintf(nconf, "\n");
}
+#endif /* CONFIG_WPS2 */
}
fprintf(nconf, "# WPS configuration - END\n");
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 0d83920..80bad4f 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -29,12 +29,16 @@
* ranges to avoid to reduce issues due to interference or internal
* co-existence information in the driver. The event data structure is
* defined in struct qca_avoid_freq_list.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support
+ * for DFS offloading.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
QCA_NL80211_VENDOR_SUBCMD_TEST = 1,
/* subcmds 2..9 not yet allocated */
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11,
};
@@ -48,4 +52,13 @@
struct qca_avoid_freq_range range[0];
} STRUCT_PACKED;
+enum qca_wlan_vendor_attr {
+ QCA_WLAN_VENDOR_ATTR_INVALID = 0,
+ /* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */
+ QCA_WLAN_VENDOR_ATTR_DFS = 1,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2eafc14..5935273 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -897,7 +897,8 @@
#define WPA_DRIVER_FLAGS_DRIVER_IE 0x00000001
/* Driver needs static WEP key setup after association command */
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
-/* unused: 0x00000004 */
+/* Driver takes care of all DFS operations */
+#define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004
/* Driver takes care of RSN 4-way handshake internally; PMK is configured with
* struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index dcd002e..c3449ac 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -303,6 +303,7 @@
unsigned int start_iface_up:1;
unsigned int test_use_roc_tx:1;
unsigned int ignore_deauth_event:1;
+ unsigned int dfs_vendor_cmd_avail:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
@@ -3725,6 +3726,10 @@
continue;
}
vinfo = nla_data(nl);
+ if (vinfo->subcmd ==
+ QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)
+ drv->dfs_vendor_cmd_avail = 1;
+
wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
vinfo->vendor_id, vinfo->subcmd);
}
@@ -8889,11 +8894,44 @@
}
+static int dfs_info_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ int *dfs_capability_ptr = arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
+ nla_data(nl_vend), nla_len(nl_vend), NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]) {
+ u32 val;
+ val = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]);
+ wpa_printf(MSG_DEBUG, "nl80211: DFS offload capability: %u",
+ val);
+ *dfs_capability_ptr = val;
+ }
+ }
+
+ return NL_SKIP;
+}
+
+
static int wpa_driver_nl80211_get_capa(void *priv,
struct wpa_driver_capa *capa)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int dfs_capability = 0;
+ int ret = 0;
+
if (!drv->has_capability)
return -1;
os_memcpy(capa, &drv->capa, sizeof(*capa));
@@ -8909,7 +8947,31 @@
capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
}
- return 0;
+ if (drv->dfs_vendor_cmd_avail == 1) {
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA);
+ NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY);
+
+ ret = send_and_recv_msgs(drv, msg, dfs_info_handler,
+ &dfs_capability);
+ if (!ret) {
+ if (dfs_capability)
+ capa->flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
+ }
+ }
+
+ return ret;
+
+ nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index c5bf41f..a1325d3 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1208,10 +1208,25 @@
0) {
p2p_dbg(p2p, "Select possible 5 GHz channel (op_class %u channel %u) as operating channel preference",
p2p->op_reg_class, p2p->op_channel);
- } else {
+ } else if (p2p_channels_includes(&p2p->cfg->channels,
+ p2p->cfg->op_reg_class,
+ p2p->cfg->op_channel)) {
p2p_dbg(p2p, "Select pre-configured channel as operating channel preference");
p2p->op_reg_class = p2p->cfg->op_reg_class;
p2p->op_channel = p2p->cfg->op_channel;
+ } else if (p2p_channel_random_social(&p2p->cfg->channels,
+ &p2p->op_reg_class,
+ &p2p->op_channel) == 0) {
+ p2p_dbg(p2p, "Select random available social channel %d from 2.4 GHz band as operating channel preference",
+ p2p->op_channel);
+ } else {
+ /* Select any random available channel from the first available
+ * operating class */
+ p2p_channel_select(&p2p->cfg->channels, NULL,
+ &p2p->op_reg_class,
+ &p2p->op_channel);
+ p2p_dbg(p2p, "Select random available channel %d from operating class %d as operating channel preference",
+ p2p->op_channel, p2p->op_reg_class);
}
os_memcpy(&p2p->channels, &p2p->cfg->channels,
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 420c739..8c225ec 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -592,6 +592,8 @@
const struct p2p_channels *chan);
int p2p_channel_select(struct p2p_channels *chans, const int *classes,
u8 *op_class, u8 *op_channel);
+int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
+ u8 *op_channel);
/* p2p_parse.c */
int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg);
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 161a402..de47c12 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -441,31 +441,65 @@
}
+static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels)
+{
+ unsigned int r;
+ os_get_random((u8 *) &r, sizeof(r));
+ r %= num_channels;
+ return channels[r];
+}
+
+
int p2p_channel_select(struct p2p_channels *chans, const int *classes,
u8 *op_class, u8 *op_channel)
{
- unsigned int i, j, r;
+ unsigned int i, j;
- for (j = 0; classes[j]; j++) {
+ for (j = 0; classes == NULL || classes[j]; j++) {
for (i = 0; i < chans->reg_classes; i++) {
struct p2p_reg_class *c = &chans->reg_class[i];
if (c->channels == 0)
continue;
- if (c->reg_class == classes[j]) {
+ if (classes == NULL || c->reg_class == classes[j]) {
/*
* Pick one of the available channels in the
* operating class at random.
*/
- os_get_random((u8 *) &r, sizeof(r));
- r %= c->channels;
*op_class = c->reg_class;
- *op_channel = c->channel[r];
+ *op_channel = p2p_channel_pick_random(
+ c->channel, c->channels);
return 0;
}
}
+ if (classes == NULL)
+ break;
}
return -1;
}
+
+
+int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
+ u8 *op_channel)
+{
+ u8 chan[3];
+ unsigned int num_channels = 0;
+
+ /* Try to find available social channels from 2.4 GHz */
+ if (p2p_channels_includes(chans, 81, 1))
+ chan[num_channels++] = 1;
+ if (p2p_channels_includes(chans, 81, 6))
+ chan[num_channels++] = 6;
+ if (p2p_channels_includes(chans, 81, 11))
+ chan[num_channels++] = 11;
+
+ if (num_channels == 0)
+ return -1;
+
+ *op_class = 81;
+ *op_channel = p2p_channel_pick_random(chan, num_channels);
+
+ return 0;
+}
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 184b41e..7c80528 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -123,7 +123,7 @@
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
# This requires CONFIG_EAP_AKA to be enabled, too.
-#CONFIG_EAP_AKA_PRIME=y
+CONFIG_EAP_AKA_PRIME=y
# Enable USIM simulator (Milenage) for EAP-AKA
#CONFIG_USIM_SIMULATOR=y
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 87ed3e2..704caa1 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -46,6 +46,8 @@
char *buf, int len);
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
char *buf, int len);
+static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
+ char *val);
static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
{
@@ -245,6 +247,33 @@
}
#endif /* CONFIG_NO_CONFIG_BLOBS */
+
+static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ char *params;
+ char *pos;
+ int *freqs = NULL;
+ int ret;
+
+ if (atoi(cmd)) {
+ params = os_strchr(cmd, ' ');
+ os_free(wpa_s->manual_sched_scan_freqs);
+ if (params) {
+ params++;
+ pos = os_strstr(params, "freq=");
+ if (pos)
+ freqs = freq_range_to_channel_list(wpa_s,
+ pos + 5);
+ }
+ wpa_s->manual_sched_scan_freqs = freqs;
+ ret = wpas_start_pno(wpa_s);
+ } else {
+ ret = wpas_stop_pno(wpa_s);
+ }
+ return ret;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
@@ -328,10 +357,7 @@
wpa_tdls_enable(wpa_s->wpa, !disabled);
#endif /* CONFIG_TDLS */
} else if (os_strcasecmp(cmd, "pno") == 0) {
- if (atoi(value))
- ret = wpas_start_pno(wpa_s);
- else
- ret = wpas_stop_pno(wpa_s);
+ ret = wpas_ctrl_pno(wpa_s, value);
} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
int disabled = atoi(value);
if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 5e02956..a0653f0 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2649,6 +2649,7 @@
(WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
{
{ "args", "a{sv}", ARG_IN },
+ { "ref", "t", ARG_OUT },
END_ARGS
}
},
@@ -2679,13 +2680,6 @@
END_ARGS
}
},
- { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
- (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
- {
- { "arg", "i", ARG_IN },
- END_ARGS
- }
- },
{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
(WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
{
@@ -3280,6 +3274,10 @@
wpas_dbus_getter_p2p_peer_ies,
NULL
},
+ { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
+ wpas_dbus_getter_p2p_peer_device_address,
+ NULL
+ },
{ NULL, NULL, NULL, NULL, NULL }
};
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 2b83637..7857bfd 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -825,6 +825,11 @@
wpa_s->conf->disassoc_low_ack))
goto err_no_mem;
+ /* No Group Iface */
+ if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
+ wpa_s->conf->p2p_no_group_iface))
+ goto err_no_mem;
+
if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
!dbus_message_iter_close_container(iter, &variant_iter))
goto err_no_mem;
@@ -974,6 +979,9 @@
else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
entry.type == DBUS_TYPE_UINT32)
wpa_s->conf->disassoc_low_ack = entry.uint32_value;
+ else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN)
+ wpa_s->conf->p2p_no_group_iface = entry.bool_value;
else
goto error;
@@ -1470,12 +1478,46 @@
dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
DBusError *error, void *user_data)
{
- dbus_bool_t success;
- /* struct peer_handler_args *peer_args = user_data; */
+ struct peer_handler_args *peer_args = user_data;
+ const struct p2p_peer_info *info;
- success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
- NULL, 0, error);
- return success;
+ info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+ peer_args->p2p_device_addr, 0);
+ if (info == NULL) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "failed to find peer");
+ return FALSE;
+ }
+
+ if (info->wfd_subelems == NULL)
+ return wpas_dbus_simple_array_property_getter(iter,
+ DBUS_TYPE_BYTE,
+ NULL, 0, error);
+
+ return wpas_dbus_simple_array_property_getter(
+ iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
+ info->wfd_subelems->used, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
+ DBusError *error,
+ void *user_data)
+{
+ struct peer_handler_args *peer_args = user_data;
+ const struct p2p_peer_info *info;
+
+ info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+ peer_args->p2p_device_addr, 0);
+ if (info == NULL) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "failed to find peer");
+ return FALSE;
+ }
+
+ return wpas_dbus_simple_array_property_getter(
+ iter, DBUS_TYPE_BYTE, (char *) peer_args->p2p_device_addr,
+ ETH_ALEN, error);
}
@@ -2407,7 +2449,7 @@
if (req == 0)
goto error;
- if (!wpas_p2p_sd_cancel_request(wpa_s, req))
+ if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
goto error;
return NULL;
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
index a11b3c8..67e0e9d 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
@@ -147,6 +147,10 @@
DBusError *error,
void *user_data);
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
+ DBusError *error,
+ void *user_data);
+
/*
* P2P Group properties
*/
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index b336afb..bbcd662 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -206,6 +206,14 @@
return NULL;
}
+static inline const char *
+wpa_driver_get_radio_name(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->driver->get_radio_name)
+ return wpa_s->driver->get_radio_name(wpa_s->drv_priv);
+ return NULL;
+}
+
static inline const u8 * wpa_drv_get_mac_addr(struct wpa_supplicant *wpa_s)
{
if (wpa_s->driver->get_mac_addr) {
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 487d44d..6f9f217 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1622,6 +1622,9 @@
wpas_p2p_init_group_interface(wpa_s, res->role_go);
if (group_wpa_s == NULL) {
wpas_p2p_remove_pending_group_interface(wpa_s);
+ eloop_cancel_timeout(wpas_p2p_long_listen_timeout,
+ wpa_s, NULL);
+ wpas_p2p_group_formation_failed(wpa_s);
return;
}
if (group_wpa_s != wpa_s) {
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 1d8e8a6..48e94b6 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1923,6 +1923,11 @@
interval = wpa_s->conf->sched_scan_interval ?
wpa_s->conf->sched_scan_interval : 10;
+ if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
+ params.freqs = wpa_s->manual_sched_scan_freqs;
+ }
+
ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval);
os_free(params.filter_ssids);
if (ret == 0)
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 63beaef..f01844e 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -968,8 +968,11 @@
struct ieee80211_2040_intol_chan_report *ic_report;
struct wpabuf *buf;
- wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR,
- MAC2STR(wpa_s->bssid));
+ wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
+ " (num_channels=%u num_intol=%u)",
+ MAC2STR(wpa_s->bssid), num_channels, num_intol);
+ wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
+ chan_list, num_channels);
buf = wpabuf_alloc(2 + /* action.category + action_code */
sizeof(struct ieee80211_2040_bss_coex_ie) +
@@ -1051,8 +1054,14 @@
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
+ wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
+ " freq=%u chan=%u ht_cap=0x%x",
+ MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
+ if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
+ num_intol++;
+
/* Check whether the channel is already considered */
for (i = 0; i < num_channels; i++) {
if (channel == chan_list[i])
@@ -1061,9 +1070,6 @@
if (i != num_channels)
continue;
- if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
- num_intol++;
-
chan_list[num_channels++] = channel;
}
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 499dcb3..dce1c00 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -460,6 +460,9 @@
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
+ os_free(wpa_s->manual_sched_scan_freqs);
+ wpa_s->manual_sched_scan_freqs = NULL;
+
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
@@ -3204,15 +3207,13 @@
wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
wpa_s->ifname, radio->name);
dl_list_del(&wpa_s->radio_list);
- if (!dl_list_empty(&radio->ifaces)) {
- wpa_s->radio = NULL;
+ radio_remove_works(wpa_s, NULL, 0);
+ wpa_s->radio = NULL;
+ if (!dl_list_empty(&radio->ifaces))
return; /* Interfaces remain for this radio */
- }
wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
- radio_remove_works(wpa_s, NULL, 0);
eloop_cancel_timeout(radio_start_next_work, radio, NULL);
- wpa_s->radio = NULL;
os_free(radio);
}
@@ -3361,10 +3362,7 @@
os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
}
- if (wpa_s->driver->get_radio_name)
- rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
- else
- rn = NULL;
+ rn = wpa_driver_get_radio_name(wpa_s);
if (rn && rn[0] == '\0')
rn = NULL;
@@ -4534,7 +4532,7 @@
}
/* If get_radio_name is not supported, use only the local freq */
- if (!wpa_s->driver->get_radio_name) {
+ if (!wpa_driver_get_radio_name(wpa_s)) {
freq = wpa_drv_shared_freq(wpa_s);
if (freq > 0 && idx < len &&
(idx == 0 || freq_array[0] != freq))
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 739b11f..8a33286 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -547,6 +547,7 @@
int scan_runs; /* number of scan runs since WPS was started */
int *next_scan_freqs;
int *manual_scan_freqs;
+ int *manual_sched_scan_freqs;
unsigned int manual_scan_passive:1;
unsigned int manual_scan_use_id:1;
unsigned int manual_scan_only_new:1;