u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
size_t supp_rates_len;
+
+ struct ieee80211_ht_capabilities *ht_capabilities;
+
+ u8 qos_info;
};
peer->initiator = 0;
os_free(peer->sm_tmr.buf);
peer->sm_tmr.buf = NULL;
+ os_free(peer->ht_capabilities);
+ peer->ht_capabilities = NULL;
peer->rsnie_i_len = peer->rsnie_p_len = 0;
peer->cipher = 0;
peer->tpk_set = peer->tpk_success = 0;
}
+static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde,
+ struct wpa_tdls_peer *peer)
+{
+ if (!kde->ht_capabilities ||
+ kde->ht_capabilities_len <
+ sizeof(struct ieee80211_ht_capabilities) ) {
+ wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities "
+ "received");
+ return 0;
+ }
+
+ if (!peer->ht_capabilities) {
+ peer->ht_capabilities =
+ os_zalloc(sizeof(struct ieee80211_ht_capabilities));
+ if (peer->ht_capabilities == NULL)
+ return -1;
+ }
+
+ os_memcpy(peer->ht_capabilities, kde->ht_capabilities,
+ sizeof(struct ieee80211_ht_capabilities));
+ wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities",
+ (u8 *) peer->ht_capabilities,
+ sizeof(struct ieee80211_ht_capabilities));
+
+ return 0;
+}
+
+
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
if (copy_supp_rates(&kde, peer) < 0)
goto error;
+ if (copy_peer_ht_capab(&kde, peer) < 0)
+ goto error;
+
+ peer->qos_info = kde.qosinfo;
+
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
peer = wpa_tdls_add_peer(sm, src_addr, NULL);
skip_rsn_check:
/* add the peer to the driver as a "setup in progress" peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0);
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
/* add supported rates and capabilities to the TDLS peer */
wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
- peer->supp_rates, peer->supp_rates_len);
+ peer->supp_rates, peer->supp_rates_len,
+ peer->ht_capabilities, peer->qos_info);
wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
}
if (copy_supp_rates(&kde, peer) < 0)
goto error;
+ if (copy_peer_ht_capab(&kde, peer) < 0)
+ goto error;
+
+ peer->qos_info = kde.qosinfo;
+
if (!wpa_tdls_get_privacy(sm)) {
peer->rsnie_p_len = 0;
peer->cipher = WPA_CIPHER_NONE;
peer->initiator = 1;
/* add the peer to the driver as a "setup in progress" peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0);
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0);
if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
wpa_tdls_disable_link(sm, peer->addr);
static int wpa_supplicant_tdls_peer_addset(
void *ctx, const u8 *peer, int add, u16 capability,
- const u8 *supp_rates, size_t supp_rates_len)
+ const u8 *supp_rates, size_t supp_rates_len,
+ const struct ieee80211_ht_capabilities *ht_capab,
+ u8 qosinfo)
{
struct wpa_supplicant *wpa_s = ctx;
struct hostapd_sta_add_params params;
params.aid = 1;
params.capability = capability;
params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
- params.ht_capabilities = NULL;
+
+ /*
+ * TDLS Setup frames do not contain WMM IEs, hence need to depend on
+ * qosinfo to check if the peer is WMM capable.
+ */
+ if (qosinfo)
+ params.flags |= WPA_STA_WMM;
+
+ params.ht_capabilities = ht_capab;
+ params.qosinfo = qosinfo;
params.listen_interval = 0;
params.supp_rates = supp_rates;
params.supp_rates_len = supp_rates_len;