Accumulative patch from commit 932659696e2755bb1ecd6a27e1968fd27eef4948
9326596 nl80211: Remove unused WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT
0d08efa P2P: Use the number of concurrent channels in P2P flows
a21816a Use wpa_drv_shared_freq() if get_radio_name() is not supported
53c5dfc Change share_vif_oper_freq() to handle multiple freqs
4752147 nl80211: Report the number of concurrent support channels
d7df0fa Clean up wpa_supplicant_event() with deauth/disassoc helper functions
fd9f170 Remove unnecessary nested ifdef CONFIG_AP
13adc57 IBSS RSN: Add peer restart detection
b21990b nl80211: Register for AUTH frames when joining an IBSS network
c91f796 nl80211: Support not specifying the frame frequency
ec384c5 IBSS RSN: Fix disconnect() with internal SME
ed07764 nl80211: Remove redundant assignment of ifindex
4ed8d95 TDLS: Tear down TDLS using wpas_drv_tlds_oper() if not external
831770b Cancel delayed scheduled scan when wpa_supplicant cleans up
69dd296 WDS: Fix WEP usage with nl80211 wds_sta=1
c8ebeda wpa_supplicant: Add support for VHT BSS membership selector
3f9a813 hostapd: Add a config option to control beaconing
182b2e5 Add missing host_to_le32() for big endian hosts
3f53c00 nl80211: Ignore disconnect event in case of locally generated request
Change-Id: Ia7368e71ae40966a92970ac82b002c09a7971d41
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index a744ba6..c9b2599 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -243,6 +243,7 @@
int num_deny_mac;
int wds_sta;
int isolate;
+ int start_disabled;
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 8205d13..3072562 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -296,19 +296,19 @@
}
-int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
- int val)
+int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
+ const u8 *addr, int aid, int val)
{
const char *bridge = NULL;
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
- return 0;
+ return -1;
if (hapd->conf->wds_bridge[0])
bridge = hapd->conf->wds_bridge;
else if (hapd->conf->bridge[0])
bridge = hapd->conf->bridge;
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
- bridge);
+ bridge, ifname_wds);
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 70fab55..cfc30ce 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -31,8 +31,8 @@
int enabled);
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
-int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
- int val);
+int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
+ const u8 *addr, int aid, int val);
int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 780b2e2..ac67001 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -806,7 +806,8 @@
return -1;
}
- ieee802_11_set_beacon(hapd);
+ if (!hapd->conf->start_disabled)
+ ieee802_11_set_beacon(hapd);
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
return -1;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 5503af1..35282af 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1818,6 +1818,30 @@
}
+static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ char *ifname_wds)
+{
+ int i;
+ struct hostapd_ssid *ssid = sta->ssid;
+
+ if (hapd->conf->ieee802_1x || hapd->conf->wpa)
+ return;
+
+ for (i = 0; i < 4; i++) {
+ if (ssid->wep.key[i] &&
+ hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
+ i == ssid->wep.idx, NULL, 0,
+ ssid->wep.key[i], ssid->wep.len[i])) {
+ wpa_printf(MSG_WARNING,
+ "Could not set WEP keys for WDS interface; %s",
+ ifname_wds);
+ break;
+ }
+ }
+}
+
+
static void handle_assoc_cb(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len, int reassoc, int ok)
@@ -1920,8 +1944,15 @@
goto fail;
}
- if (sta->flags & WLAN_STA_WDS)
- hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1);
+ if (sta->flags & WLAN_STA_WDS) {
+ int ret;
+ char ifname_wds[IFNAMSIZ + 1];
+
+ ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
+ sta->aid, 1);
+ if (!ret)
+ hostapd_set_wds_encryption(hapd, sta, ifname_wds);
+ }
if (sta->eapol_sm == NULL) {
/*
@@ -2162,11 +2193,18 @@
return;
if (wds && !(sta->flags & WLAN_STA_WDS)) {
+ int ret;
+ char ifname_wds[IFNAMSIZ + 1];
+
wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
"STA " MACSTR " (aid %u)",
MAC2STR(sta->addr), sta->aid);
sta->flags |= WLAN_STA_WDS;
- hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1);
+ ret = hostapd_set_wds_sta(hapd, ifname_wds,
+ sta->addr, sta->aid, 1);
+ if (!ret)
+ hostapd_set_wds_encryption(hapd, sta,
+ ifname_wds);
}
return;
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 833f1b2..21235f2 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -129,7 +129,7 @@
ap_sta_set_authorized(hapd, sta, 0);
if (sta->flags & WLAN_STA_WDS)
- hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
+ hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
if (!(sta->flags & WLAN_STA_PREAUTH))
hostapd_drv_sta_remove(hapd, sta->addr);
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 0604fef..160ac0c 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -61,6 +61,7 @@
};
#define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
+#define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1)
/**
* struct hostapd_hw_modes - Supported hardware mode information
@@ -832,8 +833,7 @@
#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400
/* This interface is P2P capable (P2P GO or P2P Client) */
#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800
-/* Driver supports concurrent operations on multiple channels */
-#define WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT 0x00001000
+/* unused: 0x00001000 */
/*
* Driver uses the initial interface for P2P management interface and non-P2P
* purposes (e.g., connect to infra AP), but this interface cannot be used for
@@ -911,6 +911,11 @@
unsigned int max_acl_mac_addrs;
/**
+ * Number of supported concurrent channels
+ */
+ unsigned int num_multichan_concurrent;
+
+ /**
* extended_capa - extended capabilities in driver/device
*
* Must be allocated and freed by driver and the pointers must be
@@ -2049,10 +2054,12 @@
* @val: 1 = bind to 4-address WDS; 0 = unbind
* @bridge_ifname: Bridge interface to use for the WDS station or %NULL
* to indicate that bridge is not to be used
+ * @ifname_wds: Buffer to return the interface name for the new WDS
+ * station or %NULL to indicate name is not returned.
* Returns: 0 on success, -1 on failure
*/
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val,
- const char *bridge_ifname);
+ const char *bridge_ifname, char *ifname_wds);
/**
* send_action - Transmit an Action frame
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index bcd0a94..eaecc36 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -310,6 +310,9 @@
unsigned int freq, unsigned int wait,
const u8 *buf, size_t buf_len, u64 *cookie,
int no_cck, int no_ack, int offchanok);
+static int nl80211_register_frame(struct i802_bss *bss,
+ struct nl_handle *hl_handle,
+ u16 type, const u8 *match, size_t match_len);
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
int report);
#ifdef ANDROID
@@ -1067,7 +1070,6 @@
return 1;
if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
- drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname);
wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
"interface");
wpa_driver_nl80211_finish_drv_init(drv);
@@ -1829,12 +1831,19 @@
static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
struct nlattr *tb[])
{
+ u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
+
if (tb[NL80211_ATTR_MAC] == NULL) {
wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
"event");
return;
}
os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+ /* register for any AUTH message */
+ nl80211_register_frame(&drv->first_bss, drv->first_bss.nl_mgmt,
+ type, NULL, 0);
+
drv->associated = 1;
wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
MAC2STR(drv->bssid));
@@ -2881,6 +2890,8 @@
struct wpa_driver_nl80211_data *drv;
struct wpa_driver_capa *capa;
+ unsigned int num_multichan_concurrent;
+
unsigned int error:1;
unsigned int device_ap_sme:1;
unsigned int poll_command_supported:1;
@@ -2891,7 +2902,6 @@
unsigned int p2p_go_supported:1;
unsigned int p2p_client_supported:1;
unsigned int p2p_concurrent:1;
- unsigned int p2p_multichan_concurrent:1;
};
@@ -3001,8 +3011,8 @@
if (combination_has_p2p && combination_has_mgd) {
info->p2p_concurrent = 1;
- if (nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) > 1)
- info->p2p_multichan_concurrent = 1;
+ info->num_multichan_concurrent =
+ nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
return 1;
}
@@ -3252,10 +3262,11 @@
drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
}
- if (info->p2p_multichan_concurrent) {
+ if (info->num_multichan_concurrent > 1) {
wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel "
"concurrent (driver advertised support)");
- drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
+ drv->capa.num_multichan_concurrent =
+ info->num_multichan_concurrent;
}
/* default to 5000 since early versions of mac80211 don't set it */
@@ -5189,12 +5200,20 @@
static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
int reason_code)
{
+ int ret;
+
wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
nl80211_mark_disconnected(drv);
- drv->ignore_next_local_disconnect = 0;
/* Disconnect command doesn't need BSSID - it uses cached value */
- return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
- reason_code, 0);
+ ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
+ reason_code, 0);
+ /*
+ * For locally generated disconnect, supplicant already generates a
+ * DEAUTH event, so ignore the event from NL80211.
+ */
+ drv->ignore_next_local_disconnect = ret == 0;
+
+ return ret;
}
@@ -5674,7 +5693,20 @@
mode = &phy_info->modes[*(phy_info->num_modes)];
os_memset(mode, 0, sizeof(*mode));
mode->mode = NUM_HOSTAPD_MODES;
- mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN;
+ mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN |
+ HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN;
+
+ /*
+ * Unsupported VHT MCS stream is defined as value 3, so the VHT
+ * MCS RX/TX map must be initialized with 0xffff to mark all 8
+ * possible streams as unsupported. This will be overridden if
+ * driver advertises VHT support.
+ */
+ mode->vht_mcs_set[0] = 0xff;
+ mode->vht_mcs_set[1] = 0xff;
+ mode->vht_mcs_set[4] = 0xff;
+ mode->vht_mcs_set[5] = 0xff;
+
*(phy_info->num_modes) += 1;
phy_info->last_mode = nl_band->nla_type;
phy_info->last_chan_idx = 0;
@@ -7835,8 +7867,6 @@
if (wpa_driver_nl80211_disconnect(
drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
return -1;
- /* Ignore the next local disconnect message. */
- drv->ignore_next_local_disconnect = 1;
ret = wpa_driver_nl80211_try_connect(drv, params);
}
return ret;
@@ -8690,13 +8720,16 @@
static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
- const char *bridge_ifname)
+ const char *bridge_ifname, char *ifname_wds)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
char name[IFNAMSIZ + 1];
os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
+ if (ifname_wds)
+ os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
+
wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
" aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
if (val) {
@@ -9216,12 +9249,13 @@
wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
"no_ack=%d offchanok=%d",
freq, wait, no_cck, no_ack, offchanok);
+ wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
if (nl80211_set_iface_id(msg, bss) < 0)
goto nla_put_failure;
-
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+ if (freq)
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
if (wait)
NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
if (offchanok && (drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX))
@@ -9809,7 +9843,7 @@
struct wpa_driver_nl80211_data *drv = bss->drv;
wpa_printf(MSG_DEBUG, "nl80211: Use Multi channel "
"concurrency");
- drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
+ drv->capa.num_multichan_concurrent = 2;
}
#endif
#endif /* CONFIG_P2P */
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index c392d57..6b5679c 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -375,14 +375,6 @@
*/
unsigned int max_listen;
-#ifdef ANDROID_P2P
- enum p2p_concurrency_type {
- P2P_NON_CONCURRENT,
- P2P_SINGLE_CHANNEL_CONCURRENT,
- P2P_MULTI_CHANNEL_CONCURRENT,
- } p2p_concurrency;
-#endif
-
/**
* cb_ctx - Context to use with callback functions
*/
diff --git a/src/utils/common.h b/src/utils/common.h
index e4f7031..29f0b95 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -205,6 +205,7 @@
#define be_to_host16(n) (n)
#define host_to_be16(n) (n)
#define le_to_host32(n) bswap_32(n)
+#define host_to_le32(n) bswap_32(n)
#define be_to_host32(n) (n)
#define host_to_be32(n) (n)
#define le_to_host64(n) bswap_64(n)