]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/commitdiff
TDLS: Collect peer capabilities and supp-rates during link setup
authorArik Nemtsov <arik@wizery.com>
Mon, 26 Sep 2011 10:55:31 +0000 (13:55 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 23 Oct 2011 19:19:13 +0000 (22:19 +0300)
Record the capabilities and supported rates of the TDLS peer during
link setup. These are given in the IEs passed in Setup Request and
Setup Response frames.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
src/rsn_supp/tdls.c
src/rsn_supp/wpa_ie.c
src/rsn_supp/wpa_ie.h

index 9fe247c2750b6318a2e68f303f437e2d0724efc4..45db2b346bce75ec29d311034ecd9cd4a945c705 100644 (file)
@@ -88,6 +88,8 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
 
 
 #define TDLS_MAX_IE_LEN 80
+#define IEEE80211_MAX_SUPP_RATES 32
+
 struct wpa_tdls_peer {
        struct wpa_tdls_peer *next;
        int initiator; /* whether this end was initiator for TDLS setup */
@@ -119,6 +121,11 @@ struct wpa_tdls_peer {
                int buf_len;    /* length of TPK message for retransmission */
                u8 *buf;        /* buffer for TPK message */
        } sm_tmr;
+
+       u16 capability;
+
+       u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+       size_t supp_rates_len;
 };
 
 
@@ -1299,6 +1306,32 @@ int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
 }
 
 
+static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
+                          struct wpa_tdls_peer *peer)
+{
+       if (!kde->supp_rates) {
+               wpa_printf(MSG_DEBUG, "TDLS: No supported rates received");
+               return -1;
+       }
+
+       peer->supp_rates_len = kde->supp_rates_len - 2;
+       if (peer->supp_rates_len > IEEE80211_MAX_SUPP_RATES)
+               peer->supp_rates_len = IEEE80211_MAX_SUPP_RATES;
+       os_memcpy(peer->supp_rates, kde->supp_rates + 2, peer->supp_rates_len);
+
+       if (kde->ext_supp_rates) {
+               int clen = kde->ext_supp_rates_len - 2;
+               if (peer->supp_rates_len + clen > IEEE80211_MAX_SUPP_RATES)
+                       clen = IEEE80211_MAX_SUPP_RATES - peer->supp_rates_len;
+               os_memcpy(peer->supp_rates + peer->supp_rates_len,
+                         kde->ext_supp_rates + 2, clen);
+               peer->supp_rates_len += clen;
+       }
+
+       return 0;
+}
+
+
 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
                                   const u8 *buf, size_t len)
 {
@@ -1321,6 +1354,7 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
        u16 ielen;
        u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
        int tdls_prohibited = sm->tdls_prohibited;
+       int existing_peer = 0;
 
        if (len < 3 + 3)
                return -1;
@@ -1333,7 +1367,22 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
 
        wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
 
-       cpos += 2; /* capability information */
+       for (peer = sm->tdls; peer; peer = peer->next) {
+               if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) {
+                       existing_peer = 1;
+                       break;
+               }
+       }
+
+       if (peer == NULL) {
+               peer = wpa_tdls_add_peer(sm, src_addr);
+               if (peer == NULL)
+                       goto error;
+       }
+
+       /* capability information */
+       peer->capability = WPA_GET_LE16(cpos);
+       cpos += 2;
 
        ielen = len - (cpos - buf); /* start of IE in buf */
        if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) {
@@ -1358,6 +1407,9 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
        wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
                   MAC2STR(src_addr));
 
+       if (copy_supp_rates(&kde, peer) < 0)
+               goto error;
+
 #ifdef CONFIG_TDLS_TESTING
        if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
                for (peer = sm->tdls; peer; peer = peer->next) {
@@ -1457,26 +1509,10 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
        }
 
 skip_rsn:
-       /* Find existing entry and if found, use that instead of adding
-        * a new one; how to handle the case where both ends initiate at the
+       /* If found, use existing entry instead of adding a new one;
+        * how to handle the case where both ends initiate at the
         * same time? */
-       for (peer = sm->tdls; peer; peer = peer->next) {
-               if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
-                       break;
-       }
-
-       if (peer == NULL) {
-               wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
-                          "peer, creating one for " MACSTR,
-                          MAC2STR(src_addr));
-               peer = os_malloc(sizeof(*peer));
-               if (peer == NULL)
-                       goto error;
-               os_memset(peer, 0, sizeof(*peer));
-               os_memcpy(peer->addr, src_addr, ETH_ALEN);
-               peer->next = sm->tdls;
-               sm->tdls = peer;
-       } else {
+       if (existing_peer) {
                if (peer->tpk_success) {
                        wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
                                   "direct link is enabled - tear down the "
@@ -1677,7 +1713,10 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
 
        if (len < 3 + 2 + 1 + 2)
                return -1;
-       pos += 2; /* capability information */
+
+       /* capability information */
+       peer->capability = WPA_GET_LE16(pos);
+       pos += 2;
 
        ielen = len - (pos - buf); /* start of IE in buf */
        if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) {
@@ -1708,6 +1747,9 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
                goto error;
        }
 
+       if (copy_supp_rates(&kde, peer) < 0)
+               goto error;
+
        if (!wpa_tdls_get_privacy(sm)) {
                peer->rsnie_p_len = 0;
                peer->cipher = WPA_CIPHER_NONE;
index 654cc1f1534096755265694c59d7097ff1476957..cbbc54fd6ab1854265c98b6e7e16e7743eaec4f9 100644 (file)
@@ -424,11 +424,19 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
                                            pos, 2 + pos[1]);
                        }
                } else if (*pos == WLAN_EID_LINK_ID) {
-                       ie->lnkid = pos;
-                       ie->lnkid_len = pos[1] + 2;
+                       if (pos[1] >= 18) {
+                               ie->lnkid = pos;
+                               ie->lnkid_len = pos[1] + 2;
+                       }
                } else if (*pos == WLAN_EID_EXT_CAPAB) {
                        ie->ext_capab = pos;
                        ie->ext_capab_len = pos[1] + 2;
+               } else if (*pos == WLAN_EID_SUPP_RATES) {
+                       ie->supp_rates = pos;
+                       ie->supp_rates_len = pos[1] + 2;
+               } 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_VENDOR_SPECIFIC) {
                        ret = wpa_parse_generic(pos, end, ie);
                        if (ret < 0)
index f939b13d1e7437d4588dfe6d374c9e4060a69b93..c13d94c6a55e2e37bccac3bb9584d6c9938e0424 100644 (file)
@@ -51,6 +51,10 @@ struct wpa_eapol_ie_parse {
        size_t lnkid_len;
        const u8 *ext_capab;
        size_t ext_capab_len;
+       const u8 *supp_rates;
+       size_t supp_rates_len;
+       const u8 *ext_supp_rates;
+       size_t ext_supp_rates_len;
 };
 
 int wpa_supplicant_parse_ies(const u8 *buf, size_t len,