From d16531c40c2322bb23dbdc0ce4338c2c3722f9f8 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Tue, 5 Feb 2013 16:50:36 +0200 Subject: [PATCH] TDLS: Pass peer's Capability and Ext Capability info during sta_add The contents of the peer's capability and extended capability information is required for the driver to perform TDLS P-UAPSD and Off Channel operations. Pass this information to the driver when the peer station is getting added. Signed-hostap: Jouni Malinen --- src/drivers/driver.h | 2 ++ src/rsn_supp/tdls.c | 46 ++++++++++++++++++++++++++++++++++---- src/rsn_supp/wpa.h | 3 ++- src/rsn_supp/wpa_i.h | 5 +++-- wpa_supplicant/wpas_glue.c | 4 +++- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 06aa8ef06..274eecaa2 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -911,6 +911,8 @@ struct hostapd_sta_add_params { u32 flags; /* bitmask of WPA_STA_* flags */ int set; /* Set STA parameters instead of add */ u8 qosinfo; + const u8 *ext_capab; + size_t ext_capab_len; }; struct hostapd_freq_params { diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 25aba62b2..09adc194d 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -124,6 +124,9 @@ struct wpa_tdls_peer { struct ieee80211_ht_capabilities *ht_capabilities; u8 qos_info; + + u8 *ext_capab; + size_t ext_capab_len; }; @@ -617,6 +620,8 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) peer->sm_tmr.buf = NULL; os_free(peer->ht_capabilities); peer->ht_capabilities = NULL; + os_free(peer->ext_capab); + peer->ext_capab = NULL; peer->rsnie_i_len = peer->rsnie_p_len = 0; peer->cipher = 0; peer->tpk_set = peer->tpk_success = 0; @@ -1365,6 +1370,30 @@ static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde, } +static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde, + struct wpa_tdls_peer *peer) +{ + if (!kde->ext_capab) { + wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities " + "received"); + return 0; + } + + if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) { + /* Need to allocate buffer to fit the new information */ + os_free(peer->ext_capab); + peer->ext_capab = os_zalloc(kde->ext_capab_len - 2); + if (peer->ext_capab == NULL) + return -1; + } + + peer->ext_capab_len = kde->ext_capab_len - 2; + os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len); + + return 0; +} + + static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, const u8 *buf, size_t len) { @@ -1437,6 +1466,9 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, if (copy_peer_ht_capab(&kde, peer) < 0) goto error; + if (copy_peer_ext_capab(&kde, peer) < 0) + goto error; + peer->qos_info = kde.qosinfo; #ifdef CONFIG_TDLS_TESTING @@ -1662,7 +1694,8 @@ 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, NULL, 0); + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 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) { @@ -1702,10 +1735,11 @@ static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) #endif /* CONFIG_TDLS_TESTING */ } - /* add supported rates and capabilities to the TDLS peer */ + /* add supported rates, capabilities, and qos_info to the TDLS peer */ wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability, peer->supp_rates, peer->supp_rates_len, - peer->ht_capabilities, peer->qos_info); + peer->ht_capabilities, peer->qos_info, + peer->ext_capab, peer->ext_capab_len); wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); } @@ -1804,6 +1838,9 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, if (copy_peer_ht_capab(&kde, peer) < 0) goto error; + if (copy_peer_ext_capab(&kde, peer) < 0) + goto error; + peer->qos_info = kde.qosinfo; if (!wpa_tdls_get_privacy(sm)) { @@ -2109,7 +2146,8 @@ 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, NULL, 0); + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0, + NULL, 0); if (wpa_tdls_send_tpk_m1(sm, peer) < 0) { wpa_tdls_disable_link(sm, peer->addr); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 218068759..6679dda54 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -60,7 +60,8 @@ struct wpa_sm_ctx { u16 capability, const u8 *supp_rates, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, - u8 qosinfo); + u8 qosinfo, const u8 *ext_capab, + size_t ext_capab_len); #endif /* CONFIG_TDLS */ void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck, const u8 *replay_ctr); diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 6decadb1a..5dae5de8e 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -285,13 +285,14 @@ 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, const struct ieee80211_ht_capabilities *ht_capab, - u8 qosinfo) + u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) { if (sm->ctx->tdls_peer_addset) return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add, capability, supp_rates, supp_rates_len, ht_capab, - qosinfo); + qosinfo, ext_capab, + ext_capab_len); return -1; } #endif /* CONFIG_TDLS */ diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index bb4ca933d..dfc3b7692 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -554,7 +554,7 @@ 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 struct ieee80211_ht_capabilities *ht_capab, - u8 qosinfo) + u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) { struct wpa_supplicant *wpa_s = ctx; struct hostapd_sta_add_params params; @@ -579,6 +579,8 @@ static int wpa_supplicant_tdls_peer_addset( params.supp_rates = supp_rates; params.supp_rates_len = supp_rates_len; params.set = !add; + params.ext_capab = ext_capab; + params.ext_capab_len = ext_capab_len; return wpa_drv_sta_add(wpa_s, ¶ms); }