TDLS: Support sending a teardown frame from usermode
authorArik Nemtsov <arik@wizery.com>
Mon, 26 Sep 2011 10:55:28 +0000 (13:55 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 23 Oct 2011 19:18:49 +0000 (22:18 +0300)
When a driver does not implement the TDLS_TEARDOWN operation internally,
send an explicit TDLS link teardown frame to the driver.

Change all teardown calls to use these calling semantics.

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
wpa_supplicant/events.c

index 8cfd8df..27159ce 100644 (file)
@@ -255,6 +255,26 @@ static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
 }
 
 
+static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
+                               u16 reason_code)
+{
+       int ret;
+
+       if (sm->tdls_external_setup) {
+               ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
+
+               /* disable the link after teardown was sent */
+               wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
+       } else {
+               ret = wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
+       }
+
+       wpa_tdls_peer_free(sm, peer);
+
+       return ret;
+}
+
+
 static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 
@@ -293,15 +313,11 @@ static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
                eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
                                       wpa_tdls_tpk_retry_timeout, sm, peer);
        } else {
-               wpa_printf(MSG_INFO, "Sending Tear_Down Request");
-               wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
-
-               wpa_printf(MSG_INFO, "Clearing SM: Peerkey(" MACSTR ")",
-                          MAC2STR(peer->addr));
                eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
 
-               /* clear the Peerkey statemachine */
-               wpa_tdls_peer_free(sm, peer);
+               wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
+               wpa_tdls_do_teardown(sm, peer,
+                                    WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
        }
 }
 
@@ -578,7 +594,8 @@ static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
        } else {
                wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
                           " - tear down", MAC2STR(peer->addr));
-               wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
+               wpa_tdls_do_teardown(sm, peer,
+                                    WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
        }
 }
 
@@ -617,8 +634,7 @@ static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
 }
 
 
-int wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr,
-                                 u16 reason_code)
+int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
 {
        struct wpa_tdls_peer *peer;
        struct wpa_tdls_ftie *ftie;
@@ -707,6 +723,34 @@ skip_ies:
 }
 
 
+int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
+{
+       struct wpa_tdls_peer *peer;
+
+       if (sm->tdls_disabled || !sm->tdls_supported)
+               return -1;
+
+       for (peer = sm->tdls; peer; peer = peer->next) {
+               if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
+                       break;
+       }
+
+       if (peer == NULL) {
+               wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
+                  " for link Teardown", MAC2STR(addr));
+               return -1;
+       }
+
+       if (!peer->tpk_success) {
+               wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
+                  " not connected - cannot Teardown link", MAC2STR(addr));
+               return -1;
+       }
+
+       return wpa_tdls_do_teardown(sm, peer, reason_code);
+}
+
+
 static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
                                  const u8 *buf, size_t len)
 {
index 297f216..eb08994 100644 (file)
@@ -360,8 +360,8 @@ void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len);
 void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len);
 int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr);
 int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr);
-int wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr,
-                                 u16 reason_code);
+int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code);
+int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code);
 int wpa_tdls_init(struct wpa_sm *sm);
 void wpa_tdls_deinit(struct wpa_sm *sm);
 void wpa_tdls_enable(struct wpa_sm *sm, int enabled);
index 4a14be2..4d9219e 100644 (file)
@@ -1755,9 +1755,8 @@ static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
                wpa_tdls_start(wpa_s->wpa, data->tdls.peer);
                break;
        case TDLS_REQUEST_TEARDOWN:
-               /* request from driver to add FTIE */
-               wpa_tdls_recv_teardown_notify(wpa_s->wpa, data->tdls.peer,
-                                             data->tdls.reason_code);
+               wpa_tdls_send_teardown(wpa_s->wpa, data->tdls.peer,
+                                      data->tdls.reason_code);
                break;
        }
 }