From 947f900fb8e431437bc9f8ff583a61b6624b3e72 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 10 Jun 2014 21:19:04 +0300 Subject: [PATCH] TDLS: Handle unreachable link teardown for external setup 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 --- src/rsn_supp/tdls.c | 21 +++++++++++++++++++-- src/rsn_supp/wpa.h | 2 +- wpa_supplicant/events.c | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 84b7c1bef..8e1775ca2 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -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); + } } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index e98967c99..07a7bf900 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -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); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index eda40ecbc..b6b2410fe 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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: