]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Maintain only a single entry for an active direct link
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 24 Jan 2011 12:26:35 +0000 (14:26 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 24 Jan 2011 12:34:45 +0000 (14:34 +0200)
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
wlantest/ctrl.c
wlantest/rx_tdls.c
wlantest/wlantest.h

index a4a315533cf93cb09b86a4557c1c2b6cfbbc9d14..34dee50b092ef2d12a63d2e04e792eebb73f80ab 100644 (file)
@@ -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);
 }
index 11a7dd40adba798a6d4ea88167d72e1157331089..e97448d6b519da69e98a0c3708c242842ce193d1 100644 (file)
@@ -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;
                }
index fd18c08316225048dd0b02108b8e41048c45ea97..4e25cceddfd6b5bc54b4a4c9f084b58fee9d4194 100644 (file)
@@ -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);
index 4301504e8e763d52c101fe40470adec5edc8ab26..da63d2f577ccba3d7b0e5a7255b106fe0709cbbc 100644 (file)
@@ -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);