[RFC 09/13] TDLS: collect peer capabilities and supp-rates during link setup
Arik Nemtsov
arik
Thu Sep 15 03:22:27 PDT 2011
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 at wizery.com>
Cc: Kalyan C Gaddam <chakkal at iit.edu>
---
src/rsn_supp/tdls.c | 97 ++++++++++++++++++++++++++++++++++++++-----------
src/rsn_supp/wpa_ie.c | 11 ++++++
src/rsn_supp/wpa_ie.h | 4 ++
3 files changed, 91 insertions(+), 21 deletions(-)
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 71b43ea..a438a53 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -119,6 +119,12 @@ struct wpa_tdls_peer {
int buf_len; /* length of TPK message for retransmission */
u8 *buf; /* buffer for TPK message */
} sm_tmr;
+
+ u16 capability;
+
+#define IEEE80211_MAX_SUPP_RATES 32
+ u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+ size_t supp_rates_len;
};
@@ -1317,6 +1323,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;
@@ -1329,7 +1336,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) {
@@ -1354,6 +1376,29 @@ 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 (!kde.supp_rates) {
+ wpa_printf(MSG_DEBUG, "TDLS: No supported rates in "
+ "Setup Req");
+ goto error;
+ }
+
+ if (kde.supp_rates_len - 2 + kde.ext_supp_rates_len - 2 >
+ IEEE80211_MAX_SUPP_RATES) {
+ wpa_printf(MSG_DEBUG, "TDLS: Too much supported rates in "
+ "Setup Req");
+ goto error;
+ }
+
+ peer->supp_rates_len = kde.supp_rates_len - 2;
+ os_memcpy(peer->supp_rates, kde.supp_rates + 2,
+ kde.supp_rates_len - 2);
+
+ if (kde.ext_supp_rates) {
+ os_memcpy(peer->supp_rates + peer->supp_rates_len,
+ kde.ext_supp_rates + 2, kde.ext_supp_rates_len - 2);
+ peer->supp_rates_len += kde.ext_supp_rates_len - 2;
+ }
+
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
for (peer = sm->tdls; peer; peer = peer->next) {
@@ -1453,26 +1498,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 "
@@ -1673,7 +1702,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) {
@@ -1704,6 +1736,29 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
goto error;
}
+ if (!kde.supp_rates) {
+ wpa_printf(MSG_DEBUG, "TDLS: No supported rates in "
+ "Setup Req");
+ goto error;
+ }
+
+ if (kde.supp_rates_len - 2 + kde.ext_supp_rates_len - 2 >
+ IEEE80211_MAX_SUPP_RATES) {
+ wpa_printf(MSG_DEBUG, "TDLS: Too much supported rates in "
+ "Setup Req");
+ goto error;
+ }
+
+ peer->supp_rates_len = kde.supp_rates_len - 2;
+ os_memcpy(peer->supp_rates, kde.supp_rates + 2,
+ kde.supp_rates_len - 2);
+
+ if (kde.ext_supp_rates) {
+ os_memcpy(peer->supp_rates + peer->supp_rates_len,
+ kde.ext_supp_rates + 2, kde.ext_supp_rates_len - 2);
+ peer->supp_rates_len += kde.ext_supp_rates_len - 2;
+ }
+
if (!wpa_tdls_get_privacy(sm)) {
peer->rsnie_p_len = 0;
peer->cipher = WPA_CIPHER_NONE;
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 654cc1f..0f89623 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -426,9 +426,20 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
} else if (*pos == WLAN_EID_LINK_ID) {
ie->lnkid = pos;
ie->lnkid_len = pos[1] + 2;
+
+ if (ie->lnkid_len < 18 + 2) {
+ ie->lnkid = 0;
+ ie->lnkid_len = 0;
+ }
} 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)
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index f939b13..c13d94c 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -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,
--
1.7.4.1
More information about the Hostap
mailing list