TDLS: Handle unreachable link teardown for external setup
authorArik Nemtsov <arik@wizery.com>
Tue, 10 Jun 2014 18:19:04 +0000 (21:19 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 16 Jun 2014 20:34:06 +0000 (23:34 +0300)
If a link is unreachable, the specification mandates we should send a
teardown packet via the AP with a specific teardown reason. Force this
by first disabling the link and only then sending the teardown packet
for the LOW_ACK event.

Rename the TDLS LOW_ACK event handler to better reflect its purpose.

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

index 84b7c1b..8e1775c 100644 (file)
@@ -802,7 +802,7 @@ static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
 }
 
 
-void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr)
+void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr)
 {
        struct wpa_tdls_peer *peer;
 
@@ -811,8 +811,25 @@ void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr)
                        break;
        }
 
-       if (peer)
+       if (!peer || !peer->tpk_success) {
+               wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
+                          " not connected - cannot teardown unreachable link",
+                          MAC2STR(addr));
+               return;
+       }
+
+       if (wpa_tdls_is_external_setup(sm)) {
+               /*
+                * Disable the link, send a teardown packet through the
+                * AP, and then reset link data.
+                */
+               wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
+               wpa_tdls_send_teardown(sm, addr,
+                                      WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE);
+               wpa_tdls_peer_free(sm, peer);
+       } else {
                wpa_tdls_disable_peer_link(sm, peer);
+       }
 }
 
 
index e98967c..07a7bf9 100644 (file)
@@ -385,7 +385,7 @@ int wpa_tdls_init(struct wpa_sm *sm);
 void wpa_tdls_teardown_peers(struct wpa_sm *sm);
 void wpa_tdls_deinit(struct wpa_sm *sm);
 void wpa_tdls_enable(struct wpa_sm *sm, int enabled);
-void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr);
+void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr);
 const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr);
 int wpa_tdls_is_external_setup(struct wpa_sm *sm);
 
index eda40ec..b6b2410 100644 (file)
@@ -3402,7 +3402,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 #endif /* CONFIG_AP */
 #ifdef CONFIG_TDLS
                if (data)
-                       wpa_tdls_disable_link(wpa_s->wpa, data->low_ack.addr);
+                       wpa_tdls_disable_unreachable_link(wpa_s->wpa,
+                                                         data->low_ack.addr);
 #endif /* CONFIG_TDLS */
                break;
        case EVENT_IBSS_PEER_LOST: