]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TDLS: Pass peer's HT Capability and QOS information during sta_add
authorSunil Dutt <duttus@codeaurora.org>
Tue, 5 Feb 2013 14:41:01 +0000 (16:41 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 14 Feb 2013 19:01:50 +0000 (21:01 +0200)
The information of the peer's HT capability and the QOS information is
required for the driver to perform TDLS operations. Pass this
information to the driver when the peer station is getting added.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/common/ieee802_11_defs.h
src/rsn_supp/tdls.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
src/rsn_supp/wpa_ie.c
src/rsn_supp/wpa_ie.h
wpa_supplicant/wpas_glue.c

index f72c0d40c8438f109f224b48a29c3329f3e6109c..6a7fff6990de9371bff41547d4713b7f712cfeaa 100644 (file)
 /* EIDs defined by IEEE 802.11h - END */
 #define WLAN_EID_ERP_INFO 42
 #define WLAN_EID_HT_CAP 45
+#define WLAN_EID_QOS 46
 #define WLAN_EID_RSN 48
 #define WLAN_EID_EXT_SUPP_RATES 50
 #define WLAN_EID_MOBILITY_DOMAIN 54
index 59929b518bd3ce604734e06c4c91b4927f65ea0f..25aba62b2917b008c04674d4bd7e4cf9189ab235 100644 (file)
@@ -120,6 +120,10 @@ struct wpa_tdls_peer {
 
        u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
        size_t supp_rates_len;
+
+       struct ieee80211_ht_capabilities *ht_capabilities;
+
+       u8 qos_info;
 };
 
 
@@ -611,6 +615,8 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
        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;
@@ -1331,6 +1337,34 @@ static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
 }
 
 
+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)
 {
@@ -1400,6 +1434,11 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_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;
+
 #ifdef CONFIG_TDLS_TESTING
        if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
                peer = wpa_tdls_add_peer(sm, src_addr, NULL);
@@ -1623,7 +1662,7 @@ skip_rsn:
 
 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) {
@@ -1665,7 +1704,8 @@ static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 
        /* 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);
 }
@@ -1761,6 +1801,11 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_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;
@@ -2064,7 +2109,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
        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);
index eedbb2d9559704b6011157faffb2456093928652..2180687591163e2d7580901adc18a6aaa2d80138 100644 (file)
@@ -12,6 +12,7 @@
 #include "common/defs.h"
 #include "common/eapol_common.h"
 #include "common/wpa_common.h"
+#include "common/ieee802_11_defs.h"
 
 struct wpa_sm;
 struct eapol_sm;
@@ -57,7 +58,9 @@ struct wpa_sm_ctx {
        int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
        int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add,
                                u16 capability, const u8 *supp_rates,
-                               size_t supp_rates_len);
+                               size_t supp_rates_len,
+                               const struct ieee80211_ht_capabilities *ht_capab,
+                               u8 qosinfo);
 #endif /* CONFIG_TDLS */
        void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
                                  const u8 *replay_ctr);
index 9f9e641c387712edd6d7ecbb504b3f067f25d364..6decadb1af18d292ea3c0bb4bfb6d0165d3f6c61 100644 (file)
@@ -283,12 +283,15 @@ static inline int wpa_sm_tdls_oper(struct wpa_sm *sm, int oper,
 static inline int
 wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
                        u16 capability, const u8 *supp_rates,
-                       size_t supp_rates_len)
+                       size_t supp_rates_len,
+                       const struct ieee80211_ht_capabilities *ht_capab,
+                       u8 qosinfo)
 {
        if (sm->ctx->tdls_peer_addset)
                return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
                                                 capability, supp_rates,
-                                                supp_rates_len);
+                                                supp_rates_len, ht_capab,
+                                                qosinfo);
        return -1;
 }
 #endif /* CONFIG_TDLS */
index 3d7536595773cb885d4115b528503437d583b83a..252737f21117e1076ebccf199aedb3267ed8ddc4 100644 (file)
@@ -427,6 +427,11 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
                } else if (*pos == WLAN_EID_EXT_SUPP_RATES) {
                        ie->ext_supp_rates = pos;
                        ie->ext_supp_rates_len = pos[1] + 2;
+               } else if (*pos == WLAN_EID_HT_CAP) {
+                       ie->ht_capabilities = pos + 2;
+                       ie->ht_capabilities_len = pos[1];
+               } else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
+                       ie->qosinfo = pos[2];
                } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
                        ret = wpa_parse_generic(pos, end, ie);
                        if (ret < 0)
index 5afdfe9fc7253c16c0b714220fff7e28e08fda7f..b212711f229dfb17d9b6a13b33a3378dd959ab94 100644 (file)
@@ -49,6 +49,9 @@ struct wpa_eapol_ie_parse {
        size_t supp_rates_len;
        const u8 *ext_supp_rates;
        size_t ext_supp_rates_len;
+       const u8 *ht_capabilities;
+       size_t ht_capabilities_len;
+       u8 qosinfo;
 };
 
 int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
index e5e1f42df565308ee6d622af3c9e1538ace16ff2..bb4ca933db62dc0ef5818626a9982f123a574c07 100644 (file)
@@ -552,7 +552,9 @@ static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer)
 
 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;
@@ -563,7 +565,16 @@ static int wpa_supplicant_tdls_peer_addset(
        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;