TDLS: Track TDLS channel switch prohibition in BSS
authorArik Nemtsov <arik@wizery.com>
Mon, 29 Dec 2014 03:35:18 +0000 (22:35 -0500)
committerJouni Malinen <j@w1.fi>
Sun, 4 Jan 2015 16:59:31 +0000 (18:59 +0200)
Mark an appropriate sm flag when TDLS switch is prohibited by the AP.
Populate the flag upon association with the AP.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
src/rsn_supp/tdls.c
src/rsn_supp/wpa_i.h

index 918440c..958c952 100644 (file)
@@ -2833,39 +2833,61 @@ void wpa_tdls_disassoc(struct wpa_sm *sm)
 }
 
 
-static int wpa_tdls_prohibited(const u8 *ies, size_t len)
+static int wpa_tdls_prohibited(struct wpa_eapol_ie_parse *elems)
 {
-       struct wpa_eapol_ie_parse elems;
-
-       if (ies == NULL)
-               return 0;
-
-       if (wpa_supplicant_parse_ies(ies, len, &elems) < 0)
-               return 0;
+       /* bit 38 - TDLS Prohibited */
+       return !!(elems->ext_capab[2 + 4] & 0x40);
+}
 
-       if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
-               return 0;
 
-        /* bit 38 - TDLS Prohibited */
-       return !!(elems.ext_capab[2 + 4] & 0x40);
+static int wpa_tdls_chan_switch_prohibited(struct wpa_eapol_ie_parse *elems)
+{
+       /* bit 39 - TDLS Channel Switch Prohibited */
+       return !!(elems->ext_capab[2 + 4] & 0x80);
 }
 
 
 void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
 {
-       sm->tdls_prohibited = wpa_tdls_prohibited(ies, len);
+       struct wpa_eapol_ie_parse elems;
+
+       sm->tdls_prohibited = 0;
+       sm->tdls_chan_switch_prohibited = 0;
+
+       if (ies == NULL || wpa_supplicant_parse_ies(ies, len, &elems) < 0 ||
+           elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
+               return;
+
+       sm->tdls_prohibited = wpa_tdls_prohibited(&elems);
        wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
                   sm->tdls_prohibited ? "prohibited" : "allowed");
+       sm->tdls_chan_switch_prohibited =
+               wpa_tdls_chan_switch_prohibited(&elems);
+       wpa_printf(MSG_DEBUG, "TDLS: TDLS channel switch %s in the target BSS",
+                  sm->tdls_chan_switch_prohibited ? "prohibited" : "allowed");
 }
 
 
 void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
 {
-       if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) {
+       struct wpa_eapol_ie_parse elems;
+
+       if (ies == NULL || wpa_supplicant_parse_ies(ies, len, &elems) < 0 ||
+           elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
+               return;
+
+       if (!sm->tdls_prohibited && wpa_tdls_prohibited(&elems)) {
                wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
                           "(Re)Association Response IEs");
                sm->tdls_prohibited = 1;
        }
+
+       if (!sm->tdls_chan_switch_prohibited &&
+           wpa_tdls_chan_switch_prohibited(&elems)) {
+               wpa_printf(MSG_DEBUG,
+                          "TDLS: TDLS channel switch prohibited based on (Re)Association Response IEs");
+               sm->tdls_chan_switch_prohibited = 1;
+       }
 }
 
 
index ad4ccae..a7f5619 100644 (file)
@@ -92,6 +92,7 @@ struct wpa_sm {
 #ifdef CONFIG_TDLS
        struct wpa_tdls_peer *tdls;
        int tdls_prohibited;
+       int tdls_chan_switch_prohibited;
        int tdls_disabled;
 
        /* The driver supports TDLS */