TDLS: Pass peer's Supported channel and oper class info during sta_add
authorSunil Dutt <usdutt@qti.qualcomm.com>
Mon, 6 Jan 2014 13:06:13 +0000 (18:36 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 14 Jan 2014 15:24:33 +0000 (17:24 +0200)
The information of the peer's supported channel and operating class
is required for the driver to do TDLS off channel operations with a
compatible peer. Pass this information to the driver when the peer
station is getting added.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

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

index 7d78648..12dc83e 100644 (file)
 #define WLAN_EID_FAST_BSS_TRANSITION 55
 #define WLAN_EID_TIMEOUT_INTERVAL 56
 #define WLAN_EID_RIC_DATA 57
+#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
 #define WLAN_EID_HT_OPERATION 61
 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
 #define WLAN_EID_WAPI 68
index db34ed1..4fd16ed 100644 (file)
@@ -1012,6 +1012,10 @@ struct hostapd_sta_add_params {
        u8 qosinfo;
        const u8 *ext_capab;
        size_t ext_capab_len;
+       const u8 *supp_channels;
+       size_t supp_channels_len;
+       const u8 *supp_oper_classes;
+       size_t supp_oper_classes_len;
 };
 
 struct hostapd_freq_params {
index efc6431..8a978f7 100644 (file)
@@ -136,6 +136,12 @@ struct wpa_tdls_peer {
 
        u8 *ext_capab;
        size_t ext_capab_len;
+
+       u8 *supp_channels;
+       size_t supp_channels_len;
+
+       u8 *supp_oper_classes;
+       size_t supp_oper_classes_len;
 };
 
 
@@ -633,6 +639,10 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
        peer->vht_capabilities = NULL;
        os_free(peer->ext_capab);
        peer->ext_capab = NULL;
+       os_free(peer->supp_channels);
+       peer->supp_channels = NULL;
+       os_free(peer->supp_oper_classes);
+       peer->supp_oper_classes = NULL;
        peer->rsnie_i_len = peer->rsnie_p_len = 0;
        peer->cipher = 0;
        peer->tpk_set = peer->tpk_success = 0;
@@ -1456,6 +1466,58 @@ static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
 }
 
 
+static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
+                                  struct wpa_tdls_peer *peer)
+{
+       if (!kde->supp_channels) {
+               wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
+               return 0;
+       }
+
+       if (!peer->supp_channels ||
+           peer->supp_channels_len < kde->supp_channels_len) {
+               os_free(peer->supp_channels);
+               peer->supp_channels = os_zalloc(kde->supp_channels_len);
+               if (peer->supp_channels == NULL)
+                       return -1;
+       }
+
+       peer->supp_channels_len = kde->supp_channels_len;
+
+       os_memcpy(peer->supp_channels, kde->supp_channels,
+                 peer->supp_channels_len);
+       wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
+                   (u8 *) peer->supp_channels, peer->supp_channels_len);
+       return 0;
+}
+
+
+static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
+                                      struct wpa_tdls_peer *peer)
+{
+       if (!kde->supp_oper_classes) {
+               wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
+               return 0;
+       }
+
+       if (!peer->supp_oper_classes ||
+           peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
+               os_free(peer->supp_oper_classes);
+               peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
+               if (peer->supp_oper_classes == NULL)
+                       return -1;
+       }
+
+       peer->supp_oper_classes_len = kde->supp_oper_classes_len;
+       os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
+                 peer->supp_oper_classes_len);
+       wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
+                   (u8 *) peer->supp_oper_classes,
+                   peer->supp_oper_classes_len);
+       return 0;
+}
+
+
 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
                                   const u8 *buf, size_t len)
 {
@@ -1568,6 +1630,12 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
        if (copy_peer_ext_capab(&kde, peer) < 0)
                goto error;
 
+       if (copy_peer_supp_channels(&kde, peer) < 0)
+               goto error;
+
+       if (copy_peer_supp_oper_classes(&kde, peer) < 0)
+               goto error;
+
        peer->qos_info = kde.qosinfo;
 
        peer->aid = kde.aid;
@@ -1761,7 +1829,7 @@ 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, 0, NULL, 0, NULL, NULL, 0,
-                               NULL, 0);
+                               NULL, 0, NULL, 0, NULL, 0);
        peer->tpk_in_progress = 1;
 
        wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1810,7 +1878,11 @@ static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
                                    peer->ht_capabilities,
                                    peer->vht_capabilities,
                                    peer->qos_info, peer->ext_capab,
-                                   peer->ext_capab_len) < 0)
+                                   peer->ext_capab_len,
+                                   peer->supp_channels,
+                                   peer->supp_channels_len,
+                                   peer->supp_oper_classes,
+                                   peer->supp_oper_classes_len) < 0)
                return -1;
 
        if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
@@ -1938,6 +2010,12 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
        if (copy_peer_ext_capab(&kde, peer) < 0)
                goto error;
 
+       if (copy_peer_supp_channels(&kde, peer) < 0)
+               goto error;
+
+       if (copy_peer_supp_oper_classes(&kde, peer) < 0)
+               goto error;
+
        peer->qos_info = kde.qosinfo;
 
        peer->aid = kde.aid;
@@ -2289,7 +2367,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
 
        /* add the peer to the driver as a "setup in progress" peer */
        wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
-                               NULL, 0);
+                               NULL, 0, NULL, 0, NULL, 0);
 
        peer->tpk_in_progress = 1;
 
index e189a58..9884ce1 100644 (file)
@@ -62,7 +62,10 @@ struct wpa_sm_ctx {
                                const struct ieee80211_ht_capabilities *ht_capab,
                                const struct ieee80211_vht_capabilities *vht_capab,
                                u8 qosinfo, const u8 *ext_capab,
-                               size_t ext_capab_len);
+                               size_t ext_capab_len, const u8 *supp_channels,
+                               size_t supp_channels_len,
+                               const u8 *supp_oper_classes,
+                               size_t supp_oper_classes_len);
 #endif /* CONFIG_TDLS */
        void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
                                  const u8 *replay_ctr);
index 0e0d373..cad6c8d 100644 (file)
@@ -286,14 +286,21 @@ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
                        size_t supp_rates_len,
                        const struct ieee80211_ht_capabilities *ht_capab,
                        const struct ieee80211_vht_capabilities *vht_capab,
-                       u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
+                       u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
+                       const u8 *supp_channels, size_t supp_channels_len,
+                       const u8 *supp_oper_classes,
+                       size_t supp_oper_classes_len)
 {
        if (sm->ctx->tdls_peer_addset)
                return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
                                                 aid, capability, supp_rates,
                                                 supp_rates_len, ht_capab,
                                                 vht_capab, qosinfo,
-                                                ext_capab, ext_capab_len);
+                                                ext_capab, ext_capab_len,
+                                                supp_channels,
+                                                supp_channels_len,
+                                                supp_oper_classes,
+                                                supp_oper_classes_len);
        return -1;
 }
 #endif /* CONFIG_TDLS */
index 50b9272..ab8d104 100644 (file)
@@ -434,6 +434,12 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
                        ie->vht_capabilities_len = pos[1];
                } else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
                        ie->qosinfo = pos[2];
+               } else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) {
+                       ie->supp_channels = pos + 2;
+                       ie->supp_channels_len = pos[1];
+               } else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) {
+                       ie->supp_oper_classes = pos + 2;
+                       ie->supp_oper_classes_len = pos[1];
                } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
                        ret = wpa_parse_generic(pos, end, ie);
                        if (ret < 0)
index 2c78801..0375767 100644 (file)
@@ -53,6 +53,10 @@ struct wpa_eapol_ie_parse {
        size_t ht_capabilities_len;
        const u8 *vht_capabilities;
        size_t vht_capabilities_len;
+       const u8 *supp_channels;
+       size_t supp_channels_len;
+       const u8 *supp_oper_classes;
+       size_t supp_oper_classes_len;
        u8 qosinfo;
        u16 aid;
 };
index 999d667..ad0895b 100644 (file)
@@ -579,7 +579,9 @@ static int wpa_supplicant_tdls_peer_addset(
        const u8 *supp_rates, size_t supp_rates_len,
        const struct ieee80211_ht_capabilities *ht_capab,
        const struct ieee80211_vht_capabilities *vht_capab,
-       u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
+       u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
+       const u8 *supp_channels, size_t supp_channels_len,
+       const u8 *supp_oper_classes, size_t supp_oper_classes_len)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct hostapd_sta_add_params params;
@@ -607,6 +609,10 @@ static int wpa_supplicant_tdls_peer_addset(
        params.set = !add;
        params.ext_capab = ext_capab;
        params.ext_capab_len = ext_capab_len;
+       params.supp_channels = supp_channels;
+       params.supp_channels_len = supp_channels_len;
+       params.supp_oper_classes = supp_oper_classes;
+       params.supp_oper_classes_len = supp_oper_classes_len;
 
        return wpa_drv_sta_add(wpa_s, &params);
 }