]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Count number of STA ACK'ed Deauth/Disassoc frames
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 3 Jan 2011 17:28:40 +0000 (19:28 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 3 Jan 2011 17:28:40 +0000 (19:28 +0200)
wlantest/process.c
wlantest/rx_mgmt.c
wlantest/wlantest.h
wlantest/wlantest_cli.c
wlantest/wlantest_ctrl.h

index 6cdb10b9b39fd83b4174a607abe55df48861d113..f740a6445187f506049fa07b56cc11f8665213f0 100644 (file)
@@ -100,6 +100,25 @@ static int rx_duplicate(struct wlantest *wt, const struct ieee80211_hdr *hdr,
 }
 
 
+static void rx_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
+{
+       struct ieee80211_hdr *last = (struct ieee80211_hdr *) wt->last_hdr;
+       u16 fc;
+
+       if (wt->last_len < 24 || (last->addr1[0] & 0x01) ||
+           os_memcmp(hdr->addr1, last->addr2, ETH_ALEN) != 0) {
+               wpa_printf(MSG_MSGDUMP, "Unknown Ack frame (previous frame "
+                          "not seen)");
+               return;
+       }
+
+       /* Ack to the previous frame */
+       fc = le_to_host16(last->frame_control);
+       if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
+               rx_mgmt_ack(wt, last);
+}
+
+
 static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
 {
        const struct ieee80211_hdr *hdr;
@@ -129,6 +148,8 @@ static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
                if (len < 10)
                        break;
                wt->rx_ctrl++;
+               if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACK)
+                       rx_ack(wt, hdr);
                break;
        case WLAN_FC_TYPE_DATA:
                if (len < 24)
@@ -142,6 +163,10 @@ static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
                           WLAN_FC_GET_TYPE(fc));
                break;
        }
+
+       os_memcpy(wt->last_hdr, data, len > sizeof(wt->last_hdr) ?
+                 sizeof(wt->last_hdr) : len);
+       wt->last_len = len;
 }
 
 
index 7630dcb12ed3c7de44135063052616d3cedea17e..8941129da9a9cd7d5ebf267aba6f739c99c6e28a 100644 (file)
@@ -1035,4 +1035,88 @@ void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
        }
 
        os_free(decrypted);
+
+       wt->last_mgmt_valid = valid;
+}
+
+
+static void rx_mgmt_deauth_ack(struct wlantest *wt,
+                              const struct ieee80211_hdr *hdr)
+{
+       const struct ieee80211_mgmt *mgmt;
+       struct wlantest_bss *bss;
+       struct wlantest_sta *sta;
+
+       mgmt = (const struct ieee80211_mgmt *) hdr;
+       bss = bss_get(wt, mgmt->bssid);
+       if (bss == NULL)
+               return;
+       if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
+               sta = sta_get(bss, mgmt->da);
+       else
+               sta = sta_get(bss, mgmt->sa);
+       if (sta == NULL)
+               return;
+
+       wpa_printf(MSG_DEBUG, "DEAUTH from " MACSTR " acknowledged by " MACSTR,
+                  MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
+       if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
+               int c;
+               c = wt->last_mgmt_valid ?
+                       WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK :
+                       WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK;
+               sta->counters[c]++;
+       }
+}
+
+
+static void rx_mgmt_disassoc_ack(struct wlantest *wt,
+                                const struct ieee80211_hdr *hdr)
+{
+       const struct ieee80211_mgmt *mgmt;
+       struct wlantest_bss *bss;
+       struct wlantest_sta *sta;
+
+       mgmt = (const struct ieee80211_mgmt *) hdr;
+       bss = bss_get(wt, mgmt->bssid);
+       if (bss == NULL)
+               return;
+       if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
+               sta = sta_get(bss, mgmt->da);
+       else
+               sta = sta_get(bss, mgmt->sa);
+       if (sta == NULL)
+               return;
+
+       wpa_printf(MSG_DEBUG, "DISASSOC from " MACSTR " acknowledged by "
+                  MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
+       if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
+               int c;
+               c = wt->last_mgmt_valid ?
+                       WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK :
+                       WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK;
+               sta->counters[c]++;
+       }
+}
+
+
+void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
+{
+       u16 fc, stype;
+       fc = le_to_host16(hdr->frame_control);
+       stype = WLAN_FC_GET_STYPE(fc);
+
+       wpa_printf(MSG_MSGDUMP, "MGMT ACK: stype=%u a1=" MACSTR " a2=" MACSTR
+                  " a3=" MACSTR,
+                  stype, MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
+                  MAC2STR(hdr->addr3));
+
+       switch (stype) {
+       case WLAN_FC_STYPE_DEAUTH:
+               rx_mgmt_deauth_ack(wt, hdr);
+               break;
+       case WLAN_FC_STYPE_DISASSOC:
+               rx_mgmt_disassoc_ack(wt, hdr);
+               break;
+       }
 }
index 5247909458e254b3e1c5d77d240b900affb6d75d..64e9b6ac582713a8e12fde6edd8965178f4227fa 100644 (file)
@@ -160,6 +160,10 @@ struct wlantest {
        void *write_pcap; /* pcap_t* */
        void *write_pcap_dumper; /* pcpa_dumper_t */
        struct timeval write_pcap_time;
+
+       u8 last_hdr[30];
+       size_t last_len;
+       int last_mgmt_valid;
 };
 
 int read_cap_file(struct wlantest *wt, const char *fname);
@@ -178,6 +182,7 @@ int monitor_init(struct wlantest *wt, const char *ifname);
 int monitor_init_wired(struct wlantest *wt, const char *ifname);
 void monitor_deinit(struct wlantest *wt);
 void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len);
+void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr);
 void rx_data(struct wlantest *wt, const u8 *data, size_t len);
 void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
                   const u8 *data, size_t len, int prot);
index b40eb54e9215079f2547fe03379361a7f83ce679..a2bb6b920227f5a982b736926da0f850ae1bd8b4 100644 (file)
@@ -540,6 +540,13 @@ static const struct sta_counters sta_counters[] = {
        { "assocresp_comeback", WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK },
        { "reassocresp_comeback", WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK },
        { "ping_ok_first_assoc", WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC },
+       { "valid_deauth_rx_ack", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK },
+       { "valid_disassoc_rx_ack",
+         WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK },
+       { "invalid_deauth_rx_ack",
+         WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK },
+       { "invalid_disassoc_rx_ack",
+         WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK },
        { NULL, 0 }
 };
 
index c8d4ce8346be656b6d475489f36857850deaafce..0dbf8c5e8ca0f4c5e9e3e6cb6f2b51fbc5107255 100644 (file)
@@ -97,6 +97,10 @@ enum wlantest_sta_counter {
        WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK,
        WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK,
        WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC,
+       WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK,
+       WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK,
+       WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK,
+       WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK,
        NUM_WLANTEST_STA_COUNTER
 };