From fb8f5fc6fd9534721a9ce2ce4af479e585062add Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 3 Jan 2011 19:28:40 +0200 Subject: [PATCH] wlantest: Count number of STA ACK'ed Deauth/Disassoc frames --- wlantest/process.c | 25 ++++++++++++ wlantest/rx_mgmt.c | 84 ++++++++++++++++++++++++++++++++++++++++ wlantest/wlantest.h | 5 +++ wlantest/wlantest_cli.c | 7 ++++ wlantest/wlantest_ctrl.h | 4 ++ 5 files changed, 125 insertions(+) diff --git a/wlantest/process.c b/wlantest/process.c index 6cdb10b9b..f740a6445 100644 --- a/wlantest/process.c +++ b/wlantest/process.c @@ -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; } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 7630dcb12..8941129da 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -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; + } } diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 524790945..64e9b6ac5 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -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); diff --git a/wlantest/wlantest_cli.c b/wlantest/wlantest_cli.c index b40eb54e9..a2bb6b920 100644 --- a/wlantest/wlantest_cli.c +++ b/wlantest/wlantest_cli.c @@ -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 } }; diff --git a/wlantest/wlantest_ctrl.h b/wlantest/wlantest_ctrl.h index c8d4ce834..0dbf8c5e8 100644 --- a/wlantest/wlantest_ctrl.h +++ b/wlantest/wlantest_ctrl.h @@ -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 };