[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