]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TDLS: Get TDLS related capabilities from driver
authorArik Nemtsov <arik@wizery.com>
Mon, 26 Sep 2011 10:55:25 +0000 (13:55 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 23 Oct 2011 19:15:15 +0000 (22:15 +0300)
Put glue code in place to propagate TDLS related driver capabilities to
the TDLS state machine.

If the driver doesn't support capabilities, assume TDLS is supported
internally.

When TDLS is explicitly not supported, disable all user facing TDLS
operations.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
src/rsn_supp/tdls.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h
wpa_supplicant/wpas_glue.c

index 87c1a63189df870f06163641d21d06b41f1f66e2..6a98944e8b7c48289527da00e16565f9edd18208 100644 (file)
@@ -625,7 +625,7 @@ int wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr,
        u8 *rbuf, *pos;
        int ielen;
 
-       if (sm->tdls_disabled)
+       if (sm->tdls_disabled || !sm->tdls_supported)
                return -1;
 
        /* Find the node and free from the list */
@@ -1823,7 +1823,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
        struct wpa_tdls_peer *peer;
        int tdls_prohibited = sm->tdls_prohibited;
 
-       if (sm->tdls_disabled)
+       if (sm->tdls_disabled || !sm->tdls_supported)
                return -1;
 
 #ifdef CONFIG_TDLS_TESTING
@@ -1870,7 +1870,7 @@ int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr)
 {
        struct wpa_tdls_peer *peer;
 
-       if (sm->tdls_disabled)
+       if (sm->tdls_disabled || !sm->tdls_supported)
                return -1;
 
        for (peer = sm->tdls; peer; peer = peer->next) {
@@ -1899,8 +1899,9 @@ static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
        wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
                    buf, len);
 
-       if (sm->tdls_disabled) {
-               wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled");
+       if (sm->tdls_disabled || !sm->tdls_supported) {
+               wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
+                          "or unsupported by driver");
                return;
        }
 
@@ -1969,6 +1970,21 @@ int wpa_tdls_init(struct wpa_sm *sm)
                return -1;
        }
 
+       /*
+        * Drivers that support TDLS but don't implement the get_capa callback
+        * are assumed to perform everything internally
+        */
+       if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
+                                &sm->tdls_external_setup) < 0) {
+               sm->tdls_supported = 1;
+               sm->tdls_external_setup = 0;
+       }
+
+       wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
+                  "driver", sm->tdls_supported ? "" : " not");
+       wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
+                  sm->tdls_external_setup ? "external" : "internal");
+
        return 0;
 }
 
index a01baf90d390b7e1325fd0d6060919a2089d5ab4..297f21619c7e376997267dab887985e8802b7cbe 100644 (file)
@@ -56,6 +56,8 @@ struct wpa_sm_ctx {
                              const u8 *ies, size_t ies_len);
        int (*mark_authenticated)(void *ctx, const u8 *target_ap);
 #ifdef CONFIG_TDLS
+       int (*tdls_get_capa)(void *ctx, int *tdls_supported,
+                            int *tdls_ext_setup);
        int (*send_tdls_mgmt)(void *ctx, const u8 *dst,
                              u8 action_code, u8 dialog_token,
                              u16 status_code, const u8 *buf, size_t len);
index ebe73ca9c0fe173c0ebbbbb990864b6c8d5259eb..67c339027834e53afaad7527dbfdb1bcec80a984 100644 (file)
@@ -98,6 +98,15 @@ struct wpa_sm {
        struct wpa_tdls_peer *tdls;
        int tdls_prohibited;
        int tdls_disabled;
+
+       /* The driver supports TDLS */
+       int tdls_supported;
+
+       /*
+        * The driver requires explicit discovery/setup/teardown frames sent
+        * to it via tdls_mgmt.
+        */
+       int tdls_external_setup;
 #endif /* CONFIG_TDLS */
 
 #ifdef CONFIG_IEEE80211R
@@ -253,6 +262,16 @@ static inline void wpa_sm_set_rekey_offload(struct wpa_sm *sm)
 }
 
 #ifdef CONFIG_TDLS
+static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm,
+                                      int *tdls_supported,
+                                      int *tdls_ext_setup)
+{
+       if (sm->ctx->tdls_get_capa)
+               return sm->ctx->tdls_get_capa(sm->ctx->ctx, tdls_supported,
+                                             tdls_ext_setup);
+       return -1;
+}
+
 static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst,
                                        u8 action_code, u8 dialog_token,
                                        u16 status_code, const u8 *buf,
index aa251f20dbbcbb873291939aedcc4cc852b74f0f..058feed1e80de044353ef7830626c936a3da3d41 100644 (file)
@@ -2318,6 +2318,7 @@ next_driver:
                                                      &wpa_s->hw.flags);
 
        if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
+               wpa_s->drv_capa_known = 1;
                wpa_s->drv_flags = capa.flags;
                wpa_s->max_scan_ssids = capa.max_scan_ssids;
                wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
index 82e7059bfd5b3ea7eefa3b9d1bdbc10d68dc44c0..c247a8c5bee3b0b89007b6a686fb36e90e024ed5 100644 (file)
@@ -500,6 +500,7 @@ struct wpa_supplicant {
        unsigned int network_select:1;
        unsigned int auto_select:1;
 #endif /* CONFIG_INTERWORKING */
+       unsigned int drv_capa_known;
 
        struct {
                struct hostapd_hw_modes *modes;
index de09f81ef88bae18188c1b0c95449e445336e946..94948c6395d464b8d207b5cbc226df7af2e2e80e 100644 (file)
@@ -525,6 +525,27 @@ static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap)
 
 #ifdef CONFIG_TDLS
 
+static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported,
+                                       int *tdls_ext_setup)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+
+       *tdls_supported = 0;
+       *tdls_ext_setup = 0;
+
+       if (!wpa_s->drv_capa_known)
+               return -1;
+
+       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)
+               *tdls_supported = 1;
+
+       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP)
+               *tdls_ext_setup = 1;
+
+       return 0;
+}
+
+
 static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
                                         u8 action_code, u8 dialog_token,
                                         u16 status_code, const u8 *buf,
@@ -700,6 +721,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
        ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_TDLS
+       ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;
        ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
        ctx->tdls_oper = wpa_supplicant_tdls_oper;
 #endif /* CONFIG_TDLS */