diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 8cfd8df6a..27159ceef 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -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) { diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 297f21619..eb089947d 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -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); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 4a14be245..4d9219e9b 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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; } }