Accumulative patch from commit ce26864e79144cba12d5ff98632570593cc57b8a
187f87f hostapd: Allow ctrl_iface group to be specified on command line
9f890c9 TDLS: Support both external and internal setup in disabling link
864fe3a TDLS: Fix TDLS Setup Request processing in existing-peer cases
1d43e28 TDLS: Fix TPK M2 processing in concurrent initiation case
ef8151a P2P: Write p2p_ignore_shared_freq to configuration file on updates
8047f70 P2P: Ignore Tx acknowledgment status for Invitation Response
18a2eaa Add ap_vendor_elements for wpa_supplicant AP/P2P GO mode
b084df8 Add vendor_elements into Beacon/Probe Response IE parameters
b92e08f nl80211: Add debug prints for set_ap parameters
c30a4ab nl80211: Fix mode settings with split wiphy dump
Change-Id: I859638e630b6ca32b64e09943fce4d96f779897b
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index b71d51d..8205d13 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -173,6 +173,14 @@
}
#endif /* CONFIG_HS20 */
+ if (hapd->conf->vendor_elements) {
+ size_t add = wpabuf_len(hapd->conf->vendor_elements);
+ if (wpabuf_resize(&beacon, add) == 0)
+ wpabuf_put_buf(beacon, hapd->conf->vendor_elements);
+ if (wpabuf_resize(&proberesp, add) == 0)
+ wpabuf_put_buf(proberesp, hapd->conf->vendor_elements);
+ }
+
*beacon_ret = beacon;
*proberesp_ret = proberesp;
*assocresp_ret = assocresp;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 8ab4f3e..f5aed99 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -40,6 +40,7 @@
int global_ctrl_sock;
char *global_iface_path;
char *global_iface_name;
+ gid_t ctrl_iface_group;
struct hostapd_iface **iface;
};
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index efd5cab..c2b9fff 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5100,21 +5100,19 @@
struct hostapd_channel_data *chan,
struct nlattr *tb_freq[])
{
+ enum hostapd_hw_mode m;
+
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
chan->flag = 0;
- /* mode is not set */
- if (mode->mode >= NUM_HOSTAPD_MODES) {
- /* crude heuristic */
- if (chan->freq < 4000)
- mode->mode = HOSTAPD_MODE_IEEE80211B;
- else if (chan->freq > 50000)
- mode->mode = HOSTAPD_MODE_IEEE80211AD;
- else
- mode->mode = HOSTAPD_MODE_IEEE80211A;
- }
+ if (chan->freq < 4000)
+ m = HOSTAPD_MODE_IEEE80211B;
+ else if (chan->freq > 50000)
+ m = HOSTAPD_MODE_IEEE80211AD;
+ else
+ m = HOSTAPD_MODE_IEEE80211A;
- switch (mode->mode) {
+ switch (m) {
case HOSTAPD_MODE_IEEE80211AD:
chan->chan = (chan->freq - 56160) / 2160;
break;
@@ -5238,12 +5236,6 @@
continue;
mode->rates[idx] = nla_get_u32(
tb_rate[NL80211_BITRATE_ATTR_RATE]);
-
- /* crude heuristic */
- if (mode->mode == HOSTAPD_MODE_IEEE80211B &&
- mode->rates[idx] > 200)
- mode->mode = HOSTAPD_MODE_IEEE80211G;
-
idx++;
}
@@ -5321,12 +5313,31 @@
static struct hostapd_hw_modes *
-wpa_driver_nl80211_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes)
+wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
+ u16 *num_modes)
{
u16 m;
struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
int i, mode11g_idx = -1;
+ /* heuristic to set up modes */
+ for (m = 0; m < *num_modes; m++) {
+ if (!modes[m].num_channels)
+ continue;
+ if (modes[m].channels[0].freq < 4000) {
+ modes[m].mode = HOSTAPD_MODE_IEEE80211B;
+ for (i = 0; i < modes[m].num_rates; i++) {
+ if (modes[m].rates[i] > 200) {
+ modes[m].mode = HOSTAPD_MODE_IEEE80211G;
+ break;
+ }
+ }
+ } else if (modes[m].channels[0].freq > 50000)
+ modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
+ else
+ modes[m].mode = HOSTAPD_MODE_IEEE80211A;
+ }
+
/* If only 802.11g mode is included, use it to construct matching
* 802.11b mode data. */
@@ -5572,7 +5583,8 @@
if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
nl80211_set_ht40_flags(drv, &result);
- return wpa_driver_nl80211_add_11b(result.modes, num_modes);
+ return wpa_driver_nl80211_postprocess_modes(result.modes,
+ num_modes);
}
msg = NULL;
nla_put_failure:
@@ -5790,32 +5802,49 @@
cmd = NL80211_CMD_SET_BEACON;
nl80211_cmd(drv, msg, 0, cmd);
+ wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
+ params->head, params->head_len);
NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);
+ wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
+ params->tail, params->tail_len);
NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);
+ wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", ifindex);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+ wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);
+ wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);
+ wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
+ params->ssid, params->ssid_len);
NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
params->ssid);
- if (params->proberesp && params->proberesp_len)
+ if (params->proberesp && params->proberesp_len) {
+ wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
+ params->proberesp, params->proberesp_len);
NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
params->proberesp);
+ }
switch (params->hide_ssid) {
case NO_SSID_HIDING:
+ wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
NL80211_HIDDEN_SSID_NOT_IN_USE);
break;
case HIDDEN_SSID_ZERO_LEN:
+ wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
NL80211_HIDDEN_SSID_ZERO_LEN);
break;
case HIDDEN_SSID_ZERO_CONTENTS:
+ wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
NL80211_HIDDEN_SSID_ZERO_CONTENTS);
break;
}
+ wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
if (params->privacy)
NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
+ wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
(WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
/* Leave out the attribute */
@@ -5826,6 +5855,7 @@
NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
NL80211_AUTHTYPE_OPEN_SYSTEM);
+ wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
ver = 0;
if (params->wpa_version & WPA_PROTO_WPA)
ver |= NL80211_WPA_VERSION_1;
@@ -5834,6 +5864,8 @@
if (ver)
NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
+ wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
+ params->key_mgmt_suites);
num_suites = 0;
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
suites[num_suites++] = WLAN_AKM_SUITE_8021X;
@@ -5848,6 +5880,8 @@
params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))
NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
+ wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
+ params->pairwise_ciphers);
num_suites = 0;
if (params->pairwise_ciphers & WPA_CIPHER_CCMP)
suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
@@ -5864,6 +5898,8 @@
num_suites * sizeof(u32), suites);
}
+ wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
+ params->group_cipher);
switch (params->group_cipher) {
case WPA_CIPHER_CCMP:
NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
@@ -5888,21 +5924,29 @@
}
if (params->beacon_ies) {
+ wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
+ params->beacon_ies);
NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
wpabuf_head(params->beacon_ies));
}
if (params->proberesp_ies) {
+ wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
+ params->proberesp_ies);
NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
wpabuf_len(params->proberesp_ies),
wpabuf_head(params->proberesp_ies));
}
if (params->assocresp_ies) {
+ wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
+ params->assocresp_ies);
NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
wpabuf_len(params->assocresp_ies),
wpabuf_head(params->assocresp_ies));
}
if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) {
+ wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
+ params->ap_max_inactivity);
NLA_PUT_U16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
params->ap_max_inactivity);
}
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 2ed9730..3beefd2 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -547,7 +547,13 @@
"P2P: Invitation Response TX callback: success=%d", success);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
- if (success && p2p->cfg->invitation_received) {
+ if (!success)
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+ "P2P: Assume Invitation Response was actually "
+ "received by the peer even though Ack was not "
+ "reported");
+
+ if (p2p->cfg->invitation_received) {
p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
p2p->inv_sa,
p2p->inv_group_bssid_ptr,
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index bcd924c..8ceaf6c 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -1464,6 +1464,57 @@
if (peer == NULL)
goto error;
+ /* If found, use existing entry instead of adding a new one;
+ * how to handle the case where both ends initiate at the
+ * same time? */
+ if (existing_peer) {
+ if (peer->tpk_success) {
+ wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
+ "direct link is enabled - tear down the "
+ "old link first");
+#if 0
+ /* TODO: Disabling the link would be more proper
+ * operation here, but it seems to trigger a race with
+ * some drivers handling the new request frame. */
+ wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr);
+#else
+ if (sm->tdls_external_setup)
+ wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
+ src_addr);
+ else
+ wpa_tdls_del_key(sm, peer);
+#endif
+ wpa_tdls_peer_free(sm, peer);
+ }
+
+ /*
+ * An entry is already present, so check if we already sent a
+ * TDLS Setup Request. If so, compare MAC addresses and let the
+ * STA with the lower MAC address continue as the initiator.
+ * The other negotiation is terminated.
+ */
+ if (peer->initiator) {
+ if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
+ wpa_printf(MSG_DEBUG, "TDLS: Discard request "
+ "from peer with higher address "
+ MACSTR, MAC2STR(src_addr));
+ return -1;
+ } else {
+ wpa_printf(MSG_DEBUG, "TDLS: Accept request "
+ "from peer with lower address "
+ MACSTR " (terminate previously "
+ "initiated negotiation",
+ MAC2STR(src_addr));
+ if (sm->tdls_external_setup)
+ wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
+ src_addr);
+ else
+ wpa_tdls_del_key(sm, peer);
+ wpa_tdls_peer_free(sm, peer);
+ }
+ }
+ }
+
/* capability information */
peer->capability = WPA_GET_LE16(cpos);
cpos += 2;
@@ -1595,52 +1646,6 @@
}
skip_rsn:
- /* If found, use existing entry instead of adding a new one;
- * how to handle the case where both ends initiate at the
- * same time? */
- if (existing_peer) {
- if (peer->tpk_success) {
- wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
- "direct link is enabled - tear down the "
- "old link first");
-#if 0
- /* TODO: Disabling the link would be more proper
- * operation here, but it seems to trigger a race with
- * some drivers handling the new request frame. */
- wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr);
-#else
- if (sm->tdls_external_setup)
- wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
- src_addr);
- else
- wpa_tdls_del_key(sm, peer);
-#endif
- wpa_tdls_peer_free(sm, peer);
- }
-
- /*
- * An entry is already present, so check if we already sent a
- * TDLS Setup Request. If so, compare MAC addresses and let the
- * STA with the lower MAC address continue as the initiator.
- * The other negotiation is terminated.
- */
- if (peer->initiator) {
- if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
- wpa_printf(MSG_DEBUG, "TDLS: Discard request "
- "from peer with higher address "
- MACSTR, MAC2STR(src_addr));
- return -1;
- } else {
- wpa_printf(MSG_DEBUG, "TDLS: Accept request "
- "from peer with lower address "
- MACSTR " (terminate previously "
- "initiated negotiation",
- MAC2STR(src_addr));
- wpa_tdls_disable_link(sm, peer->addr);
- }
- }
- }
-
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) {
@@ -1807,6 +1812,16 @@
"TPK M2: " MACSTR, MAC2STR(src_addr));
return -1;
}
+ if (!peer->initiator) {
+ /*
+ * This may happen if both devices try to initiate TDLS at the
+ * same time and we accept the TPK M1 from the peer in
+ * wpa_tdls_process_tpk_m1() and clear our previous state.
+ */
+ wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so "
+ "ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
+ return -1;
+ }
wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
if (len < 3 + 2 + 1)