]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Implement IEEE 802.11 duplicate detection
authorJouni Malinen <jouni.malinen@atheros.com>
Tue, 23 Nov 2010 12:27:28 +0000 (14:27 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 23 Nov 2010 12:27:28 +0000 (14:27 +0200)
This cleans up debug logs by avoiding incorrect entries on TKIP/CCMP
replays and some state changes.

wlantest/process.c
wlantest/sta.c
wlantest/wlantest.h

index 6083390fe0fad559dd79fbf843b60334d445b86c..7ca77b20d2b8103aa8cf2ae3654b1fb7c3027832 100644 (file)
 #include "wlantest.h"
 
 
+static int rx_duplicate(struct wlantest *wt, const struct ieee80211_hdr *hdr,
+                       size_t len)
+{
+       u16 fc;
+       int tid = 16;
+       const u8 *sta_addr, *bssid;
+       struct wlantest_bss *bss;
+       struct wlantest_sta *sta;
+       int to_ap;
+       le16 *seq_ctrl;
+
+       if (hdr->addr1[0] & 0x01)
+               return 0; /* Ignore group addressed frames */
+
+       fc = le_to_host16(hdr->frame_control);
+       if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) {
+               bssid = hdr->addr3;
+               if (os_memcmp(bssid, hdr->addr2, ETH_ALEN) == 0) {
+                       sta_addr = hdr->addr1;
+                       to_ap = 0;
+               } else {
+                       if (os_memcmp(bssid, hdr->addr1, ETH_ALEN) != 0)
+                               return 0; /* Unsupported STA-to-STA frame */
+                       sta_addr = hdr->addr2;
+                       to_ap = 1;
+               }
+       } else {
+               switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
+               case 0:
+                       return 0; /* IBSS not supported */
+               case WLAN_FC_FROMDS:
+                       sta_addr = hdr->addr1;
+                       bssid = hdr->addr2;
+                       to_ap = 0;
+                       break;
+               case WLAN_FC_TODS:
+                       sta_addr = hdr->addr2;
+                       bssid = hdr->addr1;
+                       to_ap = 1;
+                       break;
+               case WLAN_FC_TODS | WLAN_FC_FROMDS:
+                       return 0; /* WDS not supported */
+               default:
+                       return 0;
+               }
+
+               if ((WLAN_FC_GET_STYPE(fc) & 0x08) && len >= 26) {
+                       const u8 *qos = ((const u8 *) hdr) + 24;
+                       tid = qos[0] & 0x0f;
+               }
+       }
+
+       bss = bss_find(wt, bssid);
+       if (bss == NULL)
+               return 0;
+       sta = sta_find(bss, sta_addr);
+       if (sta == NULL)
+               return 0;
+
+       if (to_ap)
+               seq_ctrl = &sta->seq_ctrl_to_ap[tid];
+       else
+               seq_ctrl = &sta->seq_ctrl_to_sta[tid];
+
+       if ((fc & WLAN_FC_RETRY) && hdr->seq_ctrl == *seq_ctrl) {
+               u16 s = le_to_host16(hdr->seq_ctrl);
+               wpa_printf(MSG_MSGDUMP, "Ignore duplicated frame (seq=%u "
+                          "frag=%u A1=" MACSTR " A2=" MACSTR ")",
+                          WLAN_GET_SEQ_SEQ(s), WLAN_GET_SEQ_FRAG(s),
+                          MAC2STR(hdr->addr1), MAC2STR(hdr->addr2));
+               return 1;
+       }
+
+       *seq_ctrl = hdr->seq_ctrl;
+
+       return 0;
+}
+
+
 static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
 {
        const struct ieee80211_hdr *hdr;
@@ -40,14 +119,22 @@ static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
 
        switch (WLAN_FC_GET_TYPE(fc)) {
        case WLAN_FC_TYPE_MGMT:
+               if (len < 24)
+                       break;
+               if (rx_duplicate(wt, hdr, len))
+                       break;
                rx_mgmt(wt, data, len);
                break;
        case WLAN_FC_TYPE_CTRL:
                if (len < 10)
-                       return;
+                       break;
                wt->rx_ctrl++;
                break;
        case WLAN_FC_TYPE_DATA:
+               if (len < 24)
+                       break;
+               if (rx_duplicate(wt, hdr, len))
+                       break;
                rx_data(wt, data, len);
                break;
        default:
index bec494dabf83f004be1d4aa846234595125a9b9d..bfa6ee0b0e883a37f3d0fa68363aad9c74d3c0dc 100644 (file)
@@ -47,6 +47,8 @@ struct wlantest_sta * sta_get(struct wlantest_bss *bss, const u8 *addr)
        sta = os_zalloc(sizeof(*sta));
        if (sta == NULL)
                return NULL;
+       os_memset(sta->seq_ctrl_to_sta, 0xff, sizeof(sta->seq_ctrl_to_sta));
+       os_memset(sta->seq_ctrl_to_ap, 0xff, sizeof(sta->seq_ctrl_to_ap));
        sta->bss = bss;
        os_memcpy(sta->addr, addr, ETH_ALEN);
        dl_list_add(&bss->sta, &sta->list);
index 4899659c02b3bbb599996447b9f15b28f99324ef..6bb8e1edb231939aa3944fc8d12fab0c4946fc05 100644 (file)
@@ -79,6 +79,9 @@ struct wlantest_sta {
        u32 icmp_echo_req_dst;
        u16 icmp_echo_req_id;
        u16 icmp_echo_req_seq;
+
+       le16 seq_ctrl_to_sta[17];
+       le16 seq_ctrl_to_ap[17];
 };
 
 struct wlantest_bss {