From 0d2e395d74e5d4a77faad08bedb8609209ea0a12 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 24 Jan 2011 14:26:35 +0200 Subject: [PATCH] wlantest: Maintain only a single entry for an active direct link The TDLS link itself is bidirectional, but there is explicit initiator/responder roles. Remove the other direction of the link if it exists when processing TDLS Setup Confirm to make sure that the link counters are stored for the current TDLS entery. This is also changing the control interface search for TDLS counters to require initiator/responder addresses in the correct order instead of matching entries regardless of the role. --- wlantest/bss.c | 9 ++++++++- wlantest/ctrl.c | 3 +-- wlantest/rx_tdls.c | 36 ++++++++++++++++++++++++++++++------ wlantest/wlantest.h | 1 + 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/wlantest/bss.c b/wlantest/bss.c index a4a315533..34dee50b0 100644 --- a/wlantest/bss.c +++ b/wlantest/bss.c @@ -67,6 +67,13 @@ void pmk_deinit(struct wlantest_pmk *pmk) } +void tdls_deinit(struct wlantest_tdls *tdls) +{ + dl_list_del(&tdls->list); + os_free(tdls); +} + + void bss_deinit(struct wlantest_bss *bss) { struct wlantest_sta *sta, *n; @@ -77,7 +84,7 @@ void bss_deinit(struct wlantest_bss *bss) dl_list_for_each_safe(pmk, np, &bss->pmk, struct wlantest_pmk, list) pmk_deinit(pmk); dl_list_for_each_safe(tdls, nt, &bss->tdls, struct wlantest_tdls, list) - os_free(tdls); + tdls_deinit(tdls); dl_list_del(&bss->list); os_free(bss); } diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c index 11a7dd40a..e97448d6b 100644 --- a/wlantest/ctrl.c +++ b/wlantest/ctrl.c @@ -444,8 +444,7 @@ static void ctrl_get_tdls_counter(struct wlantest *wt, int sock, u8 *cmd, } dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if ((tdls->init == sta && tdls->resp == sta2) || - (tdls->init == sta2 && tdls->resp == sta)) { + if (tdls->init == sta && tdls->resp == sta2) { found = 1; break; } diff --git a/wlantest/rx_tdls.c b/wlantest/rx_tdls.c index fd18c0831..4e25ccedd 100644 --- a/wlantest/rx_tdls.c +++ b/wlantest/rx_tdls.c @@ -23,7 +23,8 @@ #include "wlantest.h" -static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *linkid) +static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *linkid, + int create_new) { struct wlantest_bss *bss; struct wlantest_sta *init, *resp; @@ -46,6 +47,9 @@ static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *linkid) return tdls; } + if (!create_new) + return NULL; + tdls = os_zalloc(sizeof(*tdls)); if (tdls == NULL) return NULL; @@ -202,7 +206,7 @@ static void rx_data_tdls_setup_request(struct wlantest *wt, const u8 *bssid, " initiator STA " MACSTR " responder STA " MACSTR, MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN), MAC2STR(elems.link_id + 2 * ETH_ALEN)); - tdls = get_tdls(wt, elems.link_id); + tdls = get_tdls(wt, elems.link_id, 1); if (tdls) tdls->counters[WLANTEST_TDLS_COUNTER_SETUP_REQ]++; } @@ -234,7 +238,7 @@ static void rx_data_tdls_setup_response(struct wlantest *wt, const u8 *bssid, MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN), MAC2STR(elems.link_id + 2 * ETH_ALEN)); - tdls = get_tdls(wt, elems.link_id); + tdls = get_tdls(wt, elems.link_id, 1); if (!tdls) return; if (status) @@ -259,6 +263,7 @@ static void rx_data_tdls_setup_confirm(struct wlantest *wt, const u8 *bssid, u16 status; struct ieee802_11_elems elems; struct wlantest_tdls *tdls; + u8 link_id[3 * ETH_ALEN]; if (len < 3) return; @@ -275,7 +280,7 @@ static void rx_data_tdls_setup_confirm(struct wlantest *wt, const u8 *bssid, MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN), MAC2STR(elems.link_id + 2 * ETH_ALEN)); - tdls = get_tdls(wt, elems.link_id); + tdls = get_tdls(wt, elems.link_id, 1); if (tdls == NULL) return; if (status) @@ -287,13 +292,32 @@ static void rx_data_tdls_setup_confirm(struct wlantest *wt, const u8 *bssid, return; tdls->link_up = 1; - if (tdls_derive_tpk(tdls, bssid, elems.ftie, elems.ftie_len) < 1) + if (tdls_derive_tpk(tdls, bssid, elems.ftie, elems.ftie_len) < 1) { + if (elems.ftie == NULL) + goto remove_reverse; return; + } if (tdls_verify_mic(tdls, 3, &elems) == 0) { tdls->dialog_token = data[2]; wpa_printf(MSG_DEBUG, "TDLS: Dialog Token for the link: %u", tdls->dialog_token); } + +remove_reverse: + /* + * The TDLS link itself is bidirectional, but there is explicit + * initiator/responder roles. Remove the other direction of the link + * (if it exists) to make sure that the link counters are stored for + * the current TDLS entery. + */ + os_memcpy(link_id, elems.link_id, ETH_ALEN); + os_memcpy(link_id + ETH_ALEN, elems.link_id + 2 * ETH_ALEN, ETH_ALEN); + os_memcpy(link_id + 2 * ETH_ALEN, elems.link_id + ETH_ALEN, ETH_ALEN); + tdls = get_tdls(wt, link_id, 0); + if (tdls) { + wpa_printf(MSG_DEBUG, "TDLS: Remove reverse link entry"); + tdls_deinit(tdls); + } } @@ -377,7 +401,7 @@ static void rx_data_tdls_teardown(struct wlantest *wt, const u8 *bssid, MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN), MAC2STR(elems.link_id + 2 * ETH_ALEN)); - tdls = get_tdls(wt, elems.link_id); + tdls = get_tdls(wt, elems.link_id, 1); if (tdls) { tdls->link_up = 0; tdls_verify_mic_teardown(tdls, 4, data, &elems); diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 4301504e8..da63d2f57 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -212,6 +212,7 @@ void bss_flush(struct wlantest *wt); int bss_add_pmk_from_passphrase(struct wlantest_bss *bss, const char *passphrase); void pmk_deinit(struct wlantest_pmk *pmk); +void tdls_deinit(struct wlantest_tdls *tdls); struct wlantest_sta * sta_find(struct wlantest_bss *bss, const u8 *addr); struct wlantest_sta * sta_get(struct wlantest_bss *bss, const u8 *addr);