TDLS: Pass peer's Capability and Ext Capability info during sta_add
authorSunil Dutt <duttus@codeaurora.org>
Tue, 5 Feb 2013 14:50:36 +0000 (16:50 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 14 Feb 2013 19:02:34 +0000 (21:02 +0200)
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 <jouni@qca.qualcomm.com>

src/drivers/driver.h
src/rsn_supp/tdls.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/wpas_glue.c

index 06aa8ef..274eeca 100644 (file)
@@ -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 {
index 25aba62..09adc19 100644 (file)
@@ -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);
index 2180687..6679dda 100644 (file)
@@ -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);
index 6decadb..5dae5de 100644 (file)
@@ -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 */
index bb4ca93..dfc3b76 100644 (file)
@@ -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, &params);
 }