[RFC 06/13] TDLS: support sending a teardown frame from usermode

Arik Nemtsov arik
Thu Sep 15 03:22:24 PDT 2011


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 this fallback mechanism.

Signed-off-by: Arik Nemtsov <arik at wizery.com>
Cc: Kalyan C Gaddam <chakkal at iit.edu>
---
 src/rsn_supp/tdls.c     |   62 +++++++++++++++++++++++++++++++++++++++-------
 src/rsn_supp/wpa.h      |    4 +-
 wpa_supplicant/events.c |    5 +--
 3 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 49c4c4c..b4f17db 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -255,6 +255,27 @@ 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)
+{
+	/* try asking the driver to teardown the link */
+	int ret = wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
+
+	/* it it doesn't work - send an explicit teardown message */
+	if (ret) {
+		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);
+	}
+
+	/* clear the Peerkey statemachine */
+	wpa_tdls_peer_free(sm, peer);
+
+	return ret;
+}
+
+
 static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 
@@ -293,15 +314,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_INFO, "Sending Tear_Down Request");
+		wpa_tdls_do_teardown(sm, peer,
+				     WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
 	}
 }
 
@@ -578,7 +595,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 +635,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 +724,31 @@ skip_ies:
 }
 
 
+int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
+{
+	struct wpa_tdls_peer *peer;
+
+	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)
 {
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index a01baf9..e814d33 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -358,8 +358,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);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 1856a63..d552484 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1631,9 +1631,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;
 	}
 }
-- 
1.7.4.1




More information about the Hostap mailing list