diff options
Diffstat (limited to 'wlantest')
-rw-r--r-- | wlantest/Makefile | 111 | ||||
-rw-r--r-- | wlantest/bss.c | 297 | ||||
-rw-r--r-- | wlantest/ccmp.c | 349 | ||||
-rw-r--r-- | wlantest/crc32.c | 84 | ||||
-rw-r--r-- | wlantest/ctrl.c | 1364 | ||||
-rw-r--r-- | wlantest/inject.c | 375 | ||||
-rw-r--r-- | wlantest/monitor.c | 144 | ||||
-rw-r--r-- | wlantest/process.c | 381 | ||||
-rw-r--r-- | wlantest/readpcap.c | 144 | ||||
-rw-r--r-- | wlantest/rx_data.c | 529 | ||||
-rw-r--r-- | wlantest/rx_eapol.c | 1034 | ||||
-rw-r--r-- | wlantest/rx_ip.c | 157 | ||||
-rw-r--r-- | wlantest/rx_mgmt.c | 1169 | ||||
-rw-r--r-- | wlantest/rx_tdls.c | 568 | ||||
-rw-r--r-- | wlantest/sta.c | 183 | ||||
-rw-r--r-- | wlantest/tkip.c | 381 | ||||
-rw-r--r-- | wlantest/wep.c | 103 | ||||
-rw-r--r-- | wlantest/wired.c | 288 | ||||
-rw-r--r-- | wlantest/wlantest.c | 304 | ||||
-rw-r--r-- | wlantest/wlantest.h | 247 | ||||
-rw-r--r-- | wlantest/wlantest_cli.c | 1714 | ||||
-rw-r--r-- | wlantest/wlantest_ctrl.h | 166 | ||||
-rw-r--r-- | wlantest/writepcap.c | 97 |
23 files changed, 0 insertions, 10189 deletions
diff --git a/wlantest/Makefile b/wlantest/Makefile deleted file mode 100644 index c165ed4..0000000 --- a/wlantest/Makefile +++ /dev/null @@ -1,111 +0,0 @@ -ALL=wlantest wlantest_cli - -all: $(ALL) - -ifndef CC -CC=gcc -endif - -ifndef RANLIB -RANLIB=ranlib -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - - -CFLAGS += -I. -CFLAGS += -I../src -CFLAGS += -I../src/utils - - -ifndef LDO -LDO=$(CC) -endif - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - - -OBJS_lib += ../src/utils/libutils.a -OBJS_lib += ../src/crypto/libcrypto.a - -CFLAGS += -DCONFIG_PEERKEY -CFLAGS += -DCONFIG_IEEE80211W -CFLAGS += -DCONFIG_IEEE80211R - -OBJS += ../src/common/ieee802_11_common.o -OBJS += ../src/common/wpa_common.o -OBJS += ../src/radius/radius.o -OBJS += ../src/rsn_supp/wpa_ie.o - -OBJS += wlantest.o -OBJS += readpcap.o -OBJS += writepcap.o -OBJS += monitor.o -OBJS += process.o -OBJS += wired.o -OBJS += rx_mgmt.o -OBJS += rx_data.o -OBJS += rx_eapol.o -OBJS += rx_ip.o -OBJS += rx_tdls.o -OBJS += bss.o -OBJS += sta.o -OBJS += crc32.o -OBJS += ccmp.o -OBJS += tkip.o -OBJS += ctrl.o -OBJS += inject.o -OBJS += wep.o - -LIBS += -lpcap - - -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - - -ifneq ($(CONFIG_SOLIB), yes) -LIBWLANTEST = libwlantest.a -libwlantest.a: $(OBJS_lib) - $(AR) crT libwlantest.a $(OBJS_lib) - $(RANLIB) libwlantest.a - -else -CFLAGS += -fPIC -DPIC -LDFLAGS += -shared - -LIBWLANTEST = libwlantest.so -libwlantest.so: $(OBJS_lib) - $(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBWLANTEST) - -endif - - -OBJS_cli = wlantest_cli.o - - -wlantest: $(OBJS) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o wlantest $(OBJS) -L. -lwlantest $(LIBS) - -wlantest_cli: $(OBJS_cli) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o wlantest_cli $(OBJS_cli) -L. -lwlantest - -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d libwlantest.a libwlantest.so $(ALL) - --include $(OBJS:%.o=%.d) diff --git a/wlantest/bss.c b/wlantest/bss.c deleted file mode 100644 index 94f2580..0000000 --- a/wlantest/bss.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * BSS list - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/defs.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "crypto/sha1.h" -#include "wlantest.h" - - -struct wlantest_bss * bss_find(struct wlantest *wt, const u8 *bssid) -{ - struct wlantest_bss *bss; - - dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) { - if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) - return bss; - } - - return NULL; -} - - -struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid) -{ - struct wlantest_bss *bss; - - if (bssid[0] & 0x01) - return NULL; /* Skip group addressed frames */ - - bss = bss_find(wt, bssid); - if (bss) - return bss; - - bss = os_zalloc(sizeof(*bss)); - if (bss == NULL) - return NULL; - dl_list_init(&bss->sta); - dl_list_init(&bss->pmk); - dl_list_init(&bss->tdls); - os_memcpy(bss->bssid, bssid, ETH_ALEN); - dl_list_add(&wt->bss, &bss->list); - wpa_printf(MSG_DEBUG, "Discovered new BSS - " MACSTR, - MAC2STR(bss->bssid)); - return bss; -} - - -void pmk_deinit(struct wlantest_pmk *pmk) -{ - dl_list_del(&pmk->list); - os_free(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; - struct wlantest_pmk *pmk, *np; - struct wlantest_tdls *tdls, *nt; - dl_list_for_each_safe(sta, n, &bss->sta, struct wlantest_sta, list) - sta_deinit(sta); - 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) - tdls_deinit(tdls); - dl_list_del(&bss->list); - os_free(bss); -} - - -int bss_add_pmk_from_passphrase(struct wlantest_bss *bss, - const char *passphrase) -{ - struct wlantest_pmk *pmk; - - pmk = os_zalloc(sizeof(*pmk)); - if (pmk == NULL) - return -1; - if (pbkdf2_sha1(passphrase, (char *) bss->ssid, bss->ssid_len, 4096, - pmk->pmk, sizeof(pmk->pmk)) < 0) { - os_free(pmk); - return -1; - } - - wpa_printf(MSG_INFO, "Add possible PMK for BSSID " MACSTR - " based on passphrase '%s'", - MAC2STR(bss->bssid), passphrase); - wpa_hexdump(MSG_DEBUG, "Possible PMK", pmk->pmk, sizeof(pmk->pmk)); - dl_list_add(&bss->pmk, &pmk->list); - - return 0; -} - - -static void bss_add_pmk(struct wlantest *wt, struct wlantest_bss *bss) -{ - struct wlantest_passphrase *p; - - dl_list_for_each(p, &wt->passphrase, struct wlantest_passphrase, list) - { - if (!is_zero_ether_addr(p->bssid) && - os_memcmp(p->bssid, bss->bssid, ETH_ALEN) != 0) - continue; - if (p->ssid_len && - (p->ssid_len != bss->ssid_len || - os_memcmp(p->ssid, bss->ssid, p->ssid_len) != 0)) - continue; - - if (bss_add_pmk_from_passphrase(bss, p->passphrase) < 0) - break; - } -} - - -void bss_update(struct wlantest *wt, struct wlantest_bss *bss, - struct ieee802_11_elems *elems) -{ - struct wpa_ie_data data; - int update = 0; - - if (bss->capab_info != bss->prev_capab_info) - update = 1; - - if (elems->ssid == NULL || elems->ssid_len > 32) { - wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon " - "frame for " MACSTR, MAC2STR(bss->bssid)); - bss->parse_error_reported = 1; - return; - } - - if (bss->ssid_len != elems->ssid_len || - os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0) { - wpa_printf(MSG_DEBUG, "Store SSID '%s' for BSSID " MACSTR, - wpa_ssid_txt(elems->ssid, elems->ssid_len), - MAC2STR(bss->bssid)); - os_memcpy(bss->ssid, elems->ssid, elems->ssid_len); - bss->ssid_len = elems->ssid_len; - bss_add_pmk(wt, bss); - } - - - if (elems->rsn_ie == NULL) { - if (bss->rsnie[0]) { - wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE removed", - MAC2STR(bss->bssid)); - bss->rsnie[0] = 0; - update = 1; - } - } else { - if (bss->rsnie[0] == 0 || - os_memcmp(bss->rsnie, elems->rsn_ie - 2, - elems->rsn_ie_len + 2) != 0) { - wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE " - "stored", MAC2STR(bss->bssid)); - wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2, - elems->rsn_ie_len + 2); - update = 1; - } - os_memcpy(bss->rsnie, elems->rsn_ie - 2, - elems->rsn_ie_len + 2); - } - - if (elems->wpa_ie == NULL) { - if (bss->wpaie[0]) { - wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE removed", - MAC2STR(bss->bssid)); - bss->wpaie[0] = 0; - update = 1; - } - } else { - if (bss->wpaie[0] == 0 || - os_memcmp(bss->wpaie, elems->wpa_ie - 2, - elems->wpa_ie_len + 2) != 0) { - wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE " - "stored", MAC2STR(bss->bssid)); - wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2, - elems->wpa_ie_len + 2); - update = 1; - } - os_memcpy(bss->wpaie, elems->wpa_ie - 2, - elems->wpa_ie_len + 2); - } - - if (!update) - return; - - bss->prev_capab_info = bss->capab_info; - bss->proto = 0; - bss->pairwise_cipher = 0; - bss->group_cipher = 0; - bss->key_mgmt = 0; - bss->rsn_capab = 0; - bss->mgmt_group_cipher = 0; - - if (bss->wpaie[0]) { - if (wpa_parse_wpa_ie_wpa(bss->wpaie, 2 + bss->wpaie[1], &data) - < 0) { - wpa_printf(MSG_INFO, "Failed to parse WPA IE from " - MACSTR, MAC2STR(bss->bssid)); - } else { - bss->proto |= data.proto; - bss->pairwise_cipher |= data.pairwise_cipher; - bss->group_cipher |= data.group_cipher; - bss->key_mgmt |= data.key_mgmt; - bss->rsn_capab = data.capabilities; - bss->mgmt_group_cipher |= data.mgmt_group_cipher; - } - } - - if (bss->rsnie[0]) { - if (wpa_parse_wpa_ie_rsn(bss->rsnie, 2 + bss->rsnie[1], &data) - < 0) { - wpa_printf(MSG_INFO, "Failed to parse RSN IE from " - MACSTR, MAC2STR(bss->bssid)); - } else { - bss->proto |= data.proto; - bss->pairwise_cipher |= data.pairwise_cipher; - bss->group_cipher |= data.group_cipher; - bss->key_mgmt |= data.key_mgmt; - bss->rsn_capab = data.capabilities; - bss->mgmt_group_cipher |= data.mgmt_group_cipher; - } - } - - if (!(bss->proto & WPA_PROTO_RSN) || - !(bss->rsn_capab & WPA_CAPABILITY_MFPC)) - bss->mgmt_group_cipher = 0; - - if (!bss->wpaie[0] && !bss->rsnie[0] && - (bss->capab_info & WLAN_CAPABILITY_PRIVACY)) - bss->group_cipher = WPA_CIPHER_WEP40; - - wpa_printf(MSG_INFO, "BSS " MACSTR - " proto=%s%s%s" - "pairwise=%s%s%s%s" - "group=%s%s%s%s%s%s" - "mgmt_group_cipher=%s" - "key_mgmt=%s%s%s%s%s%s%s%s" - "rsn_capab=%s%s%s%s%s", - MAC2STR(bss->bssid), - bss->proto == 0 ? "OPEN " : "", - bss->proto & WPA_PROTO_WPA ? "WPA " : "", - bss->proto & WPA_PROTO_RSN ? "WPA2 " : "", - bss->pairwise_cipher == 0 ? "N/A " : "", - bss->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "", - bss->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", - bss->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", - bss->group_cipher == 0 ? "N/A " : "", - bss->group_cipher & WPA_CIPHER_NONE ? "NONE " : "", - bss->group_cipher & WPA_CIPHER_WEP40 ? "WEP40 " : "", - bss->group_cipher & WPA_CIPHER_WEP104 ? "WEP104 " : "", - bss->group_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", - bss->group_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", - bss->mgmt_group_cipher & WPA_CIPHER_AES_128_CMAC ? "BIP " : - "N/A ", - bss->key_mgmt == 0 ? "N/A " : "", - bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "", - bss->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "", - bss->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "", - bss->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "", - bss->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "", - bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ? - "EAP-SHA256 " : "", - bss->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ? - "PSK-SHA256 " : "", - bss->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", - bss->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? - "NO_PAIRWISE " : "", - bss->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "", - bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "", - bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ? - "PEERKEY " : ""); -} - - -void bss_flush(struct wlantest *wt) -{ - struct wlantest_bss *bss, *n; - dl_list_for_each_safe(bss, n, &wt->bss, struct wlantest_bss, list) - bss_deinit(bss); -} diff --git a/wlantest/ccmp.c b/wlantest/ccmp.c deleted file mode 100644 index 6292ee0..0000000 --- a/wlantest/ccmp.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * CTR with CBC-MAC Protocol (CCMP) - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "crypto/aes.h" -#include "wlantest.h" - - -static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data, - u8 *aad, size_t *aad_len, u8 *nonce) -{ - u16 fc, stype, seq; - int qos = 0, addr4 = 0; - u8 *pos; - - nonce[0] = 0; - - fc = le_to_host16(hdr->frame_control); - stype = WLAN_FC_GET_STYPE(fc); - if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS)) - addr4 = 1; - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) { - fc &= ~0x0070; /* Mask subtype bits */ - if (stype & 0x08) { - const u8 *qc; - qos = 1; - fc &= ~WLAN_FC_ORDER; - qc = (const u8 *) (hdr + 1); - if (addr4) - qc += ETH_ALEN; - nonce[0] = qc[0] & 0x0f; - } - } else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) - nonce[0] |= 0x10; /* Management */ - - fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); - fc |= WLAN_FC_ISWEP; - WPA_PUT_LE16(aad, fc); - pos = aad + 2; - os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN); - pos += 3 * ETH_ALEN; - seq = le_to_host16(hdr->seq_ctrl); - seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */ - WPA_PUT_LE16(pos, seq); - pos += 2; - - os_memcpy(pos, hdr + 1, addr4 * ETH_ALEN + qos * 2); - pos += addr4 * ETH_ALEN; - if (qos) { - pos[0] &= ~0x70; - if (1 /* FIX: either device has SPP A-MSDU Capab = 0 */) - pos[0] &= ~0x80; - pos++; - *pos++ = 0x00; - } - - *aad_len = pos - aad; - - os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN); - nonce[7] = data[7]; /* PN5 */ - nonce[8] = data[6]; /* PN4 */ - nonce[9] = data[5]; /* PN3 */ - nonce[10] = data[4]; /* PN2 */ - nonce[11] = data[1]; /* PN1 */ - nonce[12] = data[0]; /* PN0 */ -} - - -static void xor_aes_block(u8 *dst, const u8 *src) -{ - u32 *d = (u32 *) dst; - u32 *s = (u32 *) src; - *d++ ^= *s++; - *d++ ^= *s++; - *d++ ^= *s++; - *d++ ^= *s++; -} - - -u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, - const u8 *data, size_t data_len, size_t *decrypted_len) -{ - u8 aad[2 + 30], nonce[13]; - size_t aad_len; - u8 b[AES_BLOCK_SIZE], x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; - void *aes; - const u8 *m, *mpos, *mic; - size_t mlen, last; - int i; - u8 *plain, *ppos; - u8 t[8]; - - if (data_len < 8 + 8) - return NULL; - - plain = os_malloc(data_len + AES_BLOCK_SIZE); - if (plain == NULL) - return NULL; - - aes = aes_encrypt_init(tk, 16); - if (aes == NULL) { - os_free(plain); - return NULL; - } - - m = data + 8; - mlen = data_len - 8 - 8; - last = mlen % AES_BLOCK_SIZE; - - os_memset(aad, 0, sizeof(aad)); - ccmp_aad_nonce(hdr, data, &aad[2], &aad_len, nonce); - WPA_PUT_BE16(aad, aad_len); - wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", &aad[2], aad_len); - wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); - - /* CCM: M=8 L=2, Adata=1, M' = (M-2)/2 = 3, L' = L-1 = 1 */ - - /* A_i = Flags | Nonce N | Counter i */ - a[0] = 0x01; /* Flags = L' */ - os_memcpy(&a[1], nonce, 13); - - /* Decryption */ - - mic = data + data_len - 8; - wpa_hexdump(MSG_EXCESSIVE, "CCMP U", mic, 8); - /* U = T XOR S_0; S_0 = E(K, A_0) */ - WPA_PUT_BE16(&a[14], 0); - aes_encrypt(aes, a, x); - for (i = 0; i < 8; i++) - t[i] = mic[i] ^ x[i]; - wpa_hexdump(MSG_EXCESSIVE, "CCMP T", t, 8); - - /* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */ - ppos = plain; - mpos = m; - for (i = 1; i <= mlen / AES_BLOCK_SIZE; i++) { - WPA_PUT_BE16(&a[14], i); - /* S_i = E(K, A_i) */ - aes_encrypt(aes, a, ppos); - xor_aes_block(ppos, mpos); - ppos += AES_BLOCK_SIZE; - mpos += AES_BLOCK_SIZE; - } - if (last) { - WPA_PUT_BE16(&a[14], i); - aes_encrypt(aes, a, ppos); - /* XOR zero-padded last block */ - for (i = 0; i < last; i++) - *ppos++ ^= *mpos++; - } - wpa_hexdump(MSG_EXCESSIVE, "CCMP decrypted", plain, mlen); - - /* Authentication */ - /* B_0: Flags | Nonce N | l(m) */ - b[0] = 0x40 /* Adata */ | (3 /* M' */ << 3) | 1 /* L' */; - os_memcpy(&b[1], nonce, 13); - WPA_PUT_BE16(&b[14], mlen); - - wpa_hexdump(MSG_EXCESSIVE, "CCMP B_0", b, AES_BLOCK_SIZE); - aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */ - - wpa_hexdump(MSG_EXCESSIVE, "CCMP B_1", aad, AES_BLOCK_SIZE); - xor_aes_block(aad, x); - aes_encrypt(aes, aad, x); /* X_2 = E(K, X_1 XOR B_1) */ - - wpa_hexdump(MSG_EXCESSIVE, "CCMP B_2", &aad[AES_BLOCK_SIZE], - AES_BLOCK_SIZE); - xor_aes_block(&aad[AES_BLOCK_SIZE], x); - aes_encrypt(aes, &aad[AES_BLOCK_SIZE], x); /* X_3 = E(K, X_2 XOR B_2) - */ - - ppos = plain; - for (i = 0; i < mlen / AES_BLOCK_SIZE; i++) { - /* X_i+1 = E(K, X_i XOR B_i) */ - xor_aes_block(x, ppos); - ppos += AES_BLOCK_SIZE; - aes_encrypt(aes, x, x); - } - if (last) { - /* XOR zero-padded last block */ - for (i = 0; i < last; i++) - x[i] ^= *ppos++; - aes_encrypt(aes, x, x); - } - - aes_encrypt_deinit(aes); - - if (os_memcmp(x, t, 8) != 0) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - wpa_printf(MSG_INFO, "Invalid CCMP MIC in frame: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3), - WLAN_GET_SEQ_SEQ(seq_ctrl), - WLAN_GET_SEQ_FRAG(seq_ctrl)); - wpa_hexdump(MSG_DEBUG, "CCMP decrypted", plain, mlen); - os_free(plain); - return NULL; - } - - *decrypted_len = mlen; - return plain; -} - - -void ccmp_get_pn(u8 *pn, const u8 *data) -{ - pn[0] = data[7]; /* PN5 */ - pn[1] = data[6]; /* PN4 */ - pn[2] = data[5]; /* PN3 */ - pn[3] = data[4]; /* PN2 */ - pn[4] = data[1]; /* PN1 */ - pn[5] = data[0]; /* PN0 */ -} - - -u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, - u8 *pn, int keyid, size_t *encrypted_len) -{ - u8 aad[2 + 30], nonce[13]; - size_t aad_len; - u8 b[AES_BLOCK_SIZE], x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; - void *aes; - u8 *crypt, *pos, *ppos, *mpos; - size_t plen, last; - struct ieee80211_hdr *hdr; - int i; - - if (len < hdrlen || hdrlen < 24) - return NULL; - plen = len - hdrlen; - last = plen % AES_BLOCK_SIZE; - - crypt = os_malloc(hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE); - if (crypt == NULL) - return NULL; - - os_memcpy(crypt, frame, hdrlen); - hdr = (struct ieee80211_hdr *) crypt; - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - pos = crypt + hdrlen; - *pos++ = pn[5]; /* PN0 */ - *pos++ = pn[4]; /* PN1 */ - *pos++ = 0x00; /* Rsvd */ - *pos++ = 0x20 | (keyid << 6); - *pos++ = pn[3]; /* PN2 */ - *pos++ = pn[2]; /* PN3 */ - *pos++ = pn[1]; /* PN4 */ - *pos++ = pn[0]; /* PN5 */ - - aes = aes_encrypt_init(tk, 16); - if (aes == NULL) { - os_free(crypt); - return NULL; - } - - os_memset(aad, 0, sizeof(aad)); - ccmp_aad_nonce(hdr, crypt + hdrlen, &aad[2], &aad_len, nonce); - WPA_PUT_BE16(aad, aad_len); - wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", &aad[2], aad_len); - wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); - - /* Authentication */ - /* B_0: Flags | Nonce N | l(m) */ - b[0] = 0x40 /* Adata */ | (3 /* M' */ << 3) | 1 /* L' */; - os_memcpy(&b[1], nonce, 13); - WPA_PUT_BE16(&b[14], plen); - - wpa_hexdump(MSG_EXCESSIVE, "CCMP B_0", b, AES_BLOCK_SIZE); - aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */ - - wpa_hexdump(MSG_EXCESSIVE, "CCMP B_1", aad, AES_BLOCK_SIZE); - xor_aes_block(aad, x); - aes_encrypt(aes, aad, x); /* X_2 = E(K, X_1 XOR B_1) */ - - wpa_hexdump(MSG_EXCESSIVE, "CCMP B_2", &aad[AES_BLOCK_SIZE], - AES_BLOCK_SIZE); - xor_aes_block(&aad[AES_BLOCK_SIZE], x); - aes_encrypt(aes, &aad[AES_BLOCK_SIZE], x); /* X_3 = E(K, X_2 XOR B_2) - */ - - ppos = frame + hdrlen; - for (i = 0; i < plen / AES_BLOCK_SIZE; i++) { - /* X_i+1 = E(K, X_i XOR B_i) */ - xor_aes_block(x, ppos); - ppos += AES_BLOCK_SIZE; - aes_encrypt(aes, x, x); - } - if (last) { - /* XOR zero-padded last block */ - for (i = 0; i < last; i++) - x[i] ^= *ppos++; - aes_encrypt(aes, x, x); - } - - /* Encryption */ - - /* CCM: M=8 L=2, Adata=1, M' = (M-2)/2 = 3, L' = L-1 = 1 */ - - /* A_i = Flags | Nonce N | Counter i */ - a[0] = 0x01; /* Flags = L' */ - os_memcpy(&a[1], nonce, 13); - - ppos = crypt + hdrlen + 8; - - /* crypt = msg XOR (S_1 | S_2 | ... | S_n) */ - mpos = frame + hdrlen; - for (i = 1; i <= plen / AES_BLOCK_SIZE; i++) { - WPA_PUT_BE16(&a[14], i); - /* S_i = E(K, A_i) */ - aes_encrypt(aes, a, ppos); - xor_aes_block(ppos, mpos); - ppos += AES_BLOCK_SIZE; - mpos += AES_BLOCK_SIZE; - } - if (last) { - WPA_PUT_BE16(&a[14], i); - aes_encrypt(aes, a, ppos); - /* XOR zero-padded last block */ - for (i = 0; i < last; i++) - *ppos++ ^= *mpos++; - } - - wpa_hexdump(MSG_EXCESSIVE, "CCMP T", x, 8); - /* U = T XOR S_0; S_0 = E(K, A_0) */ - WPA_PUT_BE16(&a[14], 0); - aes_encrypt(aes, a, b); - for (i = 0; i < 8; i++) - ppos[i] = x[i] ^ b[i]; - wpa_hexdump(MSG_EXCESSIVE, "CCMP U", ppos, 8); - - wpa_hexdump(MSG_EXCESSIVE, "CCMP encrypted", crypt + hdrlen + 8, plen); - - aes_encrypt_deinit(aes); - - *encrypted_len = hdrlen + 8 + plen + 8; - - return crypt; -} diff --git a/wlantest/crc32.c b/wlantest/crc32.c deleted file mode 100644 index adbbda5..0000000 --- a/wlantest/crc32.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 32-bit CRC for FCS calculation - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" - -/* - * IEEE 802.11 FCS CRC32 - * G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + - * x^5 + x^4 + x^2 + x + 1 - */ -static const u32 crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d -}; - - -u32 crc32(const u8 *frame, size_t frame_len) -{ - size_t i; - u32 crc; - - crc = 0xFFFFFFFF; - for (i = 0; i < frame_len; i++) - crc = crc32_table[(crc ^ frame[i]) & 0xff] ^ (crc >> 8); - - return ~crc; -} diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c deleted file mode 100644 index bed5d6c..0000000 --- a/wlantest/ctrl.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * wlantest control interface - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <sys/un.h> - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/defs.h" -#include "common/version.h" -#include "common/ieee802_11_defs.h" -#include "wlantest.h" -#include "wlantest_ctrl.h" - - -static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr, - size_t *len) -{ - u8 *pos = buf; - - while (pos + 8 <= buf + buflen) { - enum wlantest_ctrl_attr a; - size_t alen; - a = WPA_GET_BE32(pos); - pos += 4; - alen = WPA_GET_BE32(pos); - pos += 4; - if (pos + alen > buf + buflen) { - wpa_printf(MSG_DEBUG, "Invalid control message " - "attribute"); - return NULL; - } - if (a == attr) { - *len = alen; - return pos; - } - pos += alen; - } - - return NULL; -} - - -static u8 * attr_get_macaddr(u8 *buf, size_t buflen, - enum wlantest_ctrl_attr attr) -{ - u8 *addr; - size_t addr_len; - addr = attr_get(buf, buflen, attr, &addr_len); - if (addr && addr_len != ETH_ALEN) - addr = NULL; - return addr; -} - - -static int attr_get_int(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr) -{ - u8 *pos; - size_t len; - pos = attr_get(buf, buflen, attr, &len); - if (pos == NULL || len != 4) - return -1; - return WPA_GET_BE32(pos); -} - - -static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr, - const char *str) -{ - size_t len = os_strlen(str); - - if (pos == NULL || end - pos < 8 + len) - return NULL; - WPA_PUT_BE32(pos, attr); - pos += 4; - WPA_PUT_BE32(pos, len); - pos += 4; - os_memcpy(pos, str, len); - pos += len; - return pos; -} - - -static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr, - u32 val) -{ - if (pos == NULL || end - pos < 12) - return NULL; - WPA_PUT_BE32(pos, attr); - pos += 4; - WPA_PUT_BE32(pos, 4); - pos += 4; - WPA_PUT_BE32(pos, val); - pos += 4; - return pos; -} - - -static void ctrl_disconnect(struct wlantest *wt, int sock) -{ - int i; - wpa_printf(MSG_DEBUG, "Disconnect control interface connection %d", - sock); - for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) { - if (wt->ctrl_socks[i] == sock) { - close(wt->ctrl_socks[i]); - eloop_unregister_read_sock(wt->ctrl_socks[i]); - wt->ctrl_socks[i] = -1; - break; - } - } -} - - -static void ctrl_send(struct wlantest *wt, int sock, const u8 *buf, - size_t len) -{ - if (send(sock, buf, len, 0) < 0) { - wpa_printf(MSG_INFO, "send(ctrl): %s", strerror(errno)); - ctrl_disconnect(wt, sock); - } -} - - -static void ctrl_send_simple(struct wlantest *wt, int sock, - enum wlantest_ctrl_cmd cmd) -{ - u8 buf[4]; - WPA_PUT_BE32(buf, cmd); - ctrl_send(wt, sock, buf, sizeof(buf)); -} - - -static struct wlantest_bss * ctrl_get_bss(struct wlantest *wt, int sock, - u8 *cmd, size_t clen) -{ - struct wlantest_bss *bss; - u8 *pos; - size_t len; - - pos = attr_get(cmd, clen, WLANTEST_ATTR_BSSID, &len); - if (pos == NULL || len != ETH_ALEN) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return NULL; - } - - bss = bss_find(wt, pos); - if (bss == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return NULL; - } - - return bss; -} - - -static struct wlantest_sta * ctrl_get_sta(struct wlantest *wt, int sock, - u8 *cmd, size_t clen, - struct wlantest_bss *bss) -{ - struct wlantest_sta *sta; - u8 *pos; - size_t len; - - if (bss == NULL) - return NULL; - - pos = attr_get(cmd, clen, WLANTEST_ATTR_STA_ADDR, &len); - if (pos == NULL || len != ETH_ALEN) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return NULL; - } - - sta = sta_find(bss, pos); - if (sta == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return NULL; - } - - return sta; -} - - -static struct wlantest_sta * ctrl_get_sta2(struct wlantest *wt, int sock, - u8 *cmd, size_t clen, - struct wlantest_bss *bss) -{ - struct wlantest_sta *sta; - u8 *pos; - size_t len; - - if (bss == NULL) - return NULL; - - pos = attr_get(cmd, clen, WLANTEST_ATTR_STA2_ADDR, &len); - if (pos == NULL || len != ETH_ALEN) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return NULL; - } - - sta = sta_find(bss, pos); - if (sta == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return NULL; - } - - return sta; -} - - -static void ctrl_list_bss(struct wlantest *wt, int sock) -{ - u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos, *len; - struct wlantest_bss *bss; - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID); - pos += 4; - len = pos; /* to be filled */ - pos += 4; - - dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) { - if (pos + ETH_ALEN > buf + WLANTEST_CTRL_MAX_RESP_LEN) - break; - os_memcpy(pos, bss->bssid, ETH_ALEN); - pos += ETH_ALEN; - } - - WPA_PUT_BE32(len, pos - len - 4); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_list_sta(struct wlantest *wt, int sock, u8 *cmd, size_t clen) -{ - u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos, *len; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - if (bss == NULL) - return; - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR); - pos += 4; - len = pos; /* to be filled */ - pos += 4; - - dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) { - if (pos + ETH_ALEN > buf + WLANTEST_CTRL_MAX_RESP_LEN) - break; - os_memcpy(pos, sta->addr, ETH_ALEN); - pos += ETH_ALEN; - } - - WPA_PUT_BE32(len, pos - len - 4); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_flush(struct wlantest *wt, int sock) -{ - wpa_printf(MSG_DEBUG, "Drop all collected BSS data"); - bss_flush(wt); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); -} - - -static void ctrl_clear_sta_counters(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - sta = ctrl_get_sta(wt, sock, cmd, clen, bss); - if (sta == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - os_memset(sta->counters, 0, sizeof(sta->counters)); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); -} - - -static void ctrl_clear_bss_counters(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - struct wlantest_bss *bss; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - if (bss == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - os_memset(bss->counters, 0, sizeof(bss->counters)); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); -} - - -static void ctrl_clear_tdls_counters(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - struct wlantest_sta *sta2; - struct wlantest_tdls *tdls; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - sta = ctrl_get_sta(wt, sock, cmd, clen, bss); - sta2 = ctrl_get_sta2(wt, sock, cmd, clen, bss); - if (sta == NULL || sta2 == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if ((tdls->init == sta && tdls->resp == sta2) || - (tdls->init == sta2 && tdls->resp == sta)) - os_memset(tdls->counters, 0, sizeof(tdls->counters)); - } - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); -} - - -static void ctrl_get_sta_counter(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - u8 *addr; - size_t addr_len; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u32 counter; - u8 buf[4 + 12], *end, *pos; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - sta = ctrl_get_sta(wt, sock, cmd, clen, bss); - if (sta == NULL) - return; - - addr = attr_get(cmd, clen, WLANTEST_ATTR_STA_COUNTER, &addr_len); - if (addr == NULL || addr_len != 4) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - counter = WPA_GET_BE32(addr); - if (counter >= NUM_WLANTEST_STA_COUNTER) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - pos = attr_add_be32(pos, end, WLANTEST_ATTR_COUNTER, - sta->counters[counter]); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_get_bss_counter(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - u8 *addr; - size_t addr_len; - struct wlantest_bss *bss; - u32 counter; - u8 buf[4 + 12], *end, *pos; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - if (bss == NULL) - return; - - addr = attr_get(cmd, clen, WLANTEST_ATTR_BSS_COUNTER, &addr_len); - if (addr == NULL || addr_len != 4) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - counter = WPA_GET_BE32(addr); - if (counter >= NUM_WLANTEST_BSS_COUNTER) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - pos = attr_add_be32(pos, end, WLANTEST_ATTR_COUNTER, - bss->counters[counter]); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_get_tdls_counter(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - u8 *addr; - size_t addr_len; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - struct wlantest_sta *sta2; - struct wlantest_tdls *tdls; - u32 counter; - u8 buf[4 + 12], *end, *pos; - int found = 0; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - sta = ctrl_get_sta(wt, sock, cmd, clen, bss); - sta2 = ctrl_get_sta2(wt, sock, cmd, clen, bss); - if (sta == NULL || sta2 == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - addr = attr_get(cmd, clen, WLANTEST_ATTR_TDLS_COUNTER, &addr_len); - if (addr == NULL || addr_len != 4) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - counter = WPA_GET_BE32(addr); - if (counter >= NUM_WLANTEST_TDLS_COUNTER) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if (tdls->init == sta && tdls->resp == sta2) { - found = 1; - break; - } - } - - if (!found) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - pos = attr_add_be32(pos, end, WLANTEST_ATTR_COUNTER, - tdls->counters[counter]); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void build_mgmt_hdr(struct ieee80211_mgmt *mgmt, - struct wlantest_bss *bss, struct wlantest_sta *sta, - int sender_ap, int stype) -{ - os_memset(mgmt, 0, 24); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); - if (sender_ap) { - if (sta) - os_memcpy(mgmt->da, sta->addr, ETH_ALEN); - else - os_memset(mgmt->da, 0xff, ETH_ALEN); - os_memcpy(mgmt->sa, bss->bssid, ETH_ALEN); - } else { - os_memcpy(mgmt->da, bss->bssid, ETH_ALEN); - os_memcpy(mgmt->sa, sta->addr, ETH_ALEN); - } - os_memcpy(mgmt->bssid, bss->bssid, ETH_ALEN); -} - - -static int ctrl_inject_auth(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, int sender_ap, - enum wlantest_inject_protection prot) -{ - struct ieee80211_mgmt mgmt; - - if (prot != WLANTEST_INJECT_NORMAL && - prot != WLANTEST_INJECT_UNPROTECTED) - return -1; /* Authentication frame is never protected */ - if (sta == NULL) - return -1; /* No broadcast Authentication frames */ - - if (sender_ap) - wpa_printf(MSG_INFO, "INJECT: Auth " MACSTR " -> " MACSTR, - MAC2STR(bss->bssid), MAC2STR(sta->addr)); - else - wpa_printf(MSG_INFO, "INJECT: Auth " MACSTR " -> " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - build_mgmt_hdr(&mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_AUTH); - - mgmt.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN); - mgmt.u.auth.auth_transaction = host_to_le16(1); - mgmt.u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS); - - return wlantest_inject(wt, bss, sta, (u8 *) &mgmt, 24 + 6, - WLANTEST_INJECT_UNPROTECTED); -} - - -static int ctrl_inject_assocreq(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, int sender_ap, - enum wlantest_inject_protection prot) -{ - u8 *buf; - struct ieee80211_mgmt *mgmt; - int ret; - - if (prot != WLANTEST_INJECT_NORMAL && - prot != WLANTEST_INJECT_UNPROTECTED) - return -1; /* Association Request frame is never protected */ - if (sta == NULL) - return -1; /* No broadcast Association Request frames */ - if (sender_ap) - return -1; /* No Association Request frame sent by AP */ - if (sta->assocreq_ies == NULL) { - wpa_printf(MSG_INFO, "INJECT: No previous (Re)Association " - "Request available for " MACSTR, - MAC2STR(sta->addr)); - return -1; - } - - wpa_printf(MSG_INFO, "INJECT: AssocReq " MACSTR " -> " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - buf = os_malloc(sizeof(*mgmt) + sta->assocreq_ies_len); - if (buf == NULL) - return -1; - mgmt = (struct ieee80211_mgmt *) buf; - - build_mgmt_hdr(mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_ASSOC_REQ); - - mgmt->u.assoc_req.capab_info = host_to_le16(sta->assocreq_capab_info); - mgmt->u.assoc_req.listen_interval = - host_to_le16(sta->assocreq_listen_int); - os_memcpy(mgmt->u.assoc_req.variable, sta->assocreq_ies, - sta->assocreq_ies_len); - - ret = wlantest_inject(wt, bss, sta, buf, - 24 + 4 + sta->assocreq_ies_len, - WLANTEST_INJECT_UNPROTECTED); - os_free(buf); - return ret; -} - - -static int ctrl_inject_reassocreq(struct wlantest *wt, - struct wlantest_bss *bss, - struct wlantest_sta *sta, int sender_ap, - enum wlantest_inject_protection prot) -{ - u8 *buf; - struct ieee80211_mgmt *mgmt; - int ret; - - if (prot != WLANTEST_INJECT_NORMAL && - prot != WLANTEST_INJECT_UNPROTECTED) - return -1; /* Reassociation Request frame is never protected */ - if (sta == NULL) - return -1; /* No broadcast Reassociation Request frames */ - if (sender_ap) - return -1; /* No Reassociation Request frame sent by AP */ - if (sta->assocreq_ies == NULL) { - wpa_printf(MSG_INFO, "INJECT: No previous (Re)Association " - "Request available for " MACSTR, - MAC2STR(sta->addr)); - return -1; - } - - wpa_printf(MSG_INFO, "INJECT: ReassocReq " MACSTR " -> " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - buf = os_malloc(sizeof(*mgmt) + sta->assocreq_ies_len); - if (buf == NULL) - return -1; - mgmt = (struct ieee80211_mgmt *) buf; - - build_mgmt_hdr(mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_REASSOC_REQ); - - mgmt->u.reassoc_req.capab_info = - host_to_le16(sta->assocreq_capab_info); - mgmt->u.reassoc_req.listen_interval = - host_to_le16(sta->assocreq_listen_int); - os_memcpy(mgmt->u.reassoc_req.current_ap, bss->bssid, ETH_ALEN); - os_memcpy(mgmt->u.reassoc_req.variable, sta->assocreq_ies, - sta->assocreq_ies_len); - - ret = wlantest_inject(wt, bss, sta, buf, - 24 + 10 + sta->assocreq_ies_len, - WLANTEST_INJECT_UNPROTECTED); - os_free(buf); - return ret; -} - - -static int ctrl_inject_deauth(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, int sender_ap, - enum wlantest_inject_protection prot) -{ - struct ieee80211_mgmt mgmt; - - if (sender_ap) { - if (sta) - wpa_printf(MSG_INFO, "INJECT: Deauth " MACSTR " -> " - MACSTR, - MAC2STR(bss->bssid), MAC2STR(sta->addr)); - else - wpa_printf(MSG_INFO, "INJECT: Deauth " MACSTR - " -> broadcast", MAC2STR(bss->bssid)); - } else - wpa_printf(MSG_INFO, "INJECT: Deauth " MACSTR " -> " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - build_mgmt_hdr(&mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_DEAUTH); - - mgmt.u.deauth.reason_code = host_to_le16(WLAN_REASON_UNSPECIFIED); - - return wlantest_inject(wt, bss, sta, (u8 *) &mgmt, 24 + 2, prot); -} - - -static int ctrl_inject_disassoc(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, int sender_ap, - enum wlantest_inject_protection prot) -{ - struct ieee80211_mgmt mgmt; - - if (sender_ap) { - if (sta) - wpa_printf(MSG_INFO, "INJECT: Disassoc " MACSTR " -> " - MACSTR, - MAC2STR(bss->bssid), MAC2STR(sta->addr)); - else - wpa_printf(MSG_INFO, "INJECT: Disassoc " MACSTR - " -> broadcast", MAC2STR(bss->bssid)); - } else - wpa_printf(MSG_INFO, "INJECT: Disassoc " MACSTR " -> " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - build_mgmt_hdr(&mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_DISASSOC); - - mgmt.u.disassoc.reason_code = host_to_le16(WLAN_REASON_UNSPECIFIED); - - return wlantest_inject(wt, bss, sta, (u8 *) &mgmt, 24 + 2, prot); -} - - -static int ctrl_inject_saqueryreq(struct wlantest *wt, - struct wlantest_bss *bss, - struct wlantest_sta *sta, int sender_ap, - enum wlantest_inject_protection prot) -{ - struct ieee80211_mgmt mgmt; - - if (sta == NULL) - return -1; /* No broadcast SA Query frames */ - - if (sender_ap) - wpa_printf(MSG_INFO, "INJECT: SA Query Request " MACSTR " -> " - MACSTR, MAC2STR(bss->bssid), MAC2STR(sta->addr)); - else - wpa_printf(MSG_INFO, "INJECT: SA Query Request " MACSTR " -> " - MACSTR, MAC2STR(sta->addr), MAC2STR(bss->bssid)); - build_mgmt_hdr(&mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_ACTION); - - mgmt.u.action.category = WLAN_ACTION_SA_QUERY; - mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; - mgmt.u.action.u.sa_query_req.trans_id[0] = 0x12; - mgmt.u.action.u.sa_query_req.trans_id[1] = 0x34; - os_memcpy(sender_ap ? sta->ap_sa_query_tr : sta->sta_sa_query_tr, - mgmt.u.action.u.sa_query_req.trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - return wlantest_inject(wt, bss, sta, (u8 *) &mgmt, 24 + 4, prot); -} - - -static void ctrl_inject(struct wlantest *wt, int sock, u8 *cmd, size_t clen) -{ - u8 *bssid, *sta_addr; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - int frame, sender_ap, prot; - int ret = 0; - - bssid = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_BSSID); - sta_addr = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_STA_ADDR); - frame = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_FRAME); - sender_ap = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_SENDER_AP); - if (sender_ap < 0) - sender_ap = 0; - prot = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_PROTECTION); - if (bssid == NULL || sta_addr == NULL || frame < 0 || prot < 0) { - wpa_printf(MSG_INFO, "Invalid inject command parameters"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - bss = bss_find(wt, bssid); - if (bss == NULL) { - wpa_printf(MSG_INFO, "BSS not found for inject command"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - if (is_broadcast_ether_addr(sta_addr)) { - if (!sender_ap) { - wpa_printf(MSG_INFO, "Invalid broadcast inject " - "command without sender_ap set"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } sta = NULL; - } else { - sta = sta_find(bss, sta_addr); - if (sta == NULL) { - wpa_printf(MSG_INFO, "Station not found for inject " - "command"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - } - - switch (frame) { - case WLANTEST_FRAME_AUTH: - ret = ctrl_inject_auth(wt, bss, sta, sender_ap, prot); - break; - case WLANTEST_FRAME_ASSOCREQ: - ret = ctrl_inject_assocreq(wt, bss, sta, sender_ap, prot); - break; - case WLANTEST_FRAME_REASSOCREQ: - ret = ctrl_inject_reassocreq(wt, bss, sta, sender_ap, prot); - break; - case WLANTEST_FRAME_DEAUTH: - ret = ctrl_inject_deauth(wt, bss, sta, sender_ap, prot); - break; - case WLANTEST_FRAME_DISASSOC: - ret = ctrl_inject_disassoc(wt, bss, sta, sender_ap, prot); - break; - case WLANTEST_FRAME_SAQUERYREQ: - ret = ctrl_inject_saqueryreq(wt, bss, sta, sender_ap, prot); - break; - default: - wpa_printf(MSG_INFO, "Unsupported inject command frame %d", - frame); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - if (ret) - wpa_printf(MSG_INFO, "Failed to inject frame"); - else - wpa_printf(MSG_INFO, "Frame injected successfully"); - ctrl_send_simple(wt, sock, ret == 0 ? WLANTEST_CTRL_SUCCESS : - WLANTEST_CTRL_FAILURE); -} - - -static void ctrl_version(struct wlantest *wt, int sock) -{ - u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos; - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - pos = attr_add_str(pos, buf + sizeof(buf), WLANTEST_ATTR_VERSION, - VERSION_STR); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_add_passphrase(struct wlantest *wt, int sock, u8 *cmd, - size_t clen) -{ - u8 *passphrase; - size_t len; - struct wlantest_passphrase *p, *pa; - u8 *bssid; - - passphrase = attr_get(cmd, clen, WLANTEST_ATTR_PASSPHRASE, &len); - if (passphrase == NULL) { - u8 *wepkey; - char *key; - enum wlantest_ctrl_cmd res; - - wepkey = attr_get(cmd, clen, WLANTEST_ATTR_WEPKEY, &len); - if (wepkey == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - key = os_zalloc(len + 1); - if (key == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - os_memcpy(key, wepkey, len); - if (add_wep(wt, key) < 0) - res = WLANTEST_CTRL_FAILURE; - else - res = WLANTEST_CTRL_SUCCESS; - os_free(key); - ctrl_send_simple(wt, sock, res); - return; - } - - if (len < 8 || len > 63) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - p = os_zalloc(sizeof(*p)); - if (p == NULL) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - os_memcpy(p->passphrase, passphrase, len); - wpa_printf(MSG_INFO, "Add passphrase '%s'", p->passphrase); - - bssid = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_BSSID); - if (bssid) { - os_memcpy(p->bssid, bssid, ETH_ALEN); - wpa_printf(MSG_INFO, "Limit passphrase for BSSID " MACSTR, - MAC2STR(p->bssid)); - } - - dl_list_for_each(pa, &wt->passphrase, struct wlantest_passphrase, list) - { - if (os_strcmp(p->passphrase, pa->passphrase) == 0 && - os_memcmp(p->bssid, pa->bssid, ETH_ALEN) == 0) { - wpa_printf(MSG_INFO, "Passphrase was already known"); - os_free(p); - p = NULL; - break; - } - } - - if (p) { - struct wlantest_bss *bss; - dl_list_add(&wt->passphrase, &p->list); - dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) { - if (bssid && - os_memcmp(p->bssid, bss->bssid, ETH_ALEN) != 0) - continue; - bss_add_pmk_from_passphrase(bss, p->passphrase); - } - } - - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); -} - - -static void info_print_proto(char *buf, size_t len, int proto) -{ - char *pos, *end; - - if (proto == 0) { - os_snprintf(buf, len, "OPEN"); - return; - } - - pos = buf; - end = buf + len; - - if (proto & WPA_PROTO_WPA) - pos += os_snprintf(pos, end - pos, "%sWPA", - pos == buf ? "" : " "); - if (proto & WPA_PROTO_RSN) - pos += os_snprintf(pos, end - pos, "%sWPA2", - pos == buf ? "" : " "); -} - - -static void info_print_cipher(char *buf, size_t len, int cipher) -{ - char *pos, *end; - - if (cipher == 0) { - os_snprintf(buf, len, "N/A"); - return; - } - - pos = buf; - end = buf + len; - - if (cipher & WPA_CIPHER_NONE) - pos += os_snprintf(pos, end - pos, "%sNONE", - pos == buf ? "" : " "); - if (cipher & WPA_CIPHER_WEP40) - pos += os_snprintf(pos, end - pos, "%sWEP40", - pos == buf ? "" : " "); - if (cipher & WPA_CIPHER_WEP104) - pos += os_snprintf(pos, end - pos, "%sWEP104", - pos == buf ? "" : " "); - if (cipher & WPA_CIPHER_TKIP) - pos += os_snprintf(pos, end - pos, "%sTKIP", - pos == buf ? "" : " "); - if (cipher & WPA_CIPHER_CCMP) - pos += os_snprintf(pos, end - pos, "%sCCMP", - pos == buf ? "" : " "); - if (cipher & WPA_CIPHER_AES_128_CMAC) - pos += os_snprintf(pos, end - pos, "%sBIP", - pos == buf ? "" : " "); -} - - -static void info_print_key_mgmt(char *buf, size_t len, int key_mgmt) -{ - char *pos, *end; - - if (key_mgmt == 0) { - os_snprintf(buf, len, "N/A"); - return; - } - - pos = buf; - end = buf + len; - - if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) - pos += os_snprintf(pos, end - pos, "%sEAP", - pos == buf ? "" : " "); - if (key_mgmt & WPA_KEY_MGMT_PSK) - pos += os_snprintf(pos, end - pos, "%sPSK", - pos == buf ? "" : " "); - if (key_mgmt & WPA_KEY_MGMT_WPA_NONE) - pos += os_snprintf(pos, end - pos, "%sWPA-NONE", - pos == buf ? "" : " "); - if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) - pos += os_snprintf(pos, end - pos, "%sFT-EAP", - pos == buf ? "" : " "); - if (key_mgmt & WPA_KEY_MGMT_FT_PSK) - pos += os_snprintf(pos, end - pos, "%sFT-PSK", - pos == buf ? "" : " "); - if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) - pos += os_snprintf(pos, end - pos, "%sEAP-SHA256", - pos == buf ? "" : " "); - if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) - pos += os_snprintf(pos, end - pos, "%sPSK-SHA256", - pos == buf ? "" : " "); -} - - -static void info_print_rsn_capab(char *buf, size_t len, int capab) -{ - char *pos, *end; - - pos = buf; - end = buf + len; - - if (capab & WPA_CAPABILITY_PREAUTH) - pos += os_snprintf(pos, end - pos, "%sPREAUTH", - pos == buf ? "" : " "); - if (capab & WPA_CAPABILITY_NO_PAIRWISE) - pos += os_snprintf(pos, end - pos, "%sNO_PAIRWISE", - pos == buf ? "" : " "); - if (capab & WPA_CAPABILITY_MFPR) - pos += os_snprintf(pos, end - pos, "%sMFPR", - pos == buf ? "" : " "); - if (capab & WPA_CAPABILITY_MFPC) - pos += os_snprintf(pos, end - pos, "%sMFPC", - pos == buf ? "" : " "); - if (capab & WPA_CAPABILITY_PEERKEY_ENABLED) - pos += os_snprintf(pos, end - pos, "%sPEERKEY", - pos == buf ? "" : " "); -} - - -static void info_print_state(char *buf, size_t len, int state) -{ - switch (state) { - case STATE1: - os_strlcpy(buf, "NOT-AUTH", len); - break; - case STATE2: - os_strlcpy(buf, "AUTH", len); - break; - case STATE3: - os_strlcpy(buf, "AUTH+ASSOC", len); - break; - } -} - - -static void info_print_gtk(char *buf, size_t len, struct wlantest_sta *sta) -{ - size_t pos; - - pos = os_snprintf(buf, len, "IDX=%d,GTK=", sta->gtk_idx); - wpa_snprintf_hex(buf + pos, len - pos, sta->gtk, sta->gtk_len); -} - - -static void ctrl_info_sta(struct wlantest *wt, int sock, u8 *cmd, size_t clen) -{ - u8 *addr; - size_t addr_len; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - enum wlantest_sta_info info; - u8 buf[4 + 108], *end, *pos; - char resp[100]; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - sta = ctrl_get_sta(wt, sock, cmd, clen, bss); - if (sta == NULL) - return; - - addr = attr_get(cmd, clen, WLANTEST_ATTR_STA_INFO, &addr_len); - if (addr == NULL || addr_len != 4) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - info = WPA_GET_BE32(addr); - - resp[0] = '\0'; - switch (info) { - case WLANTEST_STA_INFO_PROTO: - info_print_proto(resp, sizeof(resp), sta->proto); - break; - case WLANTEST_STA_INFO_PAIRWISE: - info_print_cipher(resp, sizeof(resp), sta->pairwise_cipher); - break; - case WLANTEST_STA_INFO_KEY_MGMT: - info_print_key_mgmt(resp, sizeof(resp), sta->key_mgmt); - break; - case WLANTEST_STA_INFO_RSN_CAPAB: - info_print_rsn_capab(resp, sizeof(resp), sta->rsn_capab); - break; - case WLANTEST_STA_INFO_STATE: - info_print_state(resp, sizeof(resp), sta->state); - break; - case WLANTEST_STA_INFO_GTK: - info_print_gtk(resp, sizeof(resp), sta); - break; - default: - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - pos = attr_add_str(pos, end, WLANTEST_ATTR_INFO, resp); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_info_bss(struct wlantest *wt, int sock, u8 *cmd, size_t clen) -{ - u8 *addr; - size_t addr_len; - struct wlantest_bss *bss; - enum wlantest_bss_info info; - u8 buf[4 + 108], *end, *pos; - char resp[100]; - - bss = ctrl_get_bss(wt, sock, cmd, clen); - if (bss == NULL) - return; - - addr = attr_get(cmd, clen, WLANTEST_ATTR_BSS_INFO, &addr_len); - if (addr == NULL || addr_len != 4) { - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - info = WPA_GET_BE32(addr); - - resp[0] = '\0'; - switch (info) { - case WLANTEST_BSS_INFO_PROTO: - info_print_proto(resp, sizeof(resp), bss->proto); - break; - case WLANTEST_BSS_INFO_PAIRWISE: - info_print_cipher(resp, sizeof(resp), bss->pairwise_cipher); - break; - case WLANTEST_BSS_INFO_GROUP: - info_print_cipher(resp, sizeof(resp), bss->group_cipher); - break; - case WLANTEST_BSS_INFO_GROUP_MGMT: - info_print_cipher(resp, sizeof(resp), bss->mgmt_group_cipher); - break; - case WLANTEST_BSS_INFO_KEY_MGMT: - info_print_key_mgmt(resp, sizeof(resp), bss->key_mgmt); - break; - case WLANTEST_BSS_INFO_RSN_CAPAB: - info_print_rsn_capab(resp, sizeof(resp), bss->rsn_capab); - break; - default: - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS); - pos += 4; - pos = attr_add_str(pos, end, WLANTEST_ATTR_INFO, resp); - ctrl_send(wt, sock, buf, pos - buf); -} - - -static void ctrl_send_(struct wlantest *wt, int sock, u8 *cmd, size_t clen) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u8 *bssid, *sta_addr; - int prot; - u8 *frame; - size_t frame_len; - int ret = 0; - struct ieee80211_hdr *hdr; - u16 fc; - - frame = attr_get(cmd, clen, WLANTEST_ATTR_FRAME, &frame_len); - prot = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_PROTECTION); - if (frame == NULL || frame_len < 24 || prot < 0) { - wpa_printf(MSG_INFO, "Invalid send command parameters"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); - return; - } - - hdr = (struct ieee80211_hdr *) frame; - fc = le_to_host16(hdr->frame_control); - switch (WLAN_FC_GET_TYPE(fc)) { - case WLAN_FC_TYPE_MGMT: - bssid = hdr->addr3; - if (os_memcmp(hdr->addr2, hdr->addr3, ETH_ALEN) == 0) - sta_addr = hdr->addr1; - else - sta_addr = hdr->addr2; - break; - case WLAN_FC_TYPE_DATA: - switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) { - case 0: - bssid = hdr->addr3; - sta_addr = hdr->addr2; - break; - case WLAN_FC_TODS: - bssid = hdr->addr1; - sta_addr = hdr->addr2; - break; - case WLAN_FC_FROMDS: - bssid = hdr->addr2; - sta_addr = hdr->addr1; - break; - default: - wpa_printf(MSG_INFO, "Unsupported inject frame"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - break; - default: - wpa_printf(MSG_INFO, "Unsupported inject frame"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - bss = bss_find(wt, bssid); - if (bss == NULL && prot != WLANTEST_INJECT_UNPROTECTED) { - wpa_printf(MSG_INFO, "Unknown BSSID"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - if (bss) - sta = sta_find(bss, sta_addr); - else - sta = NULL; - if (sta == NULL && prot != WLANTEST_INJECT_UNPROTECTED) { - wpa_printf(MSG_INFO, "Unknown STA address"); - ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); - return; - } - - ret = wlantest_inject(wt, bss, sta, frame, frame_len, prot); - - if (ret) - wpa_printf(MSG_INFO, "Failed to inject frame"); - else - wpa_printf(MSG_INFO, "Frame injected successfully"); - ctrl_send_simple(wt, sock, ret == 0 ? WLANTEST_CTRL_SUCCESS : - WLANTEST_CTRL_FAILURE); -} - - -static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wlantest *wt = eloop_ctx; - u8 buf[WLANTEST_CTRL_MAX_CMD_LEN]; - int len; - enum wlantest_ctrl_cmd cmd; - - wpa_printf(MSG_EXCESSIVE, "New control interface message from %d", - sock); - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - wpa_printf(MSG_INFO, "recv(ctrl): %s", strerror(errno)); - ctrl_disconnect(wt, sock); - return; - } - if (len == 0) { - ctrl_disconnect(wt, sock); - return; - } - - if (len < 4) { - wpa_printf(MSG_INFO, "Too short control interface command " - "from %d", sock); - ctrl_disconnect(wt, sock); - return; - } - cmd = WPA_GET_BE32(buf); - wpa_printf(MSG_EXCESSIVE, "Control interface command %d from %d", - cmd, sock); - - switch (cmd) { - case WLANTEST_CTRL_PING: - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); - break; - case WLANTEST_CTRL_TERMINATE: - ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS); - eloop_terminate(); - break; - case WLANTEST_CTRL_LIST_BSS: - ctrl_list_bss(wt, sock); - break; - case WLANTEST_CTRL_LIST_STA: - ctrl_list_sta(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_FLUSH: - ctrl_flush(wt, sock); - break; - case WLANTEST_CTRL_CLEAR_STA_COUNTERS: - ctrl_clear_sta_counters(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_CLEAR_BSS_COUNTERS: - ctrl_clear_bss_counters(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_CLEAR_TDLS_COUNTERS: - ctrl_clear_tdls_counters(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_GET_STA_COUNTER: - ctrl_get_sta_counter(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_GET_BSS_COUNTER: - ctrl_get_bss_counter(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_GET_TDLS_COUNTER: - ctrl_get_tdls_counter(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_INJECT: - ctrl_inject(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_VERSION: - ctrl_version(wt, sock); - break; - case WLANTEST_CTRL_ADD_PASSPHRASE: - ctrl_add_passphrase(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_INFO_STA: - ctrl_info_sta(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_INFO_BSS: - ctrl_info_bss(wt, sock, buf + 4, len - 4); - break; - case WLANTEST_CTRL_SEND: - ctrl_send_(wt, sock, buf + 4, len - 4); - break; - default: - ctrl_send_simple(wt, sock, WLANTEST_CTRL_UNKNOWN_CMD); - break; - } -} - - -static void ctrl_connect(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wlantest *wt = eloop_ctx; - int conn, i; - - conn = accept(sock, NULL, NULL); - if (conn < 0) { - wpa_printf(MSG_INFO, "accept(ctrl): %s", strerror(errno)); - return; - } - wpa_printf(MSG_MSGDUMP, "New control interface connection %d", conn); - - for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) { - if (wt->ctrl_socks[i] < 0) - break; - } - - if (i == MAX_CTRL_CONNECTIONS) { - wpa_printf(MSG_INFO, "No room for new control connection"); - close(conn); - return; - } - - wt->ctrl_socks[i] = conn; - eloop_register_read_sock(conn, ctrl_read, wt, NULL); -} - - -int ctrl_init(struct wlantest *wt) -{ - struct sockaddr_un addr; - - wt->ctrl_sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (wt->ctrl_sock < 0) { - wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME, - sizeof(addr.sun_path) - 1); - if (bind(wt->ctrl_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_ERROR, "bind: %s", strerror(errno)); - close(wt->ctrl_sock); - wt->ctrl_sock = -1; - return -1; - } - - if (listen(wt->ctrl_sock, 5) < 0) { - wpa_printf(MSG_ERROR, "listen: %s", strerror(errno)); - close(wt->ctrl_sock); - wt->ctrl_sock = -1; - return -1; - } - - if (eloop_register_read_sock(wt->ctrl_sock, ctrl_connect, wt, NULL)) { - close(wt->ctrl_sock); - wt->ctrl_sock = -1; - return -1; - } - - return 0; -} - - -void ctrl_deinit(struct wlantest *wt) -{ - int i; - - if (wt->ctrl_sock < 0) - return; - - for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) { - if (wt->ctrl_socks[i] >= 0) { - close(wt->ctrl_socks[i]); - eloop_unregister_read_sock(wt->ctrl_socks[i]); - wt->ctrl_socks[i] = -1; - } - } - - eloop_unregister_read_sock(wt->ctrl_sock); - close(wt->ctrl_sock); - wt->ctrl_sock = -1; -} diff --git a/wlantest/inject.c b/wlantest/inject.c deleted file mode 100644 index b57f23f..0000000 --- a/wlantest/inject.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * wlantest frame injection - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/defs.h" -#include "common/ieee802_11_defs.h" -#include "crypto/aes_wrap.h" -#include "wlantest.h" - - -static int inject_frame(int s, const void *data, size_t len) -{ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 - unsigned char rtap_hdr[] = { - 0x00, 0x00, /* radiotap version */ - 0x0e, 0x00, /* radiotap length */ - 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */ - IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */ - 0x00, /* padding */ - 0x00, 0x00, /* RX and TX flags to indicate that */ - 0x00, 0x00, /* this is the injected frame directly */ - }; - struct iovec iov[2] = { - { - .iov_base = &rtap_hdr, - .iov_len = sizeof(rtap_hdr), - }, - { - .iov_base = (void *) data, - .iov_len = len, - } - }; - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_iov = iov, - .msg_iovlen = 2, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, - }; - int ret; - - ret = sendmsg(s, &msg, 0); - if (ret < 0) - perror("sendmsg"); - return ret; -} - - -static int is_robust_mgmt(u8 *frame, size_t len) -{ - struct ieee80211_mgmt *mgmt; - u16 fc, stype; - if (len < 24) - return 0; - mgmt = (struct ieee80211_mgmt *) frame; - fc = le_to_host16(mgmt->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) - return 0; - stype = WLAN_FC_GET_STYPE(fc); - if (stype == WLAN_FC_STYPE_DEAUTH || stype == WLAN_FC_STYPE_DISASSOC) - return 1; - if (stype == WLAN_FC_STYPE_ACTION) { - if (len < 25) - return 0; - if (mgmt->u.action.category != WLAN_ACTION_PUBLIC) - return 1; - } - return 0; -} - - -static int wlantest_inject_bip(struct wlantest *wt, struct wlantest_bss *bss, - u8 *frame, size_t len, int incorrect_key) -{ - u8 *prot, *pos, *buf; - u8 mic[16]; - u8 dummy[16]; - int ret; - u16 fc; - struct ieee80211_hdr *hdr; - size_t plen; - - if (!bss->igtk_set[bss->igtk_idx]) - return -1; - - plen = len + 18; - prot = os_malloc(plen); - if (prot == NULL) - return -1; - os_memcpy(prot, frame, len); - pos = prot + len; - *pos++ = WLAN_EID_MMIE; - *pos++ = 16; - WPA_PUT_LE16(pos, bss->igtk_idx); - pos += 2; - inc_byte_array(bss->ipn[bss->igtk_idx], 6); - os_memcpy(pos, bss->ipn[bss->igtk_idx], 6); - pos += 6; - os_memset(pos, 0, 8); /* MIC */ - - buf = os_malloc(plen + 20 - 24); - if (buf == NULL) { - os_free(prot); - return -1; - } - - /* BIP AAD: FC(masked) A1 A2 A3 */ - hdr = (struct ieee80211_hdr *) frame; - fc = le_to_host16(hdr->frame_control); - fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); - WPA_PUT_LE16(buf, fc); - os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN); - os_memcpy(buf + 20, prot + 24, plen - 24); - wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, plen + 20 - 24); - /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */ - os_memset(dummy, 0x11, sizeof(dummy)); - if (omac1_aes_128(incorrect_key ? dummy : bss->igtk[bss->igtk_idx], - buf, plen + 20 - 24, mic) < 0) { - os_free(prot); - os_free(buf); - return -1; - } - os_free(buf); - - os_memcpy(pos, mic, 8); - wpa_hexdump(MSG_DEBUG, "BIP MMIE MIC", pos, 8); - - ret = inject_frame(wt->monitor_sock, prot, plen); - os_free(prot); - - return (ret < 0) ? -1 : 0; -} - - -static int wlantest_inject_prot_bc(struct wlantest *wt, - struct wlantest_bss *bss, - u8 *frame, size_t len, int incorrect_key) -{ - u8 *crypt; - size_t crypt_len; - int ret; - u8 dummy[64]; - u8 *pn; - struct ieee80211_hdr *hdr; - u16 fc; - int hdrlen; - - hdr = (struct ieee80211_hdr *) frame; - hdrlen = 24; - fc = le_to_host16(hdr->frame_control); - - if (!bss->gtk_len[bss->gtk_idx]) - return -1; - - if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS)) - hdrlen += ETH_ALEN; - pn = bss->rsc[bss->gtk_idx]; - inc_byte_array(pn, 6); - - os_memset(dummy, 0x11, sizeof(dummy)); - if (bss->group_cipher == WPA_CIPHER_TKIP) - crypt = tkip_encrypt(incorrect_key ? dummy : - bss->gtk[bss->gtk_idx], - frame, len, hdrlen, NULL, pn, - bss->gtk_idx, &crypt_len); - else - crypt = ccmp_encrypt(incorrect_key ? dummy : - bss->gtk[bss->gtk_idx], - frame, len, hdrlen, NULL, pn, - bss->gtk_idx, &crypt_len); - - if (crypt == NULL) - return -1; - - ret = inject_frame(wt->monitor_sock, crypt, crypt_len); - os_free(crypt); - - return (ret < 0) ? -1 : 0; -} - - -static int wlantest_inject_prot(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, u8 *frame, - size_t len, int incorrect_key) -{ - u8 *crypt; - size_t crypt_len; - int ret; - u8 dummy[64]; - u8 *pn; - struct ieee80211_hdr *hdr; - u16 fc; - int tid = 0; - u8 *qos = NULL; - int hdrlen; - struct wlantest_tdls *tdls = NULL; - const u8 *tk = NULL; - - hdr = (struct ieee80211_hdr *) frame; - hdrlen = 24; - fc = le_to_host16(hdr->frame_control); - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == 0) { - struct wlantest_sta *sta2; - bss = bss_get(wt, hdr->addr3); - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "No BSS found for TDLS " - "injection"); - return -1; - } - sta = sta_find(bss, hdr->addr2); - sta2 = sta_find(bss, hdr->addr1); - if (sta == NULL || sta2 == NULL) { - wpa_printf(MSG_DEBUG, "No stations found for TDLS " - "injection"); - return -1; - } - 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->link_up) - wpa_printf(MSG_DEBUG, "TDLS: Link not " - "up, but injecting Data " - "frame on direct link"); - tk = tdls->tpk.tk; - break; - } - } - } - - if (tk == NULL && sta == NULL) { - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) - return wlantest_inject_bip(wt, bss, frame, len, - incorrect_key); - return wlantest_inject_prot_bc(wt, bss, frame, len, - incorrect_key); - } - - if (tk == NULL && !sta->ptk_set) { - wpa_printf(MSG_DEBUG, "No key known for injection"); - return -1; - } - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) - tid = 16; - else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) { - if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS)) - hdrlen += ETH_ALEN; - if (WLAN_FC_GET_STYPE(fc) & 0x08) { - qos = frame + hdrlen; - hdrlen += 2; - tid = qos[0] & 0x0f; - } - } - if (tk) { - if (os_memcmp(hdr->addr2, tdls->init->addr, ETH_ALEN) == 0) - pn = tdls->rsc_init[tid]; - else - pn = tdls->rsc_resp[tid]; - } else if (os_memcmp(hdr->addr2, bss->bssid, ETH_ALEN) == 0) - pn = sta->rsc_fromds[tid]; - else - pn = sta->rsc_tods[tid]; - inc_byte_array(pn, 6); - - os_memset(dummy, 0x11, sizeof(dummy)); - if (tk) - crypt = ccmp_encrypt(incorrect_key ? dummy : tk, - frame, len, hdrlen, qos, pn, 0, - &crypt_len); - else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) - crypt = tkip_encrypt(incorrect_key ? dummy : sta->ptk.tk1, - frame, len, hdrlen, qos, pn, 0, - &crypt_len); - else - crypt = ccmp_encrypt(incorrect_key ? dummy : sta->ptk.tk1, - frame, len, hdrlen, qos, pn, 0, - &crypt_len); - - if (crypt == NULL) { - wpa_printf(MSG_DEBUG, "Frame encryption failed"); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "Inject frame (encrypted)", crypt, crypt_len); - ret = inject_frame(wt->monitor_sock, crypt, crypt_len); - os_free(crypt); - wpa_printf(MSG_DEBUG, "inject_frame for protected frame: %d", ret); - - return (ret < 0) ? -1 : 0; -} - - -int wlantest_inject(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, u8 *frame, size_t len, - enum wlantest_inject_protection prot) -{ - int ret; - struct ieee80211_hdr *hdr; - u16 fc; - int protectable, protect = 0; - - wpa_hexdump(MSG_DEBUG, "Inject frame", frame, len); - if (wt->monitor_sock < 0) { - wpa_printf(MSG_INFO, "Cannot inject frames when monitor " - "interface is not in use"); - return -1; - } - - if (prot != WLANTEST_INJECT_UNPROTECTED && - (bss == NULL || sta == NULL)) { - wpa_printf(MSG_INFO, "No BSS/STA information to inject " - "protected frames"); - return -1; - } - - hdr = (struct ieee80211_hdr *) frame; - fc = le_to_host16(hdr->frame_control); - protectable = WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA || - is_robust_mgmt(frame, len); - - if ((prot == WLANTEST_INJECT_PROTECTED || - prot == WLANTEST_INJECT_INCORRECT_KEY) && bss) { - if (!sta && - ((WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - !bss->igtk_set[bss->igtk_idx]) || - (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - !bss->gtk_len[bss->gtk_idx]))) { - wpa_printf(MSG_INFO, "No GTK/IGTK known for " - MACSTR " to protect the injected " - "frame", MAC2STR(bss->bssid)); - return -1; - } - if (sta && !sta->ptk_set) { - wpa_printf(MSG_INFO, "No PTK known for the STA " MACSTR - " to encrypt the injected frame", - MAC2STR(sta->addr)); - return -1; - } - protect = 1; - } else if (protectable && prot != WLANTEST_INJECT_UNPROTECTED && bss) { - if (sta && sta->ptk_set) - protect = 1; - else if (!sta) { - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - bss->gtk_len[bss->gtk_idx]) - protect = 1; - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - bss->igtk_set[bss->igtk_idx]) - protect = 1; - } - } - - if (protect && bss) - return wlantest_inject_prot( - wt, bss, sta, frame, len, - prot == WLANTEST_INJECT_INCORRECT_KEY); - - ret = inject_frame(wt->monitor_sock, frame, len); - wpa_printf(MSG_DEBUG, "inject_frame for unprotected frame: %d", ret); - return (ret < 0) ? -1 : 0; -} diff --git a/wlantest/monitor.c b/wlantest/monitor.c deleted file mode 100644 index 902e6d9..0000000 --- a/wlantest/monitor.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Linux packet socket monitor - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <net/if.h> -#include <netpacket/packet.h> - -#include "utils/common.h" -#include "utils/eloop.h" -#include "wlantest.h" - - -static void monitor_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wlantest *wt = eloop_ctx; - u8 buf[3000]; - int len; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - wpa_printf(MSG_INFO, "recv(PACKET): %s", strerror(errno)); - return; - } - - write_pcap_captured(wt, buf, len); - wlantest_process(wt, buf, len); -} - - -static void monitor_read_wired(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wlantest *wt = eloop_ctx; - u8 buf[3000]; - int len; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - wpa_printf(MSG_INFO, "recv(PACKET): %s", strerror(errno)); - return; - } - - wlantest_process_wired(wt, buf, len); -} - - -int monitor_init(struct wlantest *wt, const char *ifname) -{ - struct sockaddr_ll ll; - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = if_nametoindex(ifname); - if (ll.sll_ifindex == 0) { - wpa_printf(MSG_ERROR, "Monitor interface '%s' does not exist", - ifname); - return -1; - } - - wt->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (wt->monitor_sock < 0) { - wpa_printf(MSG_ERROR, "socket(PF_PACKET,SOCK_RAW): %s", - strerror(errno)); - return -1; - } - - if (bind(wt->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - wpa_printf(MSG_ERROR, "bind(PACKET): %s", strerror(errno)); - close(wt->monitor_sock); - wt->monitor_sock = -1; - return -1; - } - - if (eloop_register_read_sock(wt->monitor_sock, monitor_read, wt, NULL)) - { - wpa_printf(MSG_ERROR, "Could not register monitor read " - "socket"); - close(wt->monitor_sock); - wt->monitor_sock = -1; - return -1; - } - - return 0; -} - - -int monitor_init_wired(struct wlantest *wt, const char *ifname) -{ - struct sockaddr_ll ll; - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = if_nametoindex(ifname); - if (ll.sll_ifindex == 0) { - wpa_printf(MSG_ERROR, "Monitor interface '%s' does not exist", - ifname); - return -1; - } - - wt->monitor_wired = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (wt->monitor_wired < 0) { - wpa_printf(MSG_ERROR, "socket(PF_PACKET,SOCK_RAW): %s", - strerror(errno)); - return -1; - } - - if (bind(wt->monitor_wired, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - wpa_printf(MSG_ERROR, "bind(PACKET): %s", strerror(errno)); - close(wt->monitor_wired); - wt->monitor_wired = -1; - return -1; - } - - if (eloop_register_read_sock(wt->monitor_wired, monitor_read_wired, - wt, NULL)) { - wpa_printf(MSG_ERROR, "Could not register monitor read " - "socket"); - close(wt->monitor_wired); - wt->monitor_wired = -1; - return -1; - } - - return 0; -} - - -void monitor_deinit(struct wlantest *wt) -{ - if (wt->monitor_sock >= 0) { - eloop_unregister_read_sock(wt->monitor_sock); - close(wt->monitor_sock); - wt->monitor_sock = -1; - } - - if (wt->monitor_wired >= 0) { - eloop_unregister_read_sock(wt->monitor_wired); - close(wt->monitor_wired); - wt->monitor_wired = -1; - } -} diff --git a/wlantest/process.c b/wlantest/process.c deleted file mode 100644 index dc272ed..0000000 --- a/wlantest/process.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Received frame processing - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/radiotap.h" -#include "utils/radiotap_iter.h" -#include "common/ieee802_11_defs.h" -#include "wlantest.h" - - -static struct wlantest_sta * rx_get_sta(struct wlantest *wt, - const struct ieee80211_hdr *hdr, - size_t len, int *to_ap) -{ - u16 fc; - const u8 *sta_addr, *bssid; - struct wlantest_bss *bss; - - *to_ap = 0; - if (hdr->addr1[0] & 0x01) - return NULL; /* Ignore group addressed frames */ - - fc = le_to_host16(hdr->frame_control); - switch (WLAN_FC_GET_TYPE(fc)) { - case WLAN_FC_TYPE_MGMT: - if (len < 24) - return NULL; - 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 NULL; /* Unsupported STA-to-STA frame */ - sta_addr = hdr->addr2; - *to_ap = 1; - } - break; - case WLAN_FC_TYPE_DATA: - if (len < 24) - return NULL; - switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) { - case 0: - return NULL; /* 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 NULL; /* WDS not supported */ - default: - return NULL; - } - break; - case WLAN_FC_TYPE_CTRL: - if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PSPOLL && - len >= 16) { - sta_addr = hdr->addr2; - bssid = hdr->addr1; - *to_ap = 1; - } else - return NULL; - break; - default: - return NULL; - } - - bss = bss_find(wt, bssid); - if (bss == NULL) - return NULL; - return sta_find(bss, sta_addr); -} - - -static void rx_update_ps(struct wlantest *wt, const struct ieee80211_hdr *hdr, - size_t len, struct wlantest_sta *sta, int to_ap) -{ - u16 fc, type, stype; - - if (sta == NULL) - return; - - fc = le_to_host16(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - if (!to_ap) { - if (sta->pwrmgt && !sta->pspoll) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - wpa_printf(MSG_DEBUG, "AP " MACSTR " sent a frame " - "(%u:%u) to a sleeping STA " MACSTR - " (seq=%u)", - MAC2STR(sta->bss->bssid), - type, stype, MAC2STR(sta->addr), - WLAN_GET_SEQ_SEQ(seq_ctrl)); - } else - sta->pspoll = 0; - return; - } - - sta->pspoll = 0; - - if (type == WLAN_FC_TYPE_DATA || type == WLAN_FC_TYPE_MGMT || - (type == WLAN_FC_TYPE_CTRL && stype == WLAN_FC_STYPE_PSPOLL)) { - /* - * In theory, the PS state changes only at the end of the frame - * exchange that is ACKed by the AP. However, most cases are - * handled with this simpler implementation that does not - * maintain state through the frame exchange. - */ - if (sta->pwrmgt && !(fc & WLAN_FC_PWRMGT)) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " woke up from " - "sleep", MAC2STR(sta->addr)); - sta->pwrmgt = 0; - } else if (!sta->pwrmgt && (fc & WLAN_FC_PWRMGT)) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " went to sleep", - MAC2STR(sta->addr)); - sta->pwrmgt = 1; - } - } - - if (type == WLAN_FC_TYPE_CTRL && stype == WLAN_FC_STYPE_PSPOLL) - sta->pspoll = 1; -} - - -static int rx_duplicate(struct wlantest *wt, const struct ieee80211_hdr *hdr, - size_t len, struct wlantest_sta *sta, int to_ap) -{ - u16 fc; - int tid = 16; - le16 *seq_ctrl; - - if (sta == NULL) - return 0; - - fc = le_to_host16(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - (WLAN_FC_GET_STYPE(fc) & 0x08) && len >= 26) { - const u8 *qos = ((const u8 *) hdr) + 24; - tid = qos[0] & 0x0f; - } - - 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_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; - u16 fc; - struct wlantest_sta *sta; - int to_ap; - - wpa_hexdump(MSG_EXCESSIVE, "RX frame", data, len); - if (len < 2) - return; - - hdr = (const struct ieee80211_hdr *) data; - fc = le_to_host16(hdr->frame_control); - if (fc & WLAN_FC_PVER) { - wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected pver=%d", - fc & WLAN_FC_PVER); - return; - } - - sta = rx_get_sta(wt, hdr, len, &to_ap); - - switch (WLAN_FC_GET_TYPE(fc)) { - case WLAN_FC_TYPE_MGMT: - if (len < 24) - break; - if (rx_duplicate(wt, hdr, len, sta, to_ap)) - break; - rx_update_ps(wt, hdr, len, sta, to_ap); - rx_mgmt(wt, data, len); - break; - case WLAN_FC_TYPE_CTRL: - if (len < 10) - break; - wt->rx_ctrl++; - rx_update_ps(wt, hdr, len, sta, to_ap); - if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACK) - rx_ack(wt, hdr); - break; - case WLAN_FC_TYPE_DATA: - if (len < 24) - break; - if (rx_duplicate(wt, hdr, len, sta, to_ap)) - break; - rx_update_ps(wt, hdr, len, sta, to_ap); - rx_data(wt, data, len); - break; - default: - wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected type %d", - 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; -} - - -static void tx_status(struct wlantest *wt, const u8 *data, size_t len, int ack) -{ - wpa_printf(MSG_DEBUG, "TX status: ack=%d", ack); - wpa_hexdump(MSG_EXCESSIVE, "TX status frame", data, len); -} - - -static int check_fcs(const u8 *frame, size_t frame_len, const u8 *fcs) -{ - if (WPA_GET_LE32(fcs) != crc32(frame, frame_len)) - return -1; - return 0; -} - - -void wlantest_process(struct wlantest *wt, const u8 *data, size_t len) -{ - struct ieee80211_radiotap_iterator iter; - int ret; - int rxflags = 0, txflags = 0, failed = 0, fcs = 0; - const u8 *frame, *fcspos; - size_t frame_len; - - wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len); - - if (ieee80211_radiotap_iterator_init(&iter, (void *) data, len)) { - wpa_printf(MSG_INFO, "Invalid radiotap frame"); - return; - } - - for (;;) { - ret = ieee80211_radiotap_iterator_next(&iter); - wpa_printf(MSG_EXCESSIVE, "radiotap iter: %d " - "this_arg_index=%d", ret, iter.this_arg_index); - if (ret == -ENOENT) - break; - if (ret) { - wpa_printf(MSG_INFO, "Invalid radiotap header: %d", - ret); - return; - } - switch (iter.this_arg_index) { - case IEEE80211_RADIOTAP_FLAGS: - if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) - fcs = 1; - break; - case IEEE80211_RADIOTAP_RX_FLAGS: - rxflags = 1; - break; - case IEEE80211_RADIOTAP_TX_FLAGS: - txflags = 1; - failed = le_to_host16((*(u16 *) iter.this_arg)) & - IEEE80211_RADIOTAP_F_TX_FAIL; - break; - - } - } - - if (iter.max_length == 8) { - wpa_printf(MSG_DEBUG, "Skip frame inserted by wlantest"); - return; - } - frame = data + iter.max_length; - frame_len = len - iter.max_length; - - if (fcs && frame_len >= 4) { - frame_len -= 4; - fcspos = frame + frame_len; - if (check_fcs(frame, frame_len, fcspos) < 0) { - wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid " - "FCS"); - wt->fcs_error++; - return; - } - } - - if (rxflags && txflags) - return; - if (!txflags) - rx_frame(wt, frame, frame_len); - else - tx_status(wt, frame, frame_len, !failed); -} - - -void wlantest_process_prism(struct wlantest *wt, const u8 *data, size_t len) -{ - int fcs = 0; - const u8 *frame, *fcspos; - size_t frame_len; - u32 hdrlen; - - wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len); - - if (len < 8) - return; - hdrlen = WPA_GET_LE32(data + 4); - - if (len < hdrlen) { - wpa_printf(MSG_INFO, "Too short frame to include prism " - "header"); - return; - } - - frame = data + hdrlen; - frame_len = len - hdrlen; - fcs = 1; - - if (fcs && frame_len >= 4) { - frame_len -= 4; - fcspos = frame + frame_len; - if (check_fcs(frame, frame_len, fcspos) < 0) { - wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid " - "FCS"); - wt->fcs_error++; - return; - } - } - - rx_frame(wt, frame, frame_len); -} - - -void wlantest_process_80211(struct wlantest *wt, const u8 *data, size_t len) -{ - wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len); - rx_frame(wt, data, len); -} diff --git a/wlantest/readpcap.c b/wlantest/readpcap.c deleted file mode 100644 index 3ab4080..0000000 --- a/wlantest/readpcap.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * PCAP capture file reader - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <pcap.h> - -#include "utils/common.h" -#include "wlantest.h" - - -int read_cap_file(struct wlantest *wt, const char *fname) -{ - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_t *pcap; - unsigned int count = 0; - struct pcap_pkthdr *hdr; - const u_char *data; - int res; - int dlt; - - pcap = pcap_open_offline(fname, errbuf); - if (pcap == NULL) { - wpa_printf(MSG_ERROR, "Failed to read pcap file '%s': %s", - fname, errbuf); - return -1; - } - dlt = pcap_datalink(pcap); - if (dlt != DLT_IEEE802_11_RADIO && dlt != DLT_PRISM_HEADER && - dlt != DLT_IEEE802_11) { - wpa_printf(MSG_ERROR, "Unsupported pcap datalink type: %d", - dlt); - pcap_close(pcap); - return -1; - } - wpa_printf(MSG_DEBUG, "pcap datalink type: %d", dlt); - - for (;;) { - res = pcap_next_ex(pcap, &hdr, &data); - if (res == -2) - break; /* No more packets */ - if (res == -1) { - wpa_printf(MSG_INFO, "pcap_next_ex failure: %s", - pcap_geterr(pcap)); - break; - } - if (res != 1) { - wpa_printf(MSG_INFO, "Unexpected pcap_next_ex return " - "value %d", res); - break; - } - - /* Packet was read without problems */ - wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d " - "len=%u/%u", - (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec, - hdr->caplen, hdr->len); - if (wt->write_pcap_dumper) { - wt->write_pcap_time = hdr->ts; - pcap_dump(wt->write_pcap_dumper, hdr, data); - } - if (hdr->caplen < hdr->len) { - wpa_printf(MSG_DEBUG, "pcap: Dropped incomplete frame " - "(%u/%u captured)", - hdr->caplen, hdr->len); - continue; - } - count++; - switch (dlt) { - case DLT_IEEE802_11_RADIO: - wlantest_process(wt, data, hdr->caplen); - break; - case DLT_PRISM_HEADER: - wlantest_process_prism(wt, data, hdr->caplen); - break; - case DLT_IEEE802_11: - wlantest_process_80211(wt, data, hdr->caplen); - } - } - - pcap_close(pcap); - - wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count); - - return 0; -} - - -int read_wired_cap_file(struct wlantest *wt, const char *fname) -{ - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_t *pcap; - unsigned int count = 0; - struct pcap_pkthdr *hdr; - const u_char *data; - int res; - - pcap = pcap_open_offline(fname, errbuf); - if (pcap == NULL) { - wpa_printf(MSG_ERROR, "Failed to read pcap file '%s': %s", - fname, errbuf); - return -1; - } - - for (;;) { - res = pcap_next_ex(pcap, &hdr, &data); - if (res == -2) - break; /* No more packets */ - if (res == -1) { - wpa_printf(MSG_INFO, "pcap_next_ex failure: %s", - pcap_geterr(pcap)); - break; - } - if (res != 1) { - wpa_printf(MSG_INFO, "Unexpected pcap_next_ex return " - "value %d", res); - break; - } - - /* Packet was read without problems */ - wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d " - "len=%u/%u", - (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec, - hdr->caplen, hdr->len); - if (hdr->caplen < hdr->len) { - wpa_printf(MSG_DEBUG, "pcap: Dropped incomplete frame " - "(%u/%u captured)", - hdr->caplen, hdr->len); - continue; - } - count++; - wlantest_process_wired(wt, data, hdr->caplen); - } - - pcap_close(pcap); - - wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count); - - return 0; -} diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c deleted file mode 100644 index fea73cc..0000000 --- a/wlantest/rx_data.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Received Data frame processing - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <linux/if_ether.h> - -#include "utils/common.h" -#include "common/defs.h" -#include "common/ieee802_11_defs.h" -#include "wlantest.h" - - -static const char * data_stype(u16 stype) -{ - switch (stype) { - case WLAN_FC_STYPE_DATA: - return "DATA"; - case WLAN_FC_STYPE_DATA_CFACK: - return "DATA-CFACK"; - case WLAN_FC_STYPE_DATA_CFPOLL: - return "DATA-CFPOLL"; - case WLAN_FC_STYPE_DATA_CFACKPOLL: - return "DATA-CFACKPOLL"; - case WLAN_FC_STYPE_NULLFUNC: - return "NULLFUNC"; - case WLAN_FC_STYPE_CFACK: - return "CFACK"; - case WLAN_FC_STYPE_CFPOLL: - return "CFPOLL"; - case WLAN_FC_STYPE_CFACKPOLL: - return "CFACKPOLL"; - case WLAN_FC_STYPE_QOS_DATA: - return "QOSDATA"; - case WLAN_FC_STYPE_QOS_DATA_CFACK: - return "QOSDATA-CFACK"; - case WLAN_FC_STYPE_QOS_DATA_CFPOLL: - return "QOSDATA-CFPOLL"; - case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL: - return "QOSDATA-CFACKPOLL"; - case WLAN_FC_STYPE_QOS_NULL: - return "QOS-NULL"; - case WLAN_FC_STYPE_QOS_CFPOLL: - return "QOS-CFPOLL"; - case WLAN_FC_STYPE_QOS_CFACKPOLL: - return "QOS-CFACKPOLL"; - } - return "??"; -} - - -static void rx_data_eth(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, const u8 *src, - u16 ethertype, const u8 *data, size_t len, int prot, - const u8 *peer_addr) -{ - switch (ethertype) { - case ETH_P_PAE: - rx_data_eapol(wt, dst, src, data, len, prot); - break; - case ETH_P_IP: - rx_data_ip(wt, bssid, sta_addr, dst, src, data, len, - peer_addr); - break; - case 0x890d: - rx_data_80211_encap(wt, bssid, sta_addr, dst, src, data, len); - break; - } -} - - -static void rx_data_process(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, - const u8 *dst, const u8 *src, - const u8 *data, size_t len, int prot, - const u8 *peer_addr) -{ - if (len == 0) - return; - - if (len >= 8 && os_memcmp(data, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) { - rx_data_eth(wt, bssid, sta_addr, dst, src, - WPA_GET_BE16(data + 6), data + 8, len - 8, prot, - peer_addr); - return; - } - - wpa_hexdump(MSG_DEBUG, "Unrecognized LLC", data, len > 8 ? 8 : len); -} - - -static void rx_data_bss_prot_group(struct wlantest *wt, - const struct ieee80211_hdr *hdr, - const u8 *qos, const u8 *dst, const u8 *src, - const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - int keyid; - u8 *decrypted; - size_t dlen; - u8 pn[6]; - - bss = bss_get(wt, hdr->addr2); - if (bss == NULL) - return; - if (len < 4) { - wpa_printf(MSG_INFO, "Too short group addressed data frame"); - return; - } - - if (bss->group_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) && - !(data[3] & 0x20)) { - wpa_printf(MSG_INFO, "Expected TKIP/CCMP frame from " - MACSTR " did not have ExtIV bit set to 1", - MAC2STR(bss->bssid)); - return; - } - - if (bss->group_cipher == WPA_CIPHER_TKIP) { - if (data[3] & 0x1f) { - wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used " - "non-zero reserved bit", - MAC2STR(bss->bssid)); - } - if (data[1] != ((data[0] | 0x20) & 0x7f)) { - wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used " - "incorrect WEPSeed[1] (was 0x%x, expected " - "0x%x)", - MAC2STR(bss->bssid), data[1], - (data[0] | 0x20) & 0x7f); - } - } else if (bss->group_cipher == WPA_CIPHER_CCMP) { - if (data[2] != 0 || (data[3] & 0x1f) != 0) { - wpa_printf(MSG_INFO, "CCMP frame from " MACSTR " used " - "non-zero reserved bit", - MAC2STR(bss->bssid)); - } - } - - keyid = data[3] >> 6; - if (bss->gtk_len[keyid] == 0 && bss->group_cipher != WPA_CIPHER_WEP40) - { - wpa_printf(MSG_MSGDUMP, "No GTK known to decrypt the frame " - "(A2=" MACSTR " KeyID=%d)", - MAC2STR(hdr->addr2), keyid); - return; - } - - if (bss->group_cipher == WPA_CIPHER_TKIP) - tkip_get_pn(pn, data); - else if (bss->group_cipher == WPA_CIPHER_WEP40) - goto skip_replay_det; - else - ccmp_get_pn(pn, data); - if (os_memcmp(pn, bss->rsc[keyid], 6) <= 0) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3), - WLAN_GET_SEQ_SEQ(seq_ctrl), - WLAN_GET_SEQ_FRAG(seq_ctrl)); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6); - } - -skip_replay_det: - if (bss->group_cipher == WPA_CIPHER_TKIP) - decrypted = tkip_decrypt(bss->gtk[keyid], hdr, data, len, - &dlen); - else if (bss->group_cipher == WPA_CIPHER_WEP40) - decrypted = wep_decrypt(wt, hdr, data, len, &dlen); - else - decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, data, len, - &dlen); - if (decrypted) { - rx_data_process(wt, bss->bssid, NULL, dst, src, decrypted, - dlen, 1, NULL); - os_memcpy(bss->rsc[keyid], pn, 6); - write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0), - decrypted, dlen); - } - os_free(decrypted); -} - - -static void rx_data_bss_prot(struct wlantest *wt, - const struct ieee80211_hdr *hdr, const u8 *qos, - const u8 *dst, const u8 *src, const u8 *data, - size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta, *sta2; - int keyid; - u16 fc = le_to_host16(hdr->frame_control); - u8 *decrypted; - size_t dlen; - int tid; - u8 pn[6], *rsc; - struct wlantest_tdls *tdls = NULL; - const u8 *tk = NULL; - - if (hdr->addr1[0] & 0x01) { - rx_data_bss_prot_group(wt, hdr, qos, dst, src, data, len); - return; - } - - if (fc & WLAN_FC_TODS) { - bss = bss_get(wt, hdr->addr1); - if (bss == NULL) - return; - sta = sta_get(bss, hdr->addr2); - if (sta) - sta->counters[WLANTEST_STA_COUNTER_PROT_DATA_TX]++; - } else if (fc & WLAN_FC_FROMDS) { - bss = bss_get(wt, hdr->addr2); - if (bss == NULL) - return; - sta = sta_get(bss, hdr->addr1); - } else { - bss = bss_get(wt, hdr->addr3); - if (bss == NULL) - return; - sta = sta_find(bss, hdr->addr2); - sta2 = sta_find(bss, hdr->addr1); - if (sta == NULL || sta2 == NULL) - return; - 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->link_up) - wpa_printf(MSG_DEBUG, "TDLS: Link not " - "up, but Data frame seen"); - tk = tdls->tpk.tk; - break; - } - } - } - if ((sta == NULL || - (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) && - tk == NULL) { - wpa_printf(MSG_MSGDUMP, "No PTK known to decrypt the frame"); - return; - } - - if (len < 4) { - wpa_printf(MSG_INFO, "Too short encrypted data frame"); - return; - } - - if (sta->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) && - !(data[3] & 0x20)) { - wpa_printf(MSG_INFO, "Expected TKIP/CCMP frame from " - MACSTR " did not have ExtIV bit set to 1", - MAC2STR(src)); - return; - } - - if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) { - if (data[3] & 0x1f) { - wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used " - "non-zero reserved bit", - MAC2STR(hdr->addr2)); - } - if (data[1] != ((data[0] | 0x20) & 0x7f)) { - wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used " - "incorrect WEPSeed[1] (was 0x%x, expected " - "0x%x)", - MAC2STR(hdr->addr2), data[1], - (data[0] | 0x20) & 0x7f); - } - } else if (tk || sta->pairwise_cipher == WPA_CIPHER_CCMP) { - if (data[2] != 0 || (data[3] & 0x1f) != 0) { - wpa_printf(MSG_INFO, "CCMP frame from " MACSTR " used " - "non-zero reserved bit", - MAC2STR(hdr->addr2)); - } - } - - keyid = data[3] >> 6; - if (keyid != 0) { - wpa_printf(MSG_INFO, "Unexpected non-zero KeyID %d in " - "individually addressed Data frame from " MACSTR, - keyid, MAC2STR(hdr->addr2)); - } - - if (qos) - tid = qos[0] & 0x0f; - else - tid = 0; - if (tk) { - if (os_memcmp(hdr->addr2, tdls->init->addr, ETH_ALEN) == 0) - rsc = tdls->rsc_init[tid]; - else - rsc = tdls->rsc_resp[tid]; - } else if (fc & WLAN_FC_TODS) - rsc = sta->rsc_tods[tid]; - else - rsc = sta->rsc_fromds[tid]; - - - if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) - tkip_get_pn(pn, data); - else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) - goto skip_replay_det; - else - ccmp_get_pn(pn, data); - if (os_memcmp(pn, rsc, 6) <= 0) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3), - WLAN_GET_SEQ_SEQ(seq_ctrl), - WLAN_GET_SEQ_FRAG(seq_ctrl)); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", rsc, 6); - } - -skip_replay_det: - if (tk) - decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); - else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) - decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); - else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) - decrypted = wep_decrypt(wt, hdr, data, len, &dlen); - else - decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); - if (decrypted) { - u16 fc = le_to_host16(hdr->frame_control); - const u8 *peer_addr = NULL; - if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS))) - peer_addr = hdr->addr1; - os_memcpy(rsc, pn, 6); - rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted, - dlen, 1, peer_addr); - write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0), - decrypted, dlen); - } - os_free(decrypted); -} - - -static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr, - const u8 *qos, const u8 *dst, const u8 *src, - const u8 *data, size_t len) -{ - u16 fc = le_to_host16(hdr->frame_control); - int prot = !!(fc & WLAN_FC_ISWEP); - - if (qos) { - u8 ack = (qos[0] & 0x60) >> 5; - wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR - " len=%u%s tid=%u%s%s", - MAC2STR(src), MAC2STR(dst), (unsigned int) len, - prot ? " Prot" : "", qos[0] & 0x0f, - (qos[0] & 0x10) ? " EOSP" : "", - ack == 0 ? "" : - (ack == 1 ? " NoAck" : - (ack == 2 ? " NoExpAck" : " BA"))); - } else { - wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR - " len=%u%s", - MAC2STR(src), MAC2STR(dst), (unsigned int) len, - prot ? " Prot" : ""); - } - - if (prot) - rx_data_bss_prot(wt, hdr, qos, dst, src, data, len); - else { - const u8 *bssid, *sta_addr, *peer_addr; - if (fc & WLAN_FC_TODS) { - bssid = hdr->addr1; - sta_addr = hdr->addr2; - peer_addr = NULL; - } else if (fc & WLAN_FC_FROMDS) { - bssid = hdr->addr2; - sta_addr = hdr->addr1; - peer_addr = NULL; - } else { - bssid = hdr->addr3; - sta_addr = hdr->addr2; - peer_addr = hdr->addr1; - } - rx_data_process(wt, bssid, sta_addr, dst, src, data, len, 0, - peer_addr); - } -} - - -static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *bssid, - const u8 *sta1_addr, - const u8 *sta2_addr) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta1, *sta2; - struct wlantest_tdls *tdls; - - bss = bss_find(wt, bssid); - if (bss == NULL) - return NULL; - sta1 = sta_find(bss, sta1_addr); - if (sta1 == NULL) - return NULL; - sta2 = sta_find(bss, sta2_addr); - if (sta2 == NULL) - return NULL; - - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if ((tdls->init == sta1 && tdls->resp == sta2) || - (tdls->init == sta2 && tdls->resp == sta1)) - return tdls; - } - - return NULL; -} - - -static void add_direct_link(struct wlantest *wt, const u8 *bssid, - const u8 *sta1_addr, const u8 *sta2_addr) -{ - struct wlantest_tdls *tdls; - - tdls = get_tdls(wt, bssid, sta1_addr, sta2_addr); - if (tdls == NULL) - return; - - if (tdls->link_up) - tdls->counters[WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK]++; - else - tdls->counters[WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK]++; -} - - -static void add_ap_path(struct wlantest *wt, const u8 *bssid, - const u8 *sta1_addr, const u8 *sta2_addr) -{ - struct wlantest_tdls *tdls; - - tdls = get_tdls(wt, bssid, sta1_addr, sta2_addr); - if (tdls == NULL) - return; - - if (tdls->link_up) - tdls->counters[WLANTEST_TDLS_COUNTER_INVALID_AP_PATH]++; - else - tdls->counters[WLANTEST_TDLS_COUNTER_VALID_AP_PATH]++; -} - - -void rx_data(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_hdr *hdr; - u16 fc, stype; - size_t hdrlen; - const u8 *qos = NULL; - - if (len < 24) - return; - - hdr = (const struct ieee80211_hdr *) data; - fc = le_to_host16(hdr->frame_control); - stype = WLAN_FC_GET_STYPE(fc); - hdrlen = 24; - if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS)) - hdrlen += ETH_ALEN; - if (stype & 0x08) { - qos = data + hdrlen; - hdrlen += 2; - } - if (len < hdrlen) - return; - wt->rx_data++; - - switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) { - case 0: - wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA=" - MACSTR " BSSID=" MACSTR, - data_stype(WLAN_FC_GET_STYPE(fc)), - fc & WLAN_FC_PWRMGT ? " PwrMgt" : "", - fc & WLAN_FC_ISWEP ? " Prot" : "", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3)); - add_direct_link(wt, hdr->addr3, hdr->addr1, hdr->addr2); - rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2, - data + hdrlen, len - hdrlen); - break; - case WLAN_FC_FROMDS: - wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR - " BSSID=" MACSTR " SA=" MACSTR, - data_stype(WLAN_FC_GET_STYPE(fc)), - fc & WLAN_FC_PWRMGT ? " PwrMgt" : "", - fc & WLAN_FC_ISWEP ? " Prot" : "", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3)); - add_ap_path(wt, hdr->addr2, hdr->addr1, hdr->addr3); - rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr3, - data + hdrlen, len - hdrlen); - break; - case WLAN_FC_TODS: - wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR - " SA=" MACSTR " DA=" MACSTR, - data_stype(WLAN_FC_GET_STYPE(fc)), - fc & WLAN_FC_PWRMGT ? " PwrMgt" : "", - fc & WLAN_FC_ISWEP ? " Prot" : "", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3)); - add_ap_path(wt, hdr->addr1, hdr->addr3, hdr->addr2); - rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2, - data + hdrlen, len - hdrlen); - break; - case WLAN_FC_TODS | WLAN_FC_FROMDS: - wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA=" - MACSTR " DA=" MACSTR " SA=" MACSTR, - data_stype(WLAN_FC_GET_STYPE(fc)), - fc & WLAN_FC_PWRMGT ? " PwrMgt" : "", - fc & WLAN_FC_ISWEP ? " Prot" : "", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3), - MAC2STR((const u8 *) (hdr + 1))); - break; - } -} diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c deleted file mode 100644 index ad9035f..0000000 --- a/wlantest/rx_eapol.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* - * Received Data frame processing for EAPOL messages - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "crypto/aes_wrap.h" -#include "crypto/crypto.h" -#include "common/defs.h" -#include "common/ieee802_11_defs.h" -#include "common/eapol_common.h" -#include "common/wpa_common.h" -#include "rsn_supp/wpa_ie.h" -#include "wlantest.h" - - -static int is_zero(const u8 *buf, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) { - if (buf[i]) - return 0; - } - return 1; -} - - -static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len) -{ - u8 *buf; - int ret = -1; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u8 rx_mic[16]; - - buf = os_malloc(len); - if (buf == NULL) - return -1; - os_memcpy(buf, data, len); - hdr = (struct ieee802_1x_hdr *) buf; - key = (struct wpa_eapol_key *) (hdr + 1); - - os_memcpy(rx_mic, key->key_mic, 16); - os_memset(key->key_mic, 0, 16); - - if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 && - os_memcmp(rx_mic, key->key_mic, 16) == 0) - ret = 0; - - os_free(buf); - - return ret; -} - - -static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - - wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR, - MAC2STR(src), MAC2STR(dst)); - bss = bss_get(wt, src); - if (bss == NULL) - return; - sta = sta_get(bss, dst); - if (sta == NULL) - return; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_INFO, "EAPOL-Key 1/4 from " MACSTR " used " - "zero nonce", MAC2STR(src)); - } - if (!is_zero(hdr->key_rsc, 8)) { - wpa_printf(MSG_INFO, "EAPOL-Key 1/4 from " MACSTR " used " - "non-zero Key RSC", MAC2STR(src)); - } - os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN); -} - - -static int try_pmk(struct wlantest_bss *bss, struct wlantest_sta *sta, - u16 ver, const u8 *data, size_t len, - struct wlantest_pmk *pmk) -{ - struct wpa_ptk ptk; - size_t ptk_len = sta->pairwise_cipher == WPA_CIPHER_TKIP ? 64 : 48; - wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk), - "Pairwise key expansion", - bss->bssid, sta->addr, sta->anonce, sta->snonce, - (u8 *) &ptk, ptk_len, - wpa_key_mgmt_sha256(sta->key_mgmt)); - if (check_mic(ptk.kck, ver, data, len) < 0) - return -1; - - wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->counters[WLANTEST_STA_COUNTER_PTK_LEARNED]++; - if (sta->ptk_set) { - /* - * Rekeying - use new PTK for EAPOL-Key frames, but continue - * using the old PTK for frame decryption. - */ - os_memcpy(&sta->tptk, &ptk, sizeof(ptk)); - wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16); - wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16); - wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16); - if (ptk_len > 48) - wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2, - 16); - sta->tptk_set = 1; - return 0; - } - os_memcpy(&sta->ptk, &ptk, sizeof(ptk)); - wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16); - wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16); - wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16); - if (ptk_len > 48) - wpa_hexdump(MSG_DEBUG, "PTK:TK2", sta->ptk.u.tk2, 16); - sta->ptk_set = 1; - os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); - os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); - return 0; -} - - -static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, u16 ver, - const u8 *data, size_t len) -{ - struct wlantest_pmk *pmk; - - wpa_printf(MSG_DEBUG, "Trying to derive PTK for " MACSTR, - MAC2STR(sta->addr)); - dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) { - wpa_printf(MSG_DEBUG, "Try per-BSS PMK"); - if (try_pmk(bss, sta, ver, data, len, pmk) == 0) - return; - } - - dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) { - wpa_printf(MSG_DEBUG, "Try global PMK"); - if (try_pmk(bss, sta, ver, data, len, pmk) == 0) - return; - } - wpa_printf(MSG_DEBUG, "No matching PMK found to derive PTK"); -} - - -static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - const u8 *key_data, *kck; - u16 key_info, key_data_len; - struct wpa_eapol_ie_parse ie; - - wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR, - MAC2STR(src), MAC2STR(dst)); - bss = bss_get(wt, dst); - if (bss == NULL) - return; - sta = sta_get(bss, src); - if (sta == NULL) - return; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_INFO, "EAPOL-Key 2/4 from " MACSTR " used " - "zero nonce", MAC2STR(src)); - } - if (!is_zero(hdr->key_rsc, 8)) { - wpa_printf(MSG_INFO, "EAPOL-Key 2/4 from " MACSTR " used " - "non-zero Key RSC", MAC2STR(src)); - } - os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN); - key_info = WPA_GET_BE16(hdr->key_info); - key_data_len = WPA_GET_BE16(hdr->key_data_length); - derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); - - if (!sta->ptk_set && !sta->tptk_set) { - wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 2/4"); - return; - } - - kck = sta->ptk.kck; - if (sta->tptk_set) { - wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); - kck = sta->tptk.kck; - } - if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { - wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC"); - return; - } - wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4"); - - key_data = (const u8 *) (hdr + 1); - - if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { - wpa_printf(MSG_INFO, "Failed to parse EAPOL-Key Key Data"); - return; - } - - if (ie.wpa_ie) { - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE", - ie.wpa_ie, ie.wpa_ie_len); - if (os_memcmp(ie.wpa_ie, sta->rsnie, ie.wpa_ie_len) != 0) { - wpa_printf(MSG_INFO, "Mismatch in WPA IE between " - "EAPOL-Key 2/4 and (Re)Association " - "Request from " MACSTR, MAC2STR(sta->addr)); - wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key", - ie.wpa_ie, ie.wpa_ie_len); - wpa_hexdump(MSG_INFO, "WPA IE in (Re)Association " - "Request", - sta->rsnie, - sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); - } - } - - if (ie.rsn_ie) { - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE", - ie.rsn_ie, ie.rsn_ie_len); - if (os_memcmp(ie.rsn_ie, sta->rsnie, ie.rsn_ie_len) != 0) { - wpa_printf(MSG_INFO, "Mismatch in RSN IE between " - "EAPOL-Key 2/4 and (Re)Association " - "Request from " MACSTR, MAC2STR(sta->addr)); - wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key", - ie.rsn_ie, ie.rsn_ie_len); - wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association " - "Request", - sta->rsnie, - sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); - } - } -} - - -static u8 * decrypt_eapol_key_data_rc4(const u8 *kek, - const struct wpa_eapol_key *hdr, - size_t *len) -{ - u8 ek[32], *buf; - u16 keydatalen = WPA_GET_BE16(hdr->key_data_length); - - buf = os_malloc(keydatalen); - if (buf == NULL) - return NULL; - - os_memcpy(ek, hdr->key_iv, 16); - os_memcpy(ek + 16, kek, 16); - os_memcpy(buf, hdr + 1, keydatalen); - if (rc4_skip(ek, 32, 256, buf, keydatalen)) { - wpa_printf(MSG_INFO, "RC4 failed"); - os_free(buf); - return NULL; - } - - *len = keydatalen; - return buf; -} - - -static u8 * decrypt_eapol_key_data_aes(const u8 *kek, - const struct wpa_eapol_key *hdr, - size_t *len) -{ - u8 *buf; - u16 keydatalen = WPA_GET_BE16(hdr->key_data_length); - - if (keydatalen % 8) { - wpa_printf(MSG_INFO, "Unsupported AES-WRAP len %d", - keydatalen); - return NULL; - } - keydatalen -= 8; /* AES-WRAP adds 8 bytes */ - buf = os_malloc(keydatalen); - if (buf == NULL) - return NULL; - if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) { - os_free(buf); - wpa_printf(MSG_INFO, "AES unwrap failed - " - "could not decrypt EAPOL-Key key data"); - return NULL; - } - - *len = keydatalen; - return buf; -} - - -static u8 * decrypt_eapol_key_data(const u8 *kek, u16 ver, - const struct wpa_eapol_key *hdr, - size_t *len) -{ - switch (ver) { - case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - return decrypt_eapol_key_data_rc4(kek, hdr, len); - case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - case WPA_KEY_INFO_TYPE_AES_128_CMAC: - return decrypt_eapol_key_data_aes(kek, hdr, len); - default: - wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor " - "Version %u", ver); - return NULL; - } -} - - -static void learn_kde_keys(struct wlantest_bss *bss, struct wlantest_sta *sta, - const u8 *buf, size_t len, const u8 *rsc) -{ - struct wpa_eapol_ie_parse ie; - - if (wpa_supplicant_parse_ies(buf, len, &ie) < 0) { - wpa_printf(MSG_INFO, "Failed to parse EAPOL-Key Key Data"); - return; - } - - if (ie.wpa_ie) { - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE", - ie.wpa_ie, ie.wpa_ie_len); - } - - if (ie.rsn_ie) { - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE", - ie.rsn_ie, ie.rsn_ie_len); - } - - if (ie.gtk) { - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE", - ie.gtk, ie.gtk_len); - if (ie.gtk_len >= 2 && ie.gtk_len <= 2 + 32) { - int id; - id = ie.gtk[0] & 0x03; - wpa_printf(MSG_DEBUG, "GTK KeyID=%u tx=%u", - id, !!(ie.gtk[0] & 0x04)); - if ((ie.gtk[0] & 0xf8) || ie.gtk[1]) - wpa_printf(MSG_INFO, "GTK KDE: Reserved field " - "set: %02x %02x", - ie.gtk[0], ie.gtk[1]); - wpa_hexdump(MSG_DEBUG, "GTK", ie.gtk + 2, - ie.gtk_len - 2); - bss->gtk_len[id] = ie.gtk_len - 2; - sta->gtk_len = ie.gtk_len - 2; - os_memcpy(bss->gtk[id], ie.gtk + 2, ie.gtk_len - 2); - os_memcpy(sta->gtk, ie.gtk + 2, ie.gtk_len - 2); - bss->rsc[id][0] = rsc[5]; - bss->rsc[id][1] = rsc[4]; - bss->rsc[id][2] = rsc[3]; - bss->rsc[id][3] = rsc[2]; - bss->rsc[id][4] = rsc[1]; - bss->rsc[id][5] = rsc[0]; - bss->gtk_idx = id; - sta->gtk_idx = id; - wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6); - } else { - wpa_printf(MSG_INFO, "Invalid GTK KDE length %u", - (unsigned) ie.gtk_len); - } - } - - if (ie.igtk) { - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - IGTK KDE", - ie.igtk, ie.igtk_len); - if (ie.igtk_len == 24) { - u16 id; - id = WPA_GET_LE16(ie.igtk); - if (id > 5) { - wpa_printf(MSG_INFO, "Unexpected IGTK KeyID " - "%u", id); - } else { - const u8 *ipn; - wpa_printf(MSG_DEBUG, "IGTK KeyID %u", id); - wpa_hexdump(MSG_DEBUG, "IPN", ie.igtk + 2, 6); - wpa_hexdump(MSG_DEBUG, "IGTK", ie.igtk + 8, - 16); - os_memcpy(bss->igtk[id], ie.igtk + 8, 16); - bss->igtk_set[id] = 1; - ipn = ie.igtk + 2; - bss->ipn[id][0] = ipn[5]; - bss->ipn[id][1] = ipn[4]; - bss->ipn[id][2] = ipn[3]; - bss->ipn[id][3] = ipn[2]; - bss->ipn[id][4] = ipn[1]; - bss->ipn[id][5] = ipn[0]; - bss->igtk_idx = id; - } - } else { - wpa_printf(MSG_INFO, "Invalid IGTK KDE length %u", - (unsigned) ie.igtk_len); - } - } -} - - -static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - const u8 *key_data, *kck, *kek; - int recalc = 0; - u16 key_info, ver; - u8 *decrypted_buf = NULL; - const u8 *decrypted; - size_t decrypted_len = 0; - struct wpa_eapol_ie_parse ie; - - wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR, - MAC2STR(src), MAC2STR(dst)); - bss = bss_get(wt, src); - if (bss == NULL) - return; - sta = sta_get(bss, dst); - if (sta == NULL) - return; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - key_info = WPA_GET_BE16(hdr->key_info); - - if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 " - "and 3/4"); - recalc = 1; - } - os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN); - if (recalc) { - derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len); - } - - if (!sta->ptk_set && !sta->tptk_set) { - wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4"); - return; - } - - kek = sta->ptk.kek; - kck = sta->ptk.kck; - if (sta->tptk_set) { - wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); - kck = sta->tptk.kck; - kek = sta->tptk.kek; - } - if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { - wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC"); - return; - } - wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4"); - - key_data = (const u8 *) (hdr + 1); - if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - if (sta->proto & WPA_PROTO_RSN) - wpa_printf(MSG_INFO, "EAPOL-Key 3/4 without " - "EncrKeyData bit"); - decrypted = key_data; - decrypted_len = WPA_GET_BE16(hdr->key_data_length); - } else { - ver = key_info & WPA_KEY_INFO_TYPE_MASK; - decrypted_buf = decrypt_eapol_key_data(kek, ver, hdr, - &decrypted_len); - if (decrypted_buf == NULL) { - wpa_printf(MSG_INFO, "Failed to decrypt EAPOL-Key Key " - "Data"); - return; - } - decrypted = decrypted_buf; - wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data", - decrypted, decrypted_len); - } - if (wt->write_pcap_dumper && decrypted != key_data) { - /* Fill in a dummy Data frame header */ - u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)]; - struct ieee80211_hdr *h; - struct wpa_eapol_key *k; - const u8 *p; - u8 *pos; - size_t plain_len; - - plain_len = decrypted_len; - p = decrypted; - while (p + 1 < decrypted + decrypted_len) { - if (p[0] == 0xdd && p[1] == 0x00) { - /* Remove padding */ - plain_len = p - decrypted; - break; - } - p += 2 + p[1]; - } - - os_memset(buf, 0, sizeof(buf)); - h = (struct ieee80211_hdr *) buf; - h->frame_control = host_to_le16(0x0208); - os_memcpy(h->addr1, dst, ETH_ALEN); - os_memcpy(h->addr2, src, ETH_ALEN); - os_memcpy(h->addr3, src, ETH_ALEN); - pos = (u8 *) (h + 1); - os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8); - pos += 8; - os_memcpy(pos, eapol, sizeof(*eapol)); - pos += sizeof(*eapol); - os_memcpy(pos, hdr, sizeof(*hdr)); - k = (struct wpa_eapol_key *) pos; - WPA_PUT_BE16(k->key_info, - key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA); - WPA_PUT_BE16(k->key_data_length, plain_len); - write_pcap_decrypted(wt, buf, sizeof(buf), - decrypted, plain_len); - } - - if (wpa_supplicant_parse_ies(decrypted, decrypted_len, &ie) < 0) { - wpa_printf(MSG_INFO, "Failed to parse EAPOL-Key Key Data"); - os_free(decrypted_buf); - return; - } - - if ((ie.wpa_ie && - os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) || - (ie.wpa_ie == NULL && bss->wpaie[0])) { - wpa_printf(MSG_INFO, "Mismatch in WPA IE between " - "EAPOL-Key 3/4 and Beacon/Probe Response " - "from " MACSTR, MAC2STR(bss->bssid)); - wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key", - ie.wpa_ie, ie.wpa_ie_len); - wpa_hexdump(MSG_INFO, "WPA IE in Beacon/Probe " - "Response", - bss->wpaie, - bss->wpaie[0] ? 2 + bss->wpaie[1] : 0); - } - - if ((ie.rsn_ie && - os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) || - (ie.rsn_ie == NULL && bss->rsnie[0])) { - wpa_printf(MSG_INFO, "Mismatch in RSN IE between " - "EAPOL-Key 3/4 and Beacon/Probe Response " - "from " MACSTR, MAC2STR(bss->bssid)); - wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key", - ie.rsn_ie, ie.rsn_ie_len); - wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association " - "Request", - bss->rsnie, - bss->rsnie[0] ? 2 + bss->rsnie[1] : 0); - } - - learn_kde_keys(bss, sta, decrypted, decrypted_len, hdr->key_rsc); - os_free(decrypted_buf); -} - - -static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - u16 key_info; - const u8 *kck; - - wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR, - MAC2STR(src), MAC2STR(dst)); - bss = bss_get(wt, dst); - if (bss == NULL) - return; - sta = sta_get(bss, src); - if (sta == NULL) - return; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - if (!is_zero(hdr->key_rsc, 8)) { - wpa_printf(MSG_INFO, "EAPOL-Key 4/4 from " MACSTR " used " - "non-zero Key RSC", MAC2STR(src)); - } - key_info = WPA_GET_BE16(hdr->key_info); - - if (!sta->ptk_set && !sta->tptk_set) { - wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4"); - return; - } - - kck = sta->ptk.kck; - if (sta->tptk_set) { - wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); - kck = sta->tptk.kck; - } - if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { - wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC"); - return; - } - wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4"); - if (sta->tptk_set) { - wpa_printf(MSG_DEBUG, "Update PTK (rekeying)"); - os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk)); - sta->ptk_set = 1; - sta->tptk_set = 0; - os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); - os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); - } -} - - -static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - const u8 *key_data; - u16 key_info, ver; - u8 *decrypted; - size_t decrypted_len = 0; - - wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR, - MAC2STR(src), MAC2STR(dst)); - bss = bss_get(wt, src); - if (bss == NULL) - return; - sta = sta_get(bss, dst); - if (sta == NULL) - return; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - key_info = WPA_GET_BE16(hdr->key_info); - - if (!sta->ptk_set) { - wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 1/2"); - return; - } - - if (sta->ptk_set && - check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { - wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC"); - return; - } - wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 1/2"); - - key_data = (const u8 *) (hdr + 1); - if (sta->proto & WPA_PROTO_RSN && - !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_INFO, "EAPOL-Key 1/2 without EncrKeyData bit"); - return; - } - ver = key_info & WPA_KEY_INFO_TYPE_MASK; - decrypted = decrypt_eapol_key_data(sta->ptk.kek, ver, hdr, - &decrypted_len); - if (decrypted == NULL) { - wpa_printf(MSG_INFO, "Failed to decrypt EAPOL-Key Key Data"); - return; - } - wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data", - decrypted, decrypted_len); - if (wt->write_pcap_dumper) { - /* Fill in a dummy Data frame header */ - u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)]; - struct ieee80211_hdr *h; - struct wpa_eapol_key *k; - u8 *pos; - size_t plain_len; - - plain_len = decrypted_len; - pos = decrypted; - while (pos + 1 < decrypted + decrypted_len) { - if (pos[0] == 0xdd && pos[1] == 0x00) { - /* Remove padding */ - plain_len = pos - decrypted; - break; - } - pos += 2 + pos[1]; - } - - os_memset(buf, 0, sizeof(buf)); - h = (struct ieee80211_hdr *) buf; - h->frame_control = host_to_le16(0x0208); - os_memcpy(h->addr1, dst, ETH_ALEN); - os_memcpy(h->addr2, src, ETH_ALEN); - os_memcpy(h->addr3, src, ETH_ALEN); - pos = (u8 *) (h + 1); - os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8); - pos += 8; - os_memcpy(pos, eapol, sizeof(*eapol)); - pos += sizeof(*eapol); - os_memcpy(pos, hdr, sizeof(*hdr)); - k = (struct wpa_eapol_key *) pos; - WPA_PUT_BE16(k->key_info, - key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA); - WPA_PUT_BE16(k->key_data_length, plain_len); - write_pcap_decrypted(wt, buf, sizeof(buf), - decrypted, plain_len); - } - if (sta->proto & WPA_PROTO_RSN) - learn_kde_keys(bss, sta, decrypted, decrypted_len, - hdr->key_rsc); - else { - int klen = bss->group_cipher == WPA_CIPHER_TKIP ? 32 : 16; - if (decrypted_len == klen) { - const u8 *rsc = hdr->key_rsc; - int id; - id = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT; - wpa_printf(MSG_DEBUG, "GTK key index %d", id); - wpa_hexdump(MSG_DEBUG, "GTK", decrypted, - decrypted_len); - bss->gtk_len[id] = decrypted_len; - os_memcpy(bss->gtk[id], decrypted, decrypted_len); - bss->rsc[id][0] = rsc[5]; - bss->rsc[id][1] = rsc[4]; - bss->rsc[id][2] = rsc[3]; - bss->rsc[id][3] = rsc[2]; - bss->rsc[id][4] = rsc[1]; - bss->rsc[id][5] = rsc[0]; - wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6); - } else { - wpa_printf(MSG_INFO, "Unexpected WPA Key Data length " - "in Group Key msg 1/2 from " MACSTR, - MAC2STR(src)); - } - } - os_free(decrypted); -} - - -static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - u16 key_info; - - wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR, - MAC2STR(src), MAC2STR(dst)); - bss = bss_get(wt, dst); - if (bss == NULL) - return; - sta = sta_get(bss, src); - if (sta == NULL) - return; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - if (!is_zero(hdr->key_rsc, 8)) { - wpa_printf(MSG_INFO, "EAPOL-Key 2/2 from " MACSTR " used " - "non-zero Key RSC", MAC2STR(src)); - } - key_info = WPA_GET_BE16(hdr->key_info); - - if (!sta->ptk_set) { - wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 2/2"); - return; - } - - if (sta->ptk_set && - check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { - wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC"); - return; - } - wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/2"); -} - - -static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, - const u8 *src, const u8 *data, size_t len, - int prot) -{ - const struct ieee802_1x_hdr *eapol; - const struct wpa_eapol_key *hdr; - const u8 *key_data; - u16 key_info, key_length, ver, key_data_length; - - eapol = (const struct ieee802_1x_hdr *) data; - hdr = (const struct wpa_eapol_key *) (eapol + 1); - - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key", - (const u8 *) hdr, len - sizeof(*eapol)); - if (len < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "Too short EAPOL-Key frame from " MACSTR, - MAC2STR(src)); - return; - } - - if (hdr->type == EAPOL_KEY_TYPE_RC4) { - /* TODO: EAPOL-Key RC4 for WEP */ - wpa_printf(MSG_INFO, "EAPOL-Key Descriptor Type RC4 from " - MACSTR, MAC2STR(src)); - return; - } - - if (hdr->type != EAPOL_KEY_TYPE_RSN && - hdr->type != EAPOL_KEY_TYPE_WPA) { - wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Descriptor Type " - "%u from " MACSTR, hdr->type, MAC2STR(src)); - return; - } - - key_info = WPA_GET_BE16(hdr->key_info); - key_length = WPA_GET_BE16(hdr->key_length); - key_data_length = WPA_GET_BE16(hdr->key_data_length); - key_data = (const u8 *) (hdr + 1); - if (key_data + key_data_length > data + len) { - wpa_printf(MSG_INFO, "Truncated EAPOL-Key from " MACSTR, - MAC2STR(src)); - return; - } - if (key_data + key_data_length < data + len) { - wpa_hexdump(MSG_DEBUG, "Extra data after EAPOL-Key Key Data " - "field", key_data + key_data_length, - data + len - key_data - key_data_length); - } - - - ver = key_info & WPA_KEY_INFO_TYPE_MASK; - wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s " - "datalen=%u", - ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G', - (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT, - (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "", - (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "", - (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "", - (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "", - (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "", - (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "", - (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "", - (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "", - key_data_length); - - if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES && - ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { - wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor " - "Version %u from " MACSTR, ver, MAC2STR(src)); - return; - } - - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter", - hdr->replay_counter, WPA_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce", - hdr->key_nonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV", - hdr->key_iv, 16); - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC", - hdr->key_rsc, WPA_KEY_RSC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC", - hdr->key_mic, 16); - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data", - key_data, key_data_length); - - if (hdr->type == EAPOL_KEY_TYPE_RSN && - (key_info & (WPA_KEY_INFO_KEY_INDEX_MASK | BIT(14) | BIT(15))) != - 0) { - wpa_printf(MSG_INFO, "RSN EAPOL-Key with non-zero reserved " - "Key Info bits 0x%x from " MACSTR, - key_info, MAC2STR(src)); - } - - if (hdr->type == EAPOL_KEY_TYPE_WPA && - (key_info & (WPA_KEY_INFO_ENCR_KEY_DATA | - WPA_KEY_INFO_SMK_MESSAGE |BIT(14) | BIT(15))) != 0) { - wpa_printf(MSG_INFO, "WPA EAPOL-Key with non-zero reserved " - "Key Info bits 0x%x from " MACSTR, - key_info, MAC2STR(src)); - } - - if (key_length > 32) { - wpa_printf(MSG_INFO, "EAPOL-Key with invalid Key Length %d " - "from " MACSTR, key_length, MAC2STR(src)); - } - - if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && - !is_zero(hdr->key_iv, 16)) { - wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key IV " - "(reserved with ver=%d) field from " MACSTR, - ver, MAC2STR(src)); - wpa_hexdump(MSG_INFO, "EAPOL-Key Key IV (reserved)", - hdr->key_iv, 16); - } - - if (!is_zero(hdr->key_id, 8)) { - wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key ID " - "(reserved) field from " MACSTR, MAC2STR(src)); - wpa_hexdump(MSG_INFO, "EAPOL-Key Key ID (reserved)", - hdr->key_id, 8); - } - - if (hdr->key_rsc[6] || hdr->key_rsc[7]) { - wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key RSC octets " - "(last two are unused)" MACSTR, MAC2STR(src)); - } - - if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST)) - return; - - if (key_info & WPA_KEY_INFO_SMK_MESSAGE) - return; - - if (key_info & WPA_KEY_INFO_KEY_TYPE) { - /* 4-Way Handshake */ - switch (key_info & (WPA_KEY_INFO_SECURE | - WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | - WPA_KEY_INFO_INSTALL)) { - case WPA_KEY_INFO_ACK: - rx_data_eapol_key_1_of_4(wt, dst, src, data, len); - break; - case WPA_KEY_INFO_MIC: - if (key_data_length == 0) - rx_data_eapol_key_4_of_4(wt, dst, src, data, - len); - else - rx_data_eapol_key_2_of_4(wt, dst, src, data, - len); - break; - case WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK | - WPA_KEY_INFO_INSTALL: - /* WPA does not include Secure bit in 3/4 */ - rx_data_eapol_key_3_of_4(wt, dst, src, data, len); - break; - case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL: - rx_data_eapol_key_3_of_4(wt, dst, src, data, len); - break; - case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC: - if (key_data_length == 0) - rx_data_eapol_key_4_of_4(wt, dst, src, data, - len); - else - rx_data_eapol_key_2_of_4(wt, dst, src, data, - len); - break; - default: - wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame"); - break; - } - } else { - /* Group Key Handshake */ - switch (key_info & (WPA_KEY_INFO_SECURE | - WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK)) { - case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK: - rx_data_eapol_key_1_of_2(wt, dst, src, data, len); - break; - case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC: - rx_data_eapol_key_2_of_2(wt, dst, src, data, len); - break; - default: - wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame"); - break; - } - } -} - - -void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src, - const u8 *data, size_t len, int prot) -{ - const struct ieee802_1x_hdr *hdr; - u16 length; - const u8 *p; - - wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len); - if (len < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR, - MAC2STR(src)); - return; - } - - hdr = (const struct ieee802_1x_hdr *) data; - length = be_to_host16(hdr->length); - wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u " - "type=%u len=%u", - MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "", - hdr->version, hdr->type, length); - if (hdr->version < 1 || hdr->version > 3) { - wpa_printf(MSG_INFO, "Unexpected EAPOL version %u from " - MACSTR, hdr->version, MAC2STR(src)); - } - if (sizeof(*hdr) + length > len) { - wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR, - MAC2STR(src)); - return; - } - - if (sizeof(*hdr) + length < len) { - wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes", - (int) (len - sizeof(*hdr) - length)); - } - p = (const u8 *) (hdr + 1); - - switch (hdr->type) { - case IEEE802_1X_TYPE_EAP_PACKET: - wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length); - break; - case IEEE802_1X_TYPE_EAPOL_START: - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length); - break; - case IEEE802_1X_TYPE_EAPOL_LOGOFF: - wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length); - break; - case IEEE802_1X_TYPE_EAPOL_KEY: - rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length, - prot); - break; - case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: - wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert", - p, length); - break; - default: - wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length); - break; - } -} diff --git a/wlantest/rx_ip.c b/wlantest/rx_ip.c deleted file mode 100644 index 016004d..0000000 --- a/wlantest/rx_ip.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Received Data frame processing for IPv4 packets - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> - -#include "utils/common.h" -#include "wlantest.h" - - -static void ping_update(struct wlantest_sta *sta, int req, u32 src, u32 dst, - u16 id, u16 seq) -{ - if (req) { - sta->icmp_echo_req_src = src; - sta->icmp_echo_req_dst = dst; - sta->icmp_echo_req_id = id; - sta->icmp_echo_req_seq = seq; - return; - } - - if (sta->icmp_echo_req_src == dst && - sta->icmp_echo_req_dst == src && - sta->icmp_echo_req_id == id && - sta->icmp_echo_req_seq == seq) { - sta->counters[WLANTEST_STA_COUNTER_PING_OK]++; - if (sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX] == 0 && - sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX] == 0) - sta->counters[ - WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC]++; - wpa_printf(MSG_DEBUG, "ICMP echo (ping) match for STA " MACSTR, - MAC2STR(sta->addr)); - } -} - - -static void rx_data_icmp(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, u32 dst, u32 src, - const u8 *data, size_t len, const u8 *peer_addr) -{ - struct in_addr addr; - char buf[20]; - const struct icmphdr *hdr; - u16 id, seq; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - - hdr = (const struct icmphdr *) data; - if (len < 4) - return; - - /* TODO: check hdr->checksum */ - - if (hdr->type != ICMP_ECHOREPLY && hdr->type != ICMP_ECHO) - return; - if (len < 8) - return; - - id = ntohs(hdr->un.echo.id); - seq = ntohs(hdr->un.echo.sequence); - - addr.s_addr = dst; - snprintf(buf, sizeof(buf), "%s", inet_ntoa(addr)); - addr.s_addr = src; - wpa_printf(MSG_DEBUG, "ICMP echo %s %s -> %s id=%04x seq=%u len=%u%s", - hdr->type == ICMP_ECHO ? "request" : "response", - inet_ntoa(addr), buf, id, seq, (unsigned) len - 8, - peer_addr ? " [DL]" : ""); - - bss = bss_find(wt, bssid); - if (bss == NULL) { - wpa_printf(MSG_INFO, "No BSS " MACSTR " known for ICMP packet", - MAC2STR(bssid)); - return; - } - - if (sta_addr == NULL) - return; /* FromDS broadcast ping */ - - sta = sta_find(bss, sta_addr); - if (sta == NULL) { - wpa_printf(MSG_INFO, "No STA " MACSTR " known for ICMP packet", - MAC2STR(sta_addr)); - return; - } - - ping_update(sta, hdr->type == ICMP_ECHO, src, dst, id, seq); - if (peer_addr && (sta = sta_find(bss, peer_addr))) - ping_update(sta, hdr->type == ICMP_ECHO, src, dst, id, seq); -} - - -void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, - const u8 *dst, const u8 *src, const u8 *data, size_t len, - const u8 *peer_addr) -{ - const struct iphdr *ip; - const u8 *payload; - size_t plen; - u16 frag_off, tot_len; - - ip = (const struct iphdr *) data; - if (len < sizeof(*ip)) - return; - if (ip->version != 4) { - wpa_printf(MSG_DEBUG, "Unexpected IP protocol version %u in " - "IPv4 packet (bssid=" MACSTR " str=" MACSTR - " dst=" MACSTR ")", ip->version, MAC2STR(bssid), - MAC2STR(src), MAC2STR(dst)); - return; - } - if (ip->ihl * 4 < sizeof(*ip)) { - wpa_printf(MSG_DEBUG, "Unexpected IP header length %u in " - "IPv4 packet (bssid=" MACSTR " str=" MACSTR - " dst=" MACSTR ")", ip->ihl, MAC2STR(bssid), - MAC2STR(src), MAC2STR(dst)); - return; - } - if (ip->ihl * 4 > len) { - wpa_printf(MSG_DEBUG, "Truncated IP header (ihl=%u len=%u) in " - "IPv4 packet (bssid=" MACSTR " str=" MACSTR - " dst=" MACSTR ")", ip->ihl, (unsigned) len, - MAC2STR(bssid), MAC2STR(src), MAC2STR(dst)); - return; - } - - /* TODO: check header checksum in ip->check */ - - frag_off = be_to_host16(ip->frag_off); - if (frag_off & 0x1fff) { - wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet " - "supported"); - return; - } - - tot_len = be_to_host16(ip->tot_len); - if (tot_len > len) - return; - if (tot_len < len) - len = tot_len; - - payload = data + 4 * ip->ihl; - plen = len - 4 * ip->ihl; - - switch (ip->protocol) { - case IPPROTO_ICMP: - rx_data_icmp(wt, bssid, sta_addr, ip->daddr, ip->saddr, - payload, plen, peer_addr); - break; - } -} diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c deleted file mode 100644 index 0d72f22..0000000 --- a/wlantest/rx_mgmt.c +++ /dev/null @@ -1,1169 +0,0 @@ -/* - * Received Management frame processing - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "crypto/aes_wrap.h" -#include "wlantest.h" - - -static const char * mgmt_stype(u16 stype) -{ - switch (stype) { - case WLAN_FC_STYPE_ASSOC_REQ: - return "ASSOC-REQ"; - case WLAN_FC_STYPE_ASSOC_RESP: - return "ASSOC-RESP"; - case WLAN_FC_STYPE_REASSOC_REQ: - return "REASSOC-REQ"; - case WLAN_FC_STYPE_REASSOC_RESP: - return "REASSOC-RESP"; - case WLAN_FC_STYPE_PROBE_REQ: - return "PROBE-REQ"; - case WLAN_FC_STYPE_PROBE_RESP: - return "PROBE-RESP"; - case WLAN_FC_STYPE_BEACON: - return "BEACON"; - case WLAN_FC_STYPE_ATIM: - return "ATIM"; - case WLAN_FC_STYPE_DISASSOC: - return "DISASSOC"; - case WLAN_FC_STYPE_AUTH: - return "AUTH"; - case WLAN_FC_STYPE_DEAUTH: - return "DEAUTH"; - case WLAN_FC_STYPE_ACTION: - return "ACTION"; - } - return "??"; -} - - -static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct ieee802_11_elems elems; - - mgmt = (const struct ieee80211_mgmt *) data; - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return; - if (bss->proberesp_seen) - return; /* do not override with Beacon data */ - bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info); - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, - len - (mgmt->u.beacon.variable - data), - &elems, 0) == ParseFailed) { - if (bss->parse_error_reported) - return; - wpa_printf(MSG_INFO, "Invalid IEs in a Beacon frame from " - MACSTR, MAC2STR(mgmt->sa)); - bss->parse_error_reported = 1; - return; - } - - bss_update(wt, bss, &elems); -} - - -static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct ieee802_11_elems elems; - - mgmt = (const struct ieee80211_mgmt *) data; - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return; - - bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info); - if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable, - len - (mgmt->u.probe_resp.variable - data), - &elems, 0) == ParseFailed) { - if (bss->parse_error_reported) - return; - wpa_printf(MSG_INFO, "Invalid IEs in a Probe Response frame " - "from " MACSTR, MAC2STR(mgmt->sa)); - bss->parse_error_reported = 1; - return; - } - - bss_update(wt, bss, &elems); -} - - -static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u16 alg, trans, status; - - mgmt = (const struct ieee80211_mgmt *) data; - 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; - - if (len < 24 + 6) { - wpa_printf(MSG_INFO, "Too short Authentication frame from " - MACSTR, MAC2STR(mgmt->sa)); - return; - } - - alg = le_to_host16(mgmt->u.auth.auth_alg); - trans = le_to_host16(mgmt->u.auth.auth_transaction); - status = le_to_host16(mgmt->u.auth.status_code); - - wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR - " (alg=%u trans=%u status=%u)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), alg, trans, status); - - if (alg == 0 && trans == 2 && status == 0) { - if (sta->state == STATE1) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 2 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE2; - } - } - - if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) - sta->counters[WLANTEST_STA_COUNTER_AUTH_RX]++; - else - sta->counters[WLANTEST_STA_COUNTER_AUTH_TX]++; -} - - -static void deauth_all_stas(struct wlantest_bss *bss) -{ - struct wlantest_sta *sta; - dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) { - if (sta->state == STATE1) - continue; - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 1 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE1; - } -} - - -static void tdls_link_down(struct wlantest_bss *bss, struct wlantest_sta *sta) -{ - struct wlantest_tdls *tdls; - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if ((tdls->init == sta || tdls->resp == sta) && tdls->link_up) - { - wpa_printf(MSG_DEBUG, "TDLS: Set link down based on " - "STA deauth/disassoc"); - tdls->link_up = 0; - } - } -} - - -static void rx_mgmt_deauth(struct wlantest *wt, const u8 *data, size_t len, - int valid) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u16 fc, reason; - - mgmt = (const struct ieee80211_mgmt *) data; - 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 (len < 24 + 2) { - wpa_printf(MSG_INFO, "Too short Deauthentication frame from " - MACSTR, MAC2STR(mgmt->sa)); - return; - } - - reason = le_to_host16(mgmt->u.deauth.reason_code); - wpa_printf(MSG_DEBUG, "DEAUTH " MACSTR " -> " MACSTR - " (reason=%u) (valid=%d)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - reason, valid); - wpa_hexdump(MSG_MSGDUMP, "DEAUTH payload", data + 24, len - 24); - - if (sta == NULL) { - if (valid && mgmt->da[0] == 0xff) - deauth_all_stas(bss); - return; - } - - if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) { - sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_RX : - WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX]++; - if (sta->pwrmgt && !sta->pspoll) - sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP]++; - else - sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE]++; - - fc = le_to_host16(mgmt->frame_control); - if (!(fc & WLAN_FC_ISWEP) && reason == 6) - sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC6]++; - else if (!(fc & WLAN_FC_ISWEP) && reason == 7) - sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC7]++; - } else - sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_TX : - WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX]++; - - if (!valid) { - wpa_printf(MSG_INFO, "Do not change STA " MACSTR " State " - "since Disassociation frame was not protected " - "correctly", MAC2STR(sta->addr)); - return; - } - - if (sta->state != STATE1) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 1 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE1; - } - tdls_link_down(bss, sta); -} - - -static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - struct ieee802_11_elems elems; - - mgmt = (const struct ieee80211_mgmt *) data; - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return; - sta = sta_get(bss, mgmt->sa); - if (sta == NULL) - return; - - if (len < 24 + 4) { - wpa_printf(MSG_INFO, "Too short Association Request frame " - "from " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR - " (capab=0x%x listen_int=%u)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - le_to_host16(mgmt->u.assoc_req.capab_info), - le_to_host16(mgmt->u.assoc_req.listen_interval)); - - sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX]++; - - if (ieee802_11_parse_elems(mgmt->u.assoc_req.variable, - len - (mgmt->u.assoc_req.variable - data), - &elems, 0) == ParseFailed) { - wpa_printf(MSG_INFO, "Invalid IEs in Association Request " - "frame from " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - sta->assocreq_capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); - sta->assocreq_listen_int = - le_to_host16(mgmt->u.assoc_req.listen_interval); - os_free(sta->assocreq_ies); - sta->assocreq_ies_len = len - (mgmt->u.assoc_req.variable - data); - sta->assocreq_ies = os_malloc(sta->assocreq_ies_len); - if (sta->assocreq_ies) - os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable, - sta->assocreq_ies_len); - - sta_update_assoc(sta, &elems); -} - - -static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u16 capab, status, aid; - - mgmt = (const struct ieee80211_mgmt *) data; - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return; - sta = sta_get(bss, mgmt->da); - if (sta == NULL) - return; - - if (len < 24 + 6) { - wpa_printf(MSG_INFO, "Too short Association Response frame " - "from " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - capab = le_to_host16(mgmt->u.assoc_resp.capab_info); - status = le_to_host16(mgmt->u.assoc_resp.status_code); - aid = le_to_host16(mgmt->u.assoc_resp.aid); - - wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR - " (capab=0x%x status=%u aid=%u)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status, - aid & 0x3fff); - - if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { - struct ieee802_11_elems elems; - const u8 *ies = mgmt->u.assoc_resp.variable; - size_t ies_len = len - (mgmt->u.assoc_resp.variable - data); - if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == - ParseFailed) { - wpa_printf(MSG_INFO, "Failed to parse IEs in " - "AssocResp from " MACSTR, - MAC2STR(mgmt->sa)); - } else if (elems.timeout_int == NULL || - elems.timeout_int_len != 5 || - elems.timeout_int[0] != - WLAN_TIMEOUT_ASSOC_COMEBACK) { - wpa_printf(MSG_INFO, "No valid Timeout Interval IE " - "with Assoc Comeback time in AssocResp " - "(status=30) from " MACSTR, - MAC2STR(mgmt->sa)); - } else { - sta->counters[ - WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK]++; - } - } - - if (status) - return; - - if ((aid & 0xc000) != 0xc000) { - wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 " - "in Association Response from " MACSTR, - MAC2STR(mgmt->sa)); - } - sta->aid = aid & 0xc000; - - if (sta->state < STATE2) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when " - "getting associated", MAC2STR(sta->addr)); - } - - if (sta->state < STATE3) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 3 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE3; - } -} - - -static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, - size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - struct ieee802_11_elems elems; - - mgmt = (const struct ieee80211_mgmt *) data; - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return; - sta = sta_get(bss, mgmt->sa); - if (sta == NULL) - return; - - if (len < 24 + 4 + ETH_ALEN) { - wpa_printf(MSG_INFO, "Too short Reassociation Request frame " - "from " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR - " (capab=0x%x listen_int=%u current_ap=" MACSTR ")", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - le_to_host16(mgmt->u.reassoc_req.capab_info), - le_to_host16(mgmt->u.reassoc_req.listen_interval), - MAC2STR(mgmt->u.reassoc_req.current_ap)); - - sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX]++; - - if (ieee802_11_parse_elems(mgmt->u.reassoc_req.variable, - len - (mgmt->u.reassoc_req.variable - data), - &elems, 0) == ParseFailed) { - wpa_printf(MSG_INFO, "Invalid IEs in Reassociation Request " - "frame from " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - sta->assocreq_capab_info = - le_to_host16(mgmt->u.reassoc_req.capab_info); - sta->assocreq_listen_int = - le_to_host16(mgmt->u.reassoc_req.listen_interval); - os_free(sta->assocreq_ies); - sta->assocreq_ies_len = len - (mgmt->u.reassoc_req.variable - data); - sta->assocreq_ies = os_malloc(sta->assocreq_ies_len); - if (sta->assocreq_ies) - os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable, - sta->assocreq_ies_len); - - sta_update_assoc(sta, &elems); -} - - -static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, - size_t len) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u16 capab, status, aid; - - mgmt = (const struct ieee80211_mgmt *) data; - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return; - sta = sta_get(bss, mgmt->da); - if (sta == NULL) - return; - - if (len < 24 + 6) { - wpa_printf(MSG_INFO, "Too short Reassociation Response frame " - "from " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - capab = le_to_host16(mgmt->u.reassoc_resp.capab_info); - status = le_to_host16(mgmt->u.reassoc_resp.status_code); - aid = le_to_host16(mgmt->u.reassoc_resp.aid); - - wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR - " (capab=0x%x status=%u aid=%u)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status, - aid & 0x3fff); - - if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { - struct ieee802_11_elems elems; - const u8 *ies = mgmt->u.reassoc_resp.variable; - size_t ies_len = len - (mgmt->u.reassoc_resp.variable - data); - if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == - ParseFailed) { - wpa_printf(MSG_INFO, "Failed to parse IEs in " - "ReassocResp from " MACSTR, - MAC2STR(mgmt->sa)); - } else if (elems.timeout_int == NULL || - elems.timeout_int_len != 5 || - elems.timeout_int[0] != - WLAN_TIMEOUT_ASSOC_COMEBACK) { - wpa_printf(MSG_INFO, "No valid Timeout Interval IE " - "with Assoc Comeback time in ReassocResp " - "(status=30) from " MACSTR, - MAC2STR(mgmt->sa)); - } else { - sta->counters[ - WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK]++; - } - } - - if (status) - return; - - if ((aid & 0xc000) != 0xc000) { - wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 " - "in Reassociation Response from " MACSTR, - MAC2STR(mgmt->sa)); - } - sta->aid = aid & 0xc000; - - if (sta->state < STATE2) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when " - "getting associated", MAC2STR(sta->addr)); - } - - if (sta->state < STATE3) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 3 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE3; - } -} - - -static void disassoc_all_stas(struct wlantest_bss *bss) -{ - struct wlantest_sta *sta; - dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) { - if (sta->state <= STATE2) - continue; - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 2 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE2; - } -} - - -static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len, - int valid) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - u16 fc, reason; - - mgmt = (const struct ieee80211_mgmt *) data; - 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 (len < 24 + 2) { - wpa_printf(MSG_INFO, "Too short Disassociation frame from " - MACSTR, MAC2STR(mgmt->sa)); - return; - } - - reason = le_to_host16(mgmt->u.disassoc.reason_code); - wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR - " (reason=%u) (valid=%d)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - reason, valid); - wpa_hexdump(MSG_MSGDUMP, "DISASSOC payload", data + 24, len - 24); - - if (sta == NULL) { - if (valid && mgmt->da[0] == 0xff) - disassoc_all_stas(bss); - return; - } - - if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) { - sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_RX : - WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX]++; - if (sta->pwrmgt && !sta->pspoll) - sta->counters[ - WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP]++; - else - sta->counters[ - WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE]++; - - fc = le_to_host16(mgmt->frame_control); - if (!(fc & WLAN_FC_ISWEP) && reason == 6) - sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC6]++; - else if (!(fc & WLAN_FC_ISWEP) && reason == 7) - sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC7]++; - } else - sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_TX : - WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX]++; - - if (!valid) { - wpa_printf(MSG_INFO, "Do not change STA " MACSTR " State " - "since Disassociation frame was not protected " - "correctly", MAC2STR(sta->addr)); - return; - } - - if (sta->state < STATE2) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 or 3 " - "when getting disassociated", MAC2STR(sta->addr)); - } - - if (sta->state > STATE2) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " moved to State 2 with " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - sta->state = STATE2; - } - tdls_link_down(bss, sta); -} - - -static void rx_mgmt_action_sa_query_req(struct wlantest *wt, - struct wlantest_sta *sta, - const struct ieee80211_mgmt *mgmt, - size_t len, int valid) -{ - const u8 *rx_id; - u8 *id; - - rx_id = (const u8 *) mgmt->u.action.u.sa_query_req.trans_id; - if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) - id = sta->ap_sa_query_tr; - else - id = sta->sta_sa_query_tr; - wpa_printf(MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR - " (trans_id=%02x%02x)%s", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1], - valid ? "" : " (invalid protection)"); - os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2); - if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0) - sta->counters[valid ? - WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX : - WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX]++; - else - sta->counters[valid ? - WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX : - WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX]++; -} - - -static void rx_mgmt_action_sa_query_resp(struct wlantest *wt, - struct wlantest_sta *sta, - const struct ieee80211_mgmt *mgmt, - size_t len, int valid) -{ - const u8 *rx_id; - u8 *id; - int match; - - rx_id = (const u8 *) mgmt->u.action.u.sa_query_resp.trans_id; - if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) - id = sta->sta_sa_query_tr; - else - id = sta->ap_sa_query_tr; - match = os_memcmp(rx_id, id, 2) == 0; - wpa_printf(MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR - " (trans_id=%02x%02x; %s)%s", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1], - match ? "match" : "mismatch", - valid ? "" : " (invalid protection)"); - if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0) - sta->counters[(valid && match) ? - WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX : - WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX]++; - else - sta->counters[(valid && match) ? - WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX : - WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX]++; -} - - -static void rx_mgmt_action_sa_query(struct wlantest *wt, - struct wlantest_sta *sta, - const struct ieee80211_mgmt *mgmt, - size_t len, int valid) -{ - if (len < 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) { - wpa_printf(MSG_INFO, "Too short SA Query frame from " MACSTR, - MAC2STR(mgmt->sa)); - return; - } - - if (len > 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) { - size_t elen = len - (24 + 2 + WLAN_SA_QUERY_TR_ID_LEN); - wpa_printf(MSG_INFO, "Unexpected %u octets of extra data at " - "the end of SA Query frame from " MACSTR, - (unsigned) elen, MAC2STR(mgmt->sa)); - wpa_hexdump(MSG_INFO, "SA Query extra data", - ((const u8 *) mgmt) + len - elen, elen); - } - - switch (mgmt->u.action.u.sa_query_req.action) { - case WLAN_SA_QUERY_REQUEST: - rx_mgmt_action_sa_query_req(wt, sta, mgmt, len, valid); - break; - case WLAN_SA_QUERY_RESPONSE: - rx_mgmt_action_sa_query_resp(wt, sta, mgmt, len, valid); - break; - default: - wpa_printf(MSG_INFO, "Unexpected SA Query action value %u " - "from " MACSTR, - mgmt->u.action.u.sa_query_req.action, - MAC2STR(mgmt->sa)); - } -} - - -static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len, - int valid) -{ - const struct ieee80211_mgmt *mgmt; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - - mgmt = (const struct ieee80211_mgmt *) data; - if (mgmt->da[0] & 0x01) { - wpa_printf(MSG_DEBUG, "Group addressed Action frame: DA=" - MACSTR " SA=" MACSTR " BSSID=" MACSTR - " category=%u", - MAC2STR(mgmt->da), MAC2STR(mgmt->sa), - MAC2STR(mgmt->bssid), mgmt->u.action.category); - return; /* Ignore group addressed Action frames for now */ - } - 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; - - if (len < 24 + 1) { - wpa_printf(MSG_INFO, "Too short Action frame from " - MACSTR, MAC2STR(mgmt->sa)); - return; - } - - wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR - " (category=%u) (valid=%d)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - mgmt->u.action.category, valid); - wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24); - - if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && - sta->state < STATE3) { - wpa_printf(MSG_INFO, "Action frame sent when STA is not in " - "State 3 (SA=" MACSTR " DATA=" MACSTR ")", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da)); - } - - switch (mgmt->u.action.category) { - case WLAN_ACTION_SA_QUERY: - rx_mgmt_action_sa_query(wt, sta, mgmt, len, valid); - break; - } -} - - -static int check_mmie_mic(const u8 *igtk, const u8 *data, size_t len) -{ - u8 *buf; - u8 mic[16]; - u16 fc; - const struct ieee80211_hdr *hdr; - - buf = os_malloc(len + 20 - 24); - if (buf == NULL) - return -1; - - /* BIP AAD: FC(masked) A1 A2 A3 */ - hdr = (const struct ieee80211_hdr *) data; - fc = le_to_host16(hdr->frame_control); - fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); - WPA_PUT_LE16(buf, fc); - os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN); - - /* Frame body with MMIE MIC masked to zero */ - os_memcpy(buf + 20, data + 24, len - 24 - 8); - os_memset(buf + 20 + len - 24 - 8, 0, 8); - - wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24); - /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */ - if (omac1_aes_128(igtk, buf, len + 20 - 24, mic) < 0) { - os_free(buf); - return -1; - } - - os_free(buf); - - if (os_memcmp(data + len - 8, mic, 8) != 0) - return -1; - - return 0; -} - - -static int check_bip(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - u16 fc, stype; - const u8 *mmie; - u16 keyid; - struct wlantest_bss *bss; - - mgmt = (const struct ieee80211_mgmt *) data; - fc = le_to_host16(mgmt->frame_control); - stype = WLAN_FC_GET_STYPE(fc); - - if (stype == WLAN_FC_STYPE_ACTION) { - if (len < 24 + 1) - return 0; - if (mgmt->u.action.category == WLAN_ACTION_PUBLIC) - return 0; /* Not a robust management frame */ - } - - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return 0; /* No key known yet */ - - if (len < 24 + 18 || data[len - 18] != WLAN_EID_MMIE || - data[len - 17] != 16) { - /* No MMIE */ - if (bss->rsn_capab & WPA_CAPABILITY_MFPC) { - wpa_printf(MSG_INFO, "Robust group-addressed " - "management frame sent without BIP by " - MACSTR, MAC2STR(mgmt->sa)); - bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++; - return -1; - } - return 0; - } - - mmie = data + len - 16; - keyid = WPA_GET_LE16(mmie); - if (keyid & 0xf000) { - wpa_printf(MSG_INFO, "MMIE KeyID reserved bits not zero " - "(%04x) from " MACSTR, keyid, MAC2STR(mgmt->sa)); - keyid &= 0x0fff; - } - if (keyid < 4 || keyid > 5) { - wpa_printf(MSG_INFO, "Unexpected MMIE KeyID %u from " MACSTR, - keyid, MAC2STR(mgmt->sa)); - bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++; - return 0; - } - wpa_printf(MSG_DEBUG, "MMIE KeyID %u", keyid); - wpa_hexdump(MSG_MSGDUMP, "MMIE IPN", mmie + 2, 6); - wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, 8); - - if (!bss->igtk_set[keyid]) { - wpa_printf(MSG_DEBUG, "No IGTK known to validate BIP frame"); - return 0; - } - - if (os_memcmp(mmie + 2, bss->ipn[keyid], 6) <= 0) { - wpa_printf(MSG_INFO, "BIP replay detected: SA=" MACSTR, - MAC2STR(mgmt->sa)); - wpa_hexdump(MSG_INFO, "RX IPN", mmie + 2, 6); - wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6); - } - - if (check_mmie_mic(bss->igtk[keyid], data, len) < 0) { - wpa_printf(MSG_INFO, "Invalid MMIE MIC in a frame from " - MACSTR, MAC2STR(mgmt->sa)); - bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++; - return -1; - } - - wpa_printf(MSG_DEBUG, "Valid MMIE MIC"); - os_memcpy(bss->ipn[keyid], mmie + 2, 6); - bss->counters[WLANTEST_BSS_COUNTER_VALID_BIP_MMIE]++; - - if (stype == WLAN_FC_STYPE_DEAUTH) - bss->counters[WLANTEST_BSS_COUNTER_BIP_DEAUTH]++; - else if (stype == WLAN_FC_STYPE_DISASSOC) - bss->counters[WLANTEST_BSS_COUNTER_BIP_DISASSOC]++; - - return 0; -} - - -static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len, - size_t *dlen) -{ - struct wlantest_bss *bss; - struct wlantest_sta *sta; - const struct ieee80211_hdr *hdr; - int keyid; - u8 *decrypted, *frame = NULL; - u8 pn[6], *rsc; - - hdr = (const struct ieee80211_hdr *) data; - bss = bss_get(wt, hdr->addr3); - if (bss == NULL) - return NULL; - if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0) - sta = sta_get(bss, hdr->addr2); - else - sta = sta_get(bss, hdr->addr1); - if (sta == NULL || !sta->ptk_set) { - wpa_printf(MSG_MSGDUMP, "No PTK known to decrypt the frame"); - return NULL; - } - - if (len < 24 + 4) - return NULL; - - if (!(data[24 + 3] & 0x20)) { - wpa_printf(MSG_INFO, "Expected CCMP frame from " MACSTR - " did not have ExtIV bit set to 1", - MAC2STR(hdr->addr2)); - return NULL; - } - - if (data[24 + 2] != 0 || (data[24 + 3] & 0x1f) != 0) { - wpa_printf(MSG_INFO, "CCMP mgmt frame from " MACSTR " used " - "non-zero reserved bit", MAC2STR(hdr->addr2)); - } - - keyid = data[24 + 3] >> 6; - if (keyid != 0) { - wpa_printf(MSG_INFO, "Unexpected non-zero KeyID %d in " - "individually addressed Management frame from " - MACSTR, keyid, MAC2STR(hdr->addr2)); - } - - if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0) - rsc = sta->rsc_tods[16]; - else - rsc = sta->rsc_fromds[16]; - - ccmp_get_pn(pn, data + 24); - if (os_memcmp(pn, rsc, 6) <= 0) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3), - WLAN_GET_SEQ_SEQ(seq_ctrl), - WLAN_GET_SEQ_FRAG(seq_ctrl)); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", rsc, 6); - } - - decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data + 24, len - 24, dlen); - if (decrypted) { - os_memcpy(rsc, pn, 6); - frame = os_malloc(24 + *dlen); - if (frame) { - os_memcpy(frame, data, 24); - os_memcpy(frame + 24, decrypted, *dlen); - *dlen += 24; - } - } - - os_free(decrypted); - - return frame; -} - - -static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - u16 fc; - struct wlantest_bss *bss; - struct wlantest_sta *sta; - - mgmt = (const struct ieee80211_mgmt *) data; - fc = le_to_host16(mgmt->frame_control); - - if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { - if (len > 24 && - mgmt->u.action.category == WLAN_ACTION_PUBLIC) - return 0; /* Not a robust management frame */ - } - - bss = bss_get(wt, mgmt->bssid); - if (bss == NULL) - return 0; - if (os_memcmp(mgmt->da, mgmt->bssid, ETH_ALEN) == 0) - sta = sta_get(bss, mgmt->sa); - else - sta = sta_get(bss, mgmt->da); - if (sta == NULL) - return 0; - - if ((sta->rsn_capab & WPA_CAPABILITY_MFPC) && - (sta->state == STATE3 || - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION)) { - wpa_printf(MSG_INFO, "Robust individually-addressed " - "management frame sent without CCMP by " - MACSTR, MAC2STR(mgmt->sa)); - return -1; - } - - return 0; -} - - -void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ieee80211_hdr *hdr; - u16 fc, stype; - int valid = 1; - u8 *decrypted = NULL; - size_t dlen; - - if (len < 24) - return; - - hdr = (const struct ieee80211_hdr *) data; - fc = le_to_host16(hdr->frame_control); - wt->rx_mgmt++; - stype = WLAN_FC_GET_STYPE(fc); - - if ((hdr->addr1[0] & 0x01) && - (stype == WLAN_FC_STYPE_DEAUTH || - stype == WLAN_FC_STYPE_DISASSOC || - stype == WLAN_FC_STYPE_ACTION)) { - if (check_bip(wt, data, len) < 0) - valid = 0; - } - - wpa_printf((stype == WLAN_FC_STYPE_BEACON || - stype == WLAN_FC_STYPE_PROBE_RESP || - stype == WLAN_FC_STYPE_PROBE_REQ) ? - MSG_EXCESSIVE : MSG_MSGDUMP, - "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR, - mgmt_stype(stype), - fc & WLAN_FC_PWRMGT ? " PwrMgt" : "", - fc & WLAN_FC_ISWEP ? " Prot" : "", - MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3)); - - if ((fc & WLAN_FC_ISWEP) && - !(hdr->addr1[0] & 0x01) && - (stype == WLAN_FC_STYPE_DEAUTH || - stype == WLAN_FC_STYPE_DISASSOC || - stype == WLAN_FC_STYPE_ACTION)) { - decrypted = mgmt_ccmp_decrypt(wt, data, len, &dlen); - if (decrypted) { - write_pcap_decrypted(wt, decrypted, dlen, NULL, 0); - data = decrypted; - len = dlen; - } else - valid = 0; - } - - if (!(fc & WLAN_FC_ISWEP) && - !(hdr->addr1[0] & 0x01) && - (stype == WLAN_FC_STYPE_DEAUTH || - stype == WLAN_FC_STYPE_DISASSOC || - stype == WLAN_FC_STYPE_ACTION)) { - if (check_mgmt_ccmp(wt, data, len) < 0) - valid = 0; - } - - switch (stype) { - case WLAN_FC_STYPE_BEACON: - rx_mgmt_beacon(wt, data, len); - break; - case WLAN_FC_STYPE_PROBE_RESP: - rx_mgmt_probe_resp(wt, data, len); - break; - case WLAN_FC_STYPE_AUTH: - rx_mgmt_auth(wt, data, len); - break; - case WLAN_FC_STYPE_DEAUTH: - rx_mgmt_deauth(wt, data, len, valid); - break; - case WLAN_FC_STYPE_ASSOC_REQ: - rx_mgmt_assoc_req(wt, data, len); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - rx_mgmt_assoc_resp(wt, data, len); - break; - case WLAN_FC_STYPE_REASSOC_REQ: - rx_mgmt_reassoc_req(wt, data, len); - break; - case WLAN_FC_STYPE_REASSOC_RESP: - rx_mgmt_reassoc_resp(wt, data, len); - break; - case WLAN_FC_STYPE_DISASSOC: - rx_mgmt_disassoc(wt, data, len, valid); - break; - case WLAN_FC_STYPE_ACTION: - rx_mgmt_action(wt, data, len, valid); - break; - } - - 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/rx_tdls.c b/wlantest/rx_tdls.c deleted file mode 100644 index 08a29a5..0000000 --- a/wlantest/rx_tdls.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Received Data frame processing for TDLS packets - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "crypto/sha256.h" -#include "crypto/crypto.h" -#include "crypto/aes_wrap.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "wlantest.h" - - -static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *linkid, - int create_new, const u8 *bssid) -{ - struct wlantest_bss *bss; - struct wlantest_sta *init, *resp; - struct wlantest_tdls *tdls; - - bss = bss_find(wt, linkid); - if (bss == NULL && bssid) { - bss = bss_find(wt, bssid); - if (bss) - wpa_printf(MSG_INFO, "TDLS: Incorrect BSSID " MACSTR - " in LinkId?! (init=" MACSTR " resp=" - MACSTR ")", - MAC2STR(linkid), MAC2STR(linkid + ETH_ALEN), - MAC2STR(linkid + 2 * ETH_ALEN)); - } - if (bss == NULL) - return NULL; - - init = sta_find(bss, linkid + ETH_ALEN); - if (init == NULL) - return NULL; - - resp = sta_find(bss, linkid + 2 * ETH_ALEN); - if (resp == NULL) - return NULL; - - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if (tdls->init == init && tdls->resp == resp) - return tdls; - } - - if (!create_new) - return NULL; - - tdls = os_zalloc(sizeof(*tdls)); - if (tdls == NULL) - return NULL; - tdls->init = init; - tdls->resp = resp; - dl_list_add(&bss->tdls, &tdls->list); - return tdls; -} - - -static int tdls_derive_tpk(struct wlantest_tdls *tdls, const u8 *bssid, - const u8 *ftie, u8 ftie_len) -{ - const struct rsn_ftie *f; - u8 key_input[SHA256_MAC_LEN]; - const u8 *nonce[2]; - size_t len[2]; - u8 data[3 * ETH_ALEN]; - - if (ftie == NULL || ftie_len < sizeof(struct rsn_ftie)) - return 0; - - f = (const struct rsn_ftie *) ftie; - wpa_hexdump(MSG_DEBUG, "TDLS ANonce", f->anonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "TDLS SNonce", f->snonce, WPA_NONCE_LEN); - - /* - * IEEE Std 802.11z-2010 8.5.9.1: - * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce)) - */ - len[0] = WPA_NONCE_LEN; - len[1] = WPA_NONCE_LEN; - if (os_memcmp(f->anonce, f->snonce, WPA_NONCE_LEN) < 0) { - nonce[0] = f->anonce; - nonce[1] = f->snonce; - } else { - nonce[0] = f->snonce; - nonce[1] = f->anonce; - } - sha256_vector(2, nonce, len, key_input); - wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input", - key_input, SHA256_MAC_LEN); - - /* - * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK", - * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY) - * TODO: is N_KEY really included in KDF Context and if so, in which - * presentation format (little endian 16-bit?) is it used? It gets - * added by the KDF anyway.. - */ - - if (os_memcmp(tdls->init->addr, tdls->resp->addr, ETH_ALEN) < 0) { - os_memcpy(data, tdls->init->addr, ETH_ALEN); - os_memcpy(data + ETH_ALEN, tdls->resp->addr, ETH_ALEN); - } else { - os_memcpy(data, tdls->resp->addr, ETH_ALEN); - os_memcpy(data + ETH_ALEN, tdls->init->addr, ETH_ALEN); - } - os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN); - wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data)); - - sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), - (u8 *) &tdls->tpk, sizeof(tdls->tpk)); - wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK", - tdls->tpk.kck, sizeof(tdls->tpk.kck)); - wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK", - tdls->tpk.tk, sizeof(tdls->tpk.tk)); - - return 1; -} - - -static int tdls_verify_mic(struct wlantest_tdls *tdls, u8 trans_seq, - struct ieee802_11_elems *elems) -{ - u8 *buf, *pos; - int len; - u8 mic[16]; - int ret; - const struct rsn_ftie *rx_ftie; - struct rsn_ftie *tmp_ftie; - - if (elems->link_id == NULL || elems->rsn_ie == NULL || - elems->timeout_int == NULL || elems->ftie == NULL) - return -1; - - len = 2 * ETH_ALEN + 1 + 2 + 18 + 2 + elems->rsn_ie_len + - 2 + elems->timeout_int_len + 2 + elems->ftie_len; - - buf = os_zalloc(len); - if (buf == NULL) - return -1; - - pos = buf; - /* 1) TDLS initiator STA MAC address */ - os_memcpy(pos, elems->link_id + ETH_ALEN, ETH_ALEN); - pos += ETH_ALEN; - /* 2) TDLS responder STA MAC address */ - os_memcpy(pos, elems->link_id + 2 * ETH_ALEN, ETH_ALEN); - pos += ETH_ALEN; - /* 3) Transaction Sequence number */ - *pos++ = trans_seq; - /* 4) Link Identifier IE */ - os_memcpy(pos, elems->link_id - 2, 2 + 18); - pos += 2 + 18; - /* 5) RSN IE */ - os_memcpy(pos, elems->rsn_ie - 2, 2 + elems->rsn_ie_len); - pos += 2 + elems->rsn_ie_len; - /* 6) Timeout Interval IE */ - os_memcpy(pos, elems->timeout_int - 2, 2 + elems->timeout_int_len); - pos += 2 + elems->timeout_int_len; - /* 7) FTIE, with the MIC field of the FTIE set to 0 */ - os_memcpy(pos, elems->ftie - 2, 2 + elems->ftie_len); - pos += 2; - tmp_ftie = (struct rsn_ftie *) pos; - os_memset(tmp_ftie->mic, 0, 16); - pos += elems->ftie_len; - - wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); - wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", tdls->tpk.kck, 16); - ret = omac1_aes_128(tdls->tpk.kck, buf, pos - buf, mic); - os_free(buf); - if (ret) - return -1; - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); - rx_ftie = (const struct rsn_ftie *) elems->ftie; - - if (os_memcmp(mic, rx_ftie->mic, 16) == 0) { - wpa_printf(MSG_DEBUG, "TDLS: Valid MIC"); - return 0; - } - wpa_printf(MSG_DEBUG, "TDLS: Invalid MIC"); - return -1; -} - - -static void rx_data_tdls_setup_request(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, - const u8 *src, - const u8 *data, size_t len) -{ - struct ieee802_11_elems elems; - struct wlantest_tdls *tdls; - - if (len < 3) { - wpa_printf(MSG_INFO, "Too short TDLS Setup Request " MACSTR - " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); - return; - } - wpa_printf(MSG_DEBUG, "TDLS Setup Request " MACSTR " -> " - MACSTR, MAC2STR(src), MAC2STR(dst)); - - if (ieee802_11_parse_elems(data + 3, len - 3, &elems, 1) == - ParseFailed || elems.link_id == NULL) - return; - wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR - " 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, 1, bssid); - if (tdls) { - tdls->counters[WLANTEST_TDLS_COUNTER_SETUP_REQ]++; - tdls->dialog_token = data[0]; - } -} - - -static void rx_data_tdls_setup_response_failure(struct wlantest *wt, - const u8 *bssid, - const u8 *sta_addr, - u8 dialog_token, u16 status) -{ - struct wlantest_bss *bss; - struct wlantest_tdls *tdls; - struct wlantest_sta *sta; - - if (status == WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_INFO, "TDLS: Invalid TDLS Setup Response from " - MACSTR, MAC2STR(sta_addr)); - return; - } - - bss = bss_find(wt, bssid); - if (!bss) - return; - sta = sta_find(bss, sta_addr); - if (!sta) - return; - - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if (tdls->resp == sta) { - if (dialog_token != tdls->dialog_token) { - wpa_printf(MSG_DEBUG, "TDLS: Dialog token " - "mismatch in TDLS Setup Response " - "(failure)"); - break; - } - wpa_printf(MSG_DEBUG, "TDLS: Found matching TDLS " - "setup session based on dialog token"); - tdls->counters[ - WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL]++; - break; - } - } -} - - -static void rx_data_tdls_setup_response(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, - const u8 *src, - const u8 *data, size_t len) -{ - u16 status; - struct ieee802_11_elems elems; - struct wlantest_tdls *tdls; - - if (len < 3) { - wpa_printf(MSG_INFO, "Too short TDLS Setup Response " MACSTR - " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); - return; - } - status = WPA_GET_LE16(data); - wpa_printf(MSG_DEBUG, "TDLS Setup Response " MACSTR " -> " - MACSTR " (status %d)", - MAC2STR(src), MAC2STR(dst), status); - if (len < 5 && status == 0) { - wpa_printf(MSG_INFO, "Too short TDLS Setup Response " MACSTR - " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); - return; - } - - if (len < 5 || - ieee802_11_parse_elems(data + 5, len - 5, &elems, 1) == - ParseFailed || elems.link_id == NULL) { - /* Need to match TDLS link based on Dialog Token */ - rx_data_tdls_setup_response_failure(wt, bssid, sta_addr, - data[2], status); - return; - } - wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR - " 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, 1, bssid); - if (!tdls) - return; - if (status) - tdls->counters[WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL]++; - else - tdls->counters[WLANTEST_TDLS_COUNTER_SETUP_RESP_OK]++; - - if (status != WLAN_STATUS_SUCCESS) - return; - - if (tdls_derive_tpk(tdls, bssid, elems.ftie, elems.ftie_len) < 1) - return; - if (tdls_verify_mic(tdls, 2, &elems) == 0) { - tdls->dialog_token = data[2]; - wpa_printf(MSG_DEBUG, "TDLS: Dialog Token for the link: %u", - tdls->dialog_token); - } -} - - -static void rx_data_tdls_setup_confirm_failure(struct wlantest *wt, - const u8 *bssid, - const u8 *src, - u8 dialog_token, u16 status) -{ - struct wlantest_bss *bss; - struct wlantest_tdls *tdls; - struct wlantest_sta *sta; - - if (status == WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_INFO, "TDLS: Invalid TDLS Setup Confirm from " - MACSTR, MAC2STR(src)); - return; - } - - bss = bss_find(wt, bssid); - if (!bss) - return; - sta = sta_find(bss, src); - if (!sta) - return; - - dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { - if (tdls->init == sta) { - if (dialog_token != tdls->dialog_token) { - wpa_printf(MSG_DEBUG, "TDLS: Dialog token " - "mismatch in TDLS Setup Confirm " - "(failure)"); - break; - } - wpa_printf(MSG_DEBUG, "TDLS: Found matching TDLS " - "setup session based on dialog token"); - tdls->counters[ - WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL]++; - break; - } - } -} - - -static void rx_data_tdls_setup_confirm(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, - const u8 *src, - const u8 *data, size_t len) -{ - u16 status; - struct ieee802_11_elems elems; - struct wlantest_tdls *tdls; - u8 link_id[3 * ETH_ALEN]; - - if (len < 3) { - wpa_printf(MSG_INFO, "Too short TDLS Setup Confirm " MACSTR - " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); - return; - } - status = WPA_GET_LE16(data); - wpa_printf(MSG_DEBUG, "TDLS Setup Confirm " MACSTR " -> " - MACSTR " (status %d)", - MAC2STR(src), MAC2STR(dst), status); - - if (ieee802_11_parse_elems(data + 3, len - 3, &elems, 1) == - ParseFailed || elems.link_id == NULL) { - /* Need to match TDLS link based on Dialog Token */ - rx_data_tdls_setup_confirm_failure(wt, bssid, src, - data[2], status); - return; - } - wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR - " 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, 1, bssid); - if (tdls == NULL) - return; - if (status) - tdls->counters[WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL]++; - else - tdls->counters[WLANTEST_TDLS_COUNTER_SETUP_CONF_OK]++; - - if (status != WLAN_STATUS_SUCCESS) - return; - - tdls->link_up = 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, bssid); - if (tdls) { - wpa_printf(MSG_DEBUG, "TDLS: Remove reverse link entry"); - tdls_deinit(tdls); - } -} - - -static int tdls_verify_mic_teardown(struct wlantest_tdls *tdls, u8 trans_seq, - const u8 *reason_code, - struct ieee802_11_elems *elems) -{ - u8 *buf, *pos; - int len; - u8 mic[16]; - int ret; - const struct rsn_ftie *rx_ftie; - struct rsn_ftie *tmp_ftie; - - if (elems->link_id == NULL || elems->ftie == NULL) - return -1; - - len = 2 + 18 + 2 + 1 + 1 + 2 + elems->ftie_len; - - buf = os_zalloc(len); - if (buf == NULL) - return -1; - - pos = buf; - /* 1) Link Identifier IE */ - os_memcpy(pos, elems->link_id - 2, 2 + 18); - pos += 2 + 18; - /* 2) Reason Code */ - os_memcpy(pos, reason_code, 2); - pos += 2; - /* 3) Dialog token */ - *pos++ = tdls->dialog_token; - /* 4) Transaction Sequence number */ - *pos++ = trans_seq; - /* 5) FTIE, with the MIC field of the FTIE set to 0 */ - os_memcpy(pos, elems->ftie - 2, 2 + elems->ftie_len); - pos += 2; - tmp_ftie = (struct rsn_ftie *) pos; - os_memset(tmp_ftie->mic, 0, 16); - pos += elems->ftie_len; - - wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); - wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", tdls->tpk.kck, 16); - ret = omac1_aes_128(tdls->tpk.kck, buf, pos - buf, mic); - os_free(buf); - if (ret) - return -1; - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); - rx_ftie = (const struct rsn_ftie *) elems->ftie; - - if (os_memcmp(mic, rx_ftie->mic, 16) == 0) { - wpa_printf(MSG_DEBUG, "TDLS: Valid MIC"); - return 0; - } - wpa_printf(MSG_DEBUG, "TDLS: Invalid MIC"); - return -1; -} - - -static void rx_data_tdls_teardown(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, - const u8 *src, - const u8 *data, size_t len) -{ - u16 reason; - struct ieee802_11_elems elems; - struct wlantest_tdls *tdls; - - if (len < 2) - return; - reason = WPA_GET_LE16(data); - wpa_printf(MSG_DEBUG, "TDLS Teardown " MACSTR " -> " - MACSTR " (reason %d)", - MAC2STR(src), MAC2STR(dst), reason); - - if (ieee802_11_parse_elems(data + 2, len - 2, &elems, 1) == - ParseFailed || elems.link_id == NULL) - return; - wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR - " 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, 1, bssid); - if (tdls) { - tdls->link_up = 0; - tdls->counters[WLANTEST_TDLS_COUNTER_TEARDOWN]++; - tdls_verify_mic_teardown(tdls, 4, data, &elems); - } -} - - -static void rx_data_tdls(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, const u8 *src, - const u8 *data, size_t len) -{ - /* data contains the payload of a TDLS Action frame */ - if (len < 2 || data[0] != WLAN_ACTION_TDLS) { - wpa_hexdump(MSG_DEBUG, "Unrecognized encapsulated TDLS frame", - data, len); - return; - } - - switch (data[1]) { - case WLAN_TDLS_SETUP_REQUEST: - rx_data_tdls_setup_request(wt, bssid, sta_addr, dst, src, - data + 2, len - 2); - break; - case WLAN_TDLS_SETUP_RESPONSE: - rx_data_tdls_setup_response(wt, bssid, sta_addr, dst, src, - data + 2, len - 2); - break; - case WLAN_TDLS_SETUP_CONFIRM: - rx_data_tdls_setup_confirm(wt, bssid, sta_addr, dst, src, - data + 2, len - 2); - break; - case WLAN_TDLS_TEARDOWN: - rx_data_tdls_teardown(wt, bssid, sta_addr, dst, src, data + 2, - len - 2); - break; - case WLAN_TDLS_DISCOVERY_REQUEST: - wpa_printf(MSG_DEBUG, "TDLS Discovery Request " MACSTR " -> " - MACSTR, MAC2STR(src), MAC2STR(dst)); - break; - } -} - - -void rx_data_80211_encap(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, const u8 *src, - const u8 *data, size_t len) -{ - wpa_hexdump(MSG_EXCESSIVE, "802.11 data encap frame", data, len); - if (len < 1) - return; - if (data[0] == 0x02) - rx_data_tdls(wt, bssid, sta_addr, dst, src, data + 1, len - 1); -} diff --git a/wlantest/sta.c b/wlantest/sta.c deleted file mode 100644 index 115ef8a..0000000 --- a/wlantest/sta.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * STA list - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/defs.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "wlantest.h" - - -struct wlantest_sta * sta_find(struct wlantest_bss *bss, const u8 *addr) -{ - struct wlantest_sta *sta; - - dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) { - if (os_memcmp(sta->addr, addr, ETH_ALEN) == 0) - return sta; - } - - return NULL; -} - - -struct wlantest_sta * sta_get(struct wlantest_bss *bss, const u8 *addr) -{ - struct wlantest_sta *sta; - - if (addr[0] & 0x01) - return NULL; /* Skip group addressed frames */ - - sta = sta_find(bss, addr); - if (sta) - return sta; - - 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); - wpa_printf(MSG_DEBUG, "Discovered new STA " MACSTR " in BSS " MACSTR, - MAC2STR(sta->addr), MAC2STR(bss->bssid)); - return sta; -} - - -void sta_deinit(struct wlantest_sta *sta) -{ - dl_list_del(&sta->list); - os_free(sta->assocreq_ies); - os_free(sta); -} - - -void sta_update_assoc(struct wlantest_sta *sta, struct ieee802_11_elems *elems) -{ - struct wpa_ie_data data; - struct wlantest_bss *bss = sta->bss; - - if (elems->wpa_ie && !bss->wpaie[0]) { - wpa_printf(MSG_INFO, "WPA IE included in Association Request " - "frame from " MACSTR " even though BSS does not " - "use WPA - ignore IE", - MAC2STR(sta->addr)); - elems->wpa_ie = NULL; - } - - if (elems->rsn_ie && !bss->rsnie[0]) { - wpa_printf(MSG_INFO, "RSN IE included in Association Request " - "frame from " MACSTR " even though BSS does not " - "use RSN - ignore IE", - MAC2STR(sta->addr)); - elems->rsn_ie = NULL; - } - - if (elems->wpa_ie && elems->rsn_ie) { - wpa_printf(MSG_INFO, "Both WPA IE and RSN IE included in " - "Association Request frame from " MACSTR, - MAC2STR(sta->addr)); - } - - if (elems->rsn_ie) { - wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2, - elems->rsn_ie_len + 2); - os_memcpy(sta->rsnie, elems->rsn_ie - 2, - elems->rsn_ie_len + 2); - if (wpa_parse_wpa_ie_rsn(sta->rsnie, 2 + sta->rsnie[1], &data) - < 0) { - wpa_printf(MSG_INFO, "Failed to parse RSN IE from " - MACSTR, MAC2STR(sta->addr)); - } - } else if (elems->wpa_ie) { - wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2, - elems->wpa_ie_len + 2); - os_memcpy(sta->rsnie, elems->wpa_ie - 2, - elems->wpa_ie_len + 2); - if (wpa_parse_wpa_ie_wpa(sta->rsnie, 2 + sta->rsnie[1], &data) - < 0) { - wpa_printf(MSG_INFO, "Failed to parse WPA IE from " - MACSTR, MAC2STR(sta->addr)); - } - } else { - sta->rsnie[0] = 0; - sta->proto = 0; - sta->pairwise_cipher = 0; - sta->key_mgmt = 0; - sta->rsn_capab = 0; - if (sta->assocreq_capab_info & WLAN_CAPABILITY_PRIVACY) - sta->pairwise_cipher = WPA_CIPHER_WEP40; - goto skip_rsn_wpa; - } - - sta->proto = data.proto; - sta->pairwise_cipher = data.pairwise_cipher; - sta->key_mgmt = data.key_mgmt; - sta->rsn_capab = data.capabilities; - if (bss->proto && (sta->proto & bss->proto) == 0) { - wpa_printf(MSG_INFO, "Mismatch in WPA/WPA2 proto: STA " - MACSTR " 0x%x BSS " MACSTR " 0x%x", - MAC2STR(sta->addr), sta->proto, - MAC2STR(bss->bssid), bss->proto); - } - if (bss->pairwise_cipher && - (sta->pairwise_cipher & bss->pairwise_cipher) == 0) { - wpa_printf(MSG_INFO, "Mismatch in pairwise cipher: STA " - MACSTR " 0x%x BSS " MACSTR " 0x%x", - MAC2STR(sta->addr), sta->pairwise_cipher, - MAC2STR(bss->bssid), bss->pairwise_cipher); - } - if (sta->proto && data.group_cipher != bss->group_cipher) { - wpa_printf(MSG_INFO, "Mismatch in group cipher: STA " - MACSTR " 0x%x != BSS " MACSTR " 0x%x", - MAC2STR(sta->addr), data.group_cipher, - MAC2STR(bss->bssid), bss->group_cipher); - } - if ((bss->rsn_capab & WPA_CAPABILITY_MFPR) && - !(sta->rsn_capab & WPA_CAPABILITY_MFPC)) { - wpa_printf(MSG_INFO, "STA " MACSTR " tries to associate " - "without MFP to BSS " MACSTR " that advertises " - "MFPR", MAC2STR(sta->addr), MAC2STR(bss->bssid)); - } - -skip_rsn_wpa: - wpa_printf(MSG_INFO, "STA " MACSTR - " proto=%s%s%s" - "pairwise=%s%s%s%s" - "key_mgmt=%s%s%s%s%s%s%s%s" - "rsn_capab=%s%s%s%s%s", - MAC2STR(sta->addr), - sta->proto == 0 ? "OPEN " : "", - sta->proto & WPA_PROTO_WPA ? "WPA " : "", - sta->proto & WPA_PROTO_RSN ? "WPA2 " : "", - sta->pairwise_cipher == 0 ? "N/A " : "", - sta->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "", - sta->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", - sta->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", - sta->key_mgmt == 0 ? "N/A " : "", - sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "", - sta->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "", - sta->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "", - sta->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "", - sta->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "", - sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ? - "EAP-SHA256 " : "", - sta->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ? - "PSK-SHA256 " : "", - sta->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", - sta->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? - "NO_PAIRWISE " : "", - sta->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "", - sta->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "", - sta->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ? - "PEERKEY " : ""); -} diff --git a/wlantest/tkip.c b/wlantest/tkip.c deleted file mode 100644 index 2d626f3..0000000 --- a/wlantest/tkip.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Temporal Key Integrity Protocol (CCMP) - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "wlantest.h" - - -void wep_crypt(u8 *key, u8 *buf, size_t plen); - - -static inline u16 RotR1(u16 val) -{ - return (val >> 1) | (val << 15); -} - - -static inline u8 Lo8(u16 val) -{ - return val & 0xff; -} - - -static inline u8 Hi8(u16 val) -{ - return val >> 8; -} - - -static inline u16 Lo16(u32 val) -{ - return val & 0xffff; -} - - -static inline u16 Hi16(u32 val) -{ - return val >> 16; -} - - -static inline u16 Mk16(u8 hi, u8 lo) -{ - return lo | (((u16) hi) << 8); -} - - -static inline u16 Mk16_le(u16 *v) -{ - return le_to_host16(*v); -} - - -static const u16 Sbox[256] = -{ - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, -}; - - -static inline u16 _S_(u16 v) -{ - u16 t = Sbox[Hi8(v)]; - return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); -} - - -#define PHASE1_LOOP_COUNT 8 - -static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) -{ - int i, j; - - /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ - TTAK[0] = Lo16(IV32); - TTAK[1] = Hi16(IV32); - TTAK[2] = Mk16(TA[1], TA[0]); - TTAK[3] = Mk16(TA[3], TA[2]); - TTAK[4] = Mk16(TA[5], TA[4]); - - for (i = 0; i < PHASE1_LOOP_COUNT; i++) { - j = 2 * (i & 1); - TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); - TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); - TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); - TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); - TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; - } -} - - -static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, - u16 IV16) -{ - u16 PPK[6]; - - /* Step 1 - make copy of TTAK and bring in TSC */ - PPK[0] = TTAK[0]; - PPK[1] = TTAK[1]; - PPK[2] = TTAK[2]; - PPK[3] = TTAK[3]; - PPK[4] = TTAK[4]; - PPK[5] = TTAK[4] + IV16; - - /* Step 2 - 96-bit bijective mixing using S-box */ - PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); - PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); - PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); - PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); - PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); - PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); - - PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); - PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - - /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value - * WEPSeed[0..2] is transmitted as WEP IV */ - WEPSeed[0] = Hi8(IV16); - WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; - WEPSeed[2] = Lo8(IV16); - WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); - WPA_PUT_LE16(&WEPSeed[4], PPK[0]); - WPA_PUT_LE16(&WEPSeed[6], PPK[1]); - WPA_PUT_LE16(&WEPSeed[8], PPK[2]); - WPA_PUT_LE16(&WEPSeed[10], PPK[3]); - WPA_PUT_LE16(&WEPSeed[12], PPK[4]); - WPA_PUT_LE16(&WEPSeed[14], PPK[5]); -} - - -static inline u32 rotl(u32 val, int bits) -{ - return (val << bits) | (val >> (32 - bits)); -} - - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - - -static inline u32 xswap(u32 val) -{ - return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); -} - - -#define michael_block(l, r) \ -do { \ - r ^= rotl(l, 17); \ - l += r; \ - r ^= xswap(l); \ - l += r; \ - r ^= rotl(l, 3); \ - l += r; \ - r ^= rotr(l, 2); \ - l += r; \ -} while (0) - - -static void michael_mic(const u8 *key, const u8 *hdr, const u8 *data, - size_t data_len, u8 *mic) -{ - u32 l, r; - int i, blocks, last; - - l = WPA_GET_LE32(key); - r = WPA_GET_LE32(key + 4); - - /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - l ^= WPA_GET_LE32(hdr); - michael_block(l, r); - l ^= WPA_GET_LE32(&hdr[4]); - michael_block(l, r); - l ^= WPA_GET_LE32(&hdr[8]); - michael_block(l, r); - l ^= WPA_GET_LE32(&hdr[12]); - michael_block(l, r); - - /* 32-bit blocks of data */ - blocks = data_len / 4; - last = data_len % 4; - for (i = 0; i < blocks; i++) { - l ^= WPA_GET_LE32(&data[4 * i]); - michael_block(l, r); - } - - /* Last block and padding (0x5a, 4..7 x 0) */ - switch (last) { - case 0: - l ^= 0x5a; - break; - case 1: - l ^= data[4 * i] | 0x5a00; - break; - case 2: - l ^= data[4 * i] | (data[4 * i + 1] << 8) | 0x5a0000; - break; - case 3: - l ^= data[4 * i] | (data[4 * i + 1] << 8) | - (data[4 * i + 2] << 16) | 0x5a000000; - break; - } - michael_block(l, r); - /* l ^= 0; */ - michael_block(l, r); - - WPA_PUT_LE32(mic, l); - WPA_PUT_LE32(mic + 4, r); -} - - -static void michael_mic_hdr(const struct ieee80211_hdr *hdr11, u8 *hdr) -{ - int hdrlen = 24; - u16 fc = le_to_host16(hdr11->frame_control); - - switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { - case WLAN_FC_TODS: - os_memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ - os_memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ - break; - case WLAN_FC_FROMDS: - os_memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ - os_memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ - break; - case WLAN_FC_FROMDS | WLAN_FC_TODS: - os_memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ - os_memcpy(hdr + ETH_ALEN, hdr11 + 1, ETH_ALEN); /* SA */ - hdrlen += ETH_ALEN; - break; - case 0: - os_memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ - os_memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ - break; - } - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - (WLAN_FC_GET_STYPE(fc) & 0x08)) { - const u8 *qos = ((const u8 *) hdr11) + hdrlen; - hdr[12] = qos[0] & 0x0f; /* priority */ - } else - hdr[12] = 0; /* priority */ - - hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ -} - - -u8 * tkip_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, - const u8 *data, size_t data_len, size_t *decrypted_len) -{ - u16 iv16; - u32 iv32; - u16 ttak[5]; - u8 rc4key[16]; - u8 *plain; - size_t plain_len; - u32 icv, rx_icv; - const u8 *mic_key; - u8 michael_hdr[16]; - u8 mic[8]; - u16 fc = le_to_host16(hdr->frame_control); - - if (data_len < 8 + 4) - return NULL; - - iv16 = (data[0] << 8) | data[2]; - iv32 = WPA_GET_LE32(&data[4]); - wpa_printf(MSG_EXCESSIVE, "TKIP decrypt: iv32=%08x iv16=%04x", - iv32, iv16); - - tkip_mixing_phase1(ttak, tk, hdr->addr2, iv32); - wpa_hexdump(MSG_EXCESSIVE, "TKIP TTAK", (u8 *) ttak, sizeof(ttak)); - tkip_mixing_phase2(rc4key, tk, ttak, iv16); - wpa_hexdump(MSG_EXCESSIVE, "TKIP RC4KEY", rc4key, sizeof(rc4key)); - - plain_len = data_len - 8; - plain = os_malloc(plain_len); - if (plain == NULL) - return NULL; - os_memcpy(plain, data + 8, plain_len); - wep_crypt(rc4key, plain, plain_len); - - icv = crc32(plain, plain_len - 4); - rx_icv = WPA_GET_LE32(plain + plain_len - 4); - if (icv != rx_icv) { - wpa_printf(MSG_INFO, "TKIP ICV mismatch in frame from " MACSTR, - MAC2STR(hdr->addr2)); - wpa_printf(MSG_DEBUG, "TKIP calculated ICV %08x received ICV " - "%08x", icv, rx_icv); - os_free(plain); - return NULL; - } - plain_len -= 4; - - /* TODO: MSDU reassembly */ - - if (plain_len < 8) { - wpa_printf(MSG_INFO, "TKIP: Not enough room for Michael MIC " - "in a frame from " MACSTR, MAC2STR(hdr->addr2)); - os_free(plain); - return NULL; - } - - michael_mic_hdr(hdr, michael_hdr); - mic_key = tk + ((fc & WLAN_FC_FROMDS) ? 16 : 24); - michael_mic(mic_key, michael_hdr, plain, plain_len - 8, mic); - if (os_memcmp(mic, plain + plain_len - 8, 8) != 0) { - wpa_printf(MSG_INFO, "TKIP: Michael MIC mismatch in a frame " - "from " MACSTR, MAC2STR(hdr->addr2)); - wpa_hexdump(MSG_DEBUG, "TKIP: Calculated MIC", mic, 8); - wpa_hexdump(MSG_DEBUG, "TKIP: Received MIC", - plain + plain_len - 8, 8); - os_free(plain); - return NULL; - } - - *decrypted_len = plain_len - 8; - return plain; -} - - -void tkip_get_pn(u8 *pn, const u8 *data) -{ - pn[0] = data[7]; /* PN5 */ - pn[1] = data[6]; /* PN4 */ - pn[2] = data[5]; /* PN3 */ - pn[3] = data[4]; /* PN2 */ - pn[4] = data[0]; /* PN1 */ - pn[5] = data[2]; /* PN0 */ -} - - -u8 * tkip_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, - u8 *pn, int keyid, size_t *encrypted_len) -{ - /* TODO */ - return NULL; -} diff --git a/wlantest/wep.c b/wlantest/wep.c deleted file mode 100644 index c4137f3..0000000 --- a/wlantest/wep.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Wired Equivalent Privacy (WEP) - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "wlantest.h" - - -void wep_crypt(u8 *key, u8 *buf, size_t plen) -{ - u32 i, j, k; - u8 S[256]; -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - u8 *pos; - - /* Setup RC4 state */ - for (i = 0; i < 256; i++) - S[i] = i; - j = 0; - for (i = 0; i < 256; i++) { - j = (j + S[i] + key[i & 0x0f]) & 0xff; - S_SWAP(i, j); - } - - /* Apply RC4 to data */ - pos = buf; - i = j = 0; - for (k = 0; k < plen; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - *pos ^= S[(S[i] + S[j]) & 0xff]; - pos++; - } -} - - -static int try_wep(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *plain) -{ - u32 icv, rx_icv; - u8 k[16]; - int i, j; - - for (i = 0, j = 0; i < sizeof(k); i++) { - k[i] = key[j]; - j++; - if (j >= key_len) - j = 0; - } - - os_memcpy(plain, data, data_len); - wep_crypt(k, plain, data_len); - icv = crc32(plain, data_len - 4); - rx_icv = WPA_GET_LE32(plain + data_len - 4); - if (icv != rx_icv) - return -1; - - return 0; -} - - -u8 * wep_decrypt(struct wlantest *wt, const struct ieee80211_hdr *hdr, - const u8 *data, size_t data_len, size_t *decrypted_len) -{ - u8 *plain; - struct wlantest_wep *w; - int found = 0; - u8 key[16]; - - if (dl_list_empty(&wt->wep)) - return NULL; - - if (data_len < 4 + 4) - return NULL; - plain = os_malloc(data_len - 4); - if (plain == NULL) - return NULL; - - dl_list_for_each(w, &wt->wep, struct wlantest_wep, list) { - os_memcpy(key, data, 3); - os_memcpy(key + 3, w->key, w->key_len); - if (try_wep(key, 3 + w->key_len, data + 4, data_len - 4, plain) - == 0) { - found = 1; - break; - } - } - if (!found) { - os_free(plain); - return NULL; - } - - *decrypted_len = data_len - 4 - 4; - return plain; -} diff --git a/wlantest/wired.c b/wlantest/wired.c deleted file mode 100644 index 77a395f..0000000 --- a/wlantest/wired.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Received frame processing for wired interface - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <net/ethernet.h> -#include <netinet/ip.h> -#include <netinet/udp.h> - -#include "utils/common.h" -#include "radius/radius.h" -#include "wlantest.h" - - -static struct wlantest_radius * radius_get(struct wlantest *wt, u32 srv, - u32 cli) -{ - struct wlantest_radius *r; - - dl_list_for_each(r, &wt->radius, struct wlantest_radius, list) { - if (r->srv == srv && r->cli == cli) - return r; - } - - r = os_zalloc(sizeof(*r)); - if (r == NULL) - return NULL; - - r->srv = srv; - r->cli = cli; - dl_list_add(&wt->radius, &r->list); - - return r; -} - - -static const char * radius_code_string(u8 code) -{ - switch (code) { - case RADIUS_CODE_ACCESS_REQUEST: - return "Access-Request"; - case RADIUS_CODE_ACCESS_ACCEPT: - return "Access-Accept"; - case RADIUS_CODE_ACCESS_REJECT: - return "Access-Reject"; - case RADIUS_CODE_ACCOUNTING_REQUEST: - return "Accounting-Request"; - case RADIUS_CODE_ACCOUNTING_RESPONSE: - return "Accounting-Response"; - case RADIUS_CODE_ACCESS_CHALLENGE: - return "Access-Challenge"; - case RADIUS_CODE_STATUS_SERVER: - return "Status-Server"; - case RADIUS_CODE_STATUS_CLIENT: - return "Status-Client"; - case RADIUS_CODE_RESERVED: - return "Reserved"; - default: - return "?Unknown?"; - } -} - - -static void process_radius_access_request(struct wlantest *wt, u32 dst, - u32 src, const u8 *data, size_t len) -{ - struct radius_msg *msg; - struct wlantest_radius *r; - - msg = radius_msg_parse(data, len); - if (msg == NULL) { - wpa_printf(MSG_DEBUG, "Failed to parse RADIUS Access-Request"); - return; - } - - r = radius_get(wt, dst, src); - if (r) { - radius_msg_free(r->last_req); - r->last_req = msg; - return; - } - radius_msg_free(msg); -} - - -static void wlantest_add_pmk(struct wlantest *wt, const u8 *pmk) -{ - struct wlantest_pmk *p; - - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return; - os_memcpy(p->pmk, pmk, 32); - dl_list_add(&wt->pmk, &p->list); - wpa_hexdump(MSG_INFO, "Add PMK", pmk, 32); -} - - -static void process_radius_access_accept(struct wlantest *wt, u32 dst, u32 src, - const u8 *data, size_t len) -{ - struct radius_msg *msg; - struct wlantest_radius *r; - struct radius_ms_mppe_keys *keys; - struct wlantest_radius_secret *s; - - r = radius_get(wt, src, dst); - if (r == NULL || r->last_req == NULL) { - wpa_printf(MSG_DEBUG, "No RADIUS Access-Challenge found for " - "decrypting Access-Accept keys"); - return; - } - - msg = radius_msg_parse(data, len); - if (msg == NULL) { - wpa_printf(MSG_DEBUG, "Failed to parse RADIUS Access-Accept"); - return; - } - - dl_list_for_each(s, &wt->secret, struct wlantest_radius_secret, list) { - int found = 0; - keys = radius_msg_get_ms_keys(msg, r->last_req, - (u8 *) s->secret, - os_strlen(s->secret)); - if (keys && keys->send && keys->recv) { - u8 pmk[32]; - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", - keys->send, keys->send_len); - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", - keys->recv, keys->recv_len); - os_memcpy(pmk, keys->recv, - keys->recv_len > 32 ? 32 : keys->recv_len); - if (keys->recv_len < 32) { - os_memcpy(pmk + keys->recv_len, - keys->send, - keys->recv_len + keys->send_len > 32 - ? 32 : 32 - keys->recv_len); - } - wlantest_add_pmk(wt, pmk); - found = 1; - } - - if (keys) { - os_free(keys->send); - os_free(keys->recv); - os_free(keys); - } - - if (found) - break; - } - - radius_msg_free(msg); -} - - -static void process_radius(struct wlantest *wt, u32 dst, u16 dport, u32 src, - u16 sport, const u8 *data, size_t len) -{ - struct in_addr addr; - char buf[20]; - const struct radius_hdr *hdr; - u16 rlen; - - if (len < sizeof(*hdr)) - return; - hdr = (const struct radius_hdr *) data; - rlen = be_to_host16(hdr->length); - if (len < rlen) - return; - if (len > rlen) - len = rlen; - - addr.s_addr = dst; - snprintf(buf, sizeof(buf), "%s", inet_ntoa(addr)); - - addr.s_addr = src; - wpa_printf(MSG_DEBUG, "RADIUS %s:%u -> %s:%u id=%u %s", - inet_ntoa(addr), sport, buf, dport, hdr->identifier, - radius_code_string(hdr->code)); - - switch (hdr->code) { - case RADIUS_CODE_ACCESS_REQUEST: - process_radius_access_request(wt, dst, src, data, len); - break; - case RADIUS_CODE_ACCESS_ACCEPT: - process_radius_access_accept(wt, dst, src, data, len); - break; - } -} - - -static void process_udp(struct wlantest *wt, u32 dst, u32 src, - const u8 *data, size_t len) -{ - const struct udphdr *udp; - u16 sport, dport, ulen; - const u8 *payload; - size_t plen; - - if (len < sizeof(*udp)) - return; - udp = (const struct udphdr *) data; - /* TODO: check UDP checksum */ - sport = be_to_host16(udp->source); - dport = be_to_host16(udp->dest); - ulen = be_to_host16(udp->len); - - if (ulen > len) - return; - if (len < ulen) - len = ulen; - - payload = (const u8 *) (udp + 1); - plen = len - sizeof(*udp); - - if (sport == 1812 || dport == 1812) - process_radius(wt, dst, dport, src, sport, payload, plen); -} - - -static void process_ipv4(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct iphdr *ip; - const u8 *payload; - size_t plen; - u16 frag_off, tot_len; - - if (len < sizeof(*ip)) - return; - - ip = (const struct iphdr *) data; - if (ip->version != 4) - return; - if (ip->ihl < 5) - return; - - /* TODO: check header checksum in ip->check */ - - frag_off = be_to_host16(ip->frag_off); - if (frag_off & 0x1fff) { - wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet " - "supported"); - return; - } - - tot_len = be_to_host16(ip->tot_len); - if (tot_len > len) - return; - if (tot_len < len) - len = tot_len; - - payload = data + 4 * ip->ihl; - plen = len - 4 * ip->ihl; - if (payload + plen > data + len) - return; - - switch (ip->protocol) { - case IPPROTO_UDP: - process_udp(wt, ip->daddr, ip->saddr, payload, plen); - break; - } -} - - -void wlantest_process_wired(struct wlantest *wt, const u8 *data, size_t len) -{ - const struct ether_header *eth; - u16 ethertype; - - wpa_hexdump(MSG_EXCESSIVE, "Process wired frame", data, len); - - if (len < sizeof(*eth)) - return; - - eth = (const struct ether_header *) data; - ethertype = be_to_host16(eth->ether_type); - - switch (ethertype) { - case ETHERTYPE_IP: - process_ipv4(wt, data + sizeof(*eth), len - sizeof(*eth)); - break; - } -} diff --git a/wlantest/wlantest.c b/wlantest/wlantest.c deleted file mode 100644 index 094ed17..0000000 --- a/wlantest/wlantest.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * wlantest - IEEE 802.11 protocol monitoring and testing tool - * Copyright (c) 2010-2011, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "wlantest.h" - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; - - -static void wlantest_terminate(int sig, void *signal_ctx) -{ - eloop_terminate(); -} - - -static void usage(void) -{ - printf("wlantest [-cddhqq] [-i<ifname>] [-r<pcap file>] " - "[-p<passphrase>]\n" - " [-I<wired ifname>] [-R<wired pcap file>] " - "[-P<RADIUS shared secret>]\n" - " [-w<write pcap file>] [-f<MSK/PMK file>]\n"); -} - - -static void passphrase_deinit(struct wlantest_passphrase *p) -{ - dl_list_del(&p->list); - os_free(p); -} - - -static void secret_deinit(struct wlantest_radius_secret *r) -{ - dl_list_del(&r->list); - os_free(r); -} - - -static void wlantest_init(struct wlantest *wt) -{ - int i; - os_memset(wt, 0, sizeof(*wt)); - wt->monitor_sock = -1; - wt->ctrl_sock = -1; - for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) - wt->ctrl_socks[i] = -1; - dl_list_init(&wt->passphrase); - dl_list_init(&wt->bss); - dl_list_init(&wt->secret); - dl_list_init(&wt->radius); - dl_list_init(&wt->pmk); - dl_list_init(&wt->wep); -} - - -void radius_deinit(struct wlantest_radius *r) -{ - dl_list_del(&r->list); - os_free(r); -} - - -static void wlantest_deinit(struct wlantest *wt) -{ - struct wlantest_passphrase *p, *pn; - struct wlantest_radius_secret *s, *sn; - struct wlantest_radius *r, *rn; - struct wlantest_pmk *pmk, *np; - struct wlantest_wep *wep, *nw; - - if (wt->ctrl_sock >= 0) - ctrl_deinit(wt); - if (wt->monitor_sock >= 0) - monitor_deinit(wt); - bss_flush(wt); - dl_list_for_each_safe(p, pn, &wt->passphrase, - struct wlantest_passphrase, list) - passphrase_deinit(p); - dl_list_for_each_safe(s, sn, &wt->secret, - struct wlantest_radius_secret, list) - secret_deinit(s); - dl_list_for_each_safe(r, rn, &wt->radius, struct wlantest_radius, list) - radius_deinit(r); - dl_list_for_each_safe(pmk, np, &wt->pmk, struct wlantest_pmk, list) - pmk_deinit(pmk); - dl_list_for_each_safe(wep, nw, &wt->wep, struct wlantest_wep, list) - os_free(wep); - write_pcap_deinit(wt); -} - - -static void add_passphrase(struct wlantest *wt, const char *passphrase) -{ - struct wlantest_passphrase *p; - size_t len = os_strlen(passphrase); - - if (len < 8 || len > 63) - return; - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return; - os_memcpy(p->passphrase, passphrase, len); - dl_list_add(&wt->passphrase, &p->list); -} - - -static void add_secret(struct wlantest *wt, const char *secret) -{ - struct wlantest_radius_secret *s; - size_t len = os_strlen(secret); - - if (len >= MAX_RADIUS_SECRET_LEN) - return; - s = os_zalloc(sizeof(*s)); - if (s == NULL) - return; - os_memcpy(s->secret, secret, len); - dl_list_add(&wt->secret, &s->list); -} - - -static int add_pmk_file(struct wlantest *wt, const char *pmk_file) -{ - FILE *f; - u8 pmk[32]; - char buf[300], *pos; - struct wlantest_pmk *p; - - f = fopen(pmk_file, "r"); - if (f == NULL) { - wpa_printf(MSG_ERROR, "Could not open '%s'", pmk_file); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - pos = buf; - while (*pos && *pos != '\r' && *pos != '\n') - pos++; - *pos = '\0'; - if (pos - buf < 2 * 32) - continue; - if (hexstr2bin(buf, pmk, 32) < 0) - continue; - p = os_zalloc(sizeof(*p)); - if (p == NULL) - break; - os_memcpy(p->pmk, pmk, 32); - dl_list_add(&wt->pmk, &p->list); - wpa_hexdump(MSG_DEBUG, "Added PMK from file", pmk, 32); - } - - fclose(f); - return 0; -} - - -int add_wep(struct wlantest *wt, const char *key) -{ - struct wlantest_wep *w; - size_t len = os_strlen(key); - - if (len != 2 * 5 && len != 2 * 13) { - wpa_printf(MSG_INFO, "Invalid WEP key '%s'", key); - return -1; - } - w = os_zalloc(sizeof(*w)); - if (w == NULL) - return -1; - if (hexstr2bin(key, w->key, len / 2) < 0) { - os_free(w); - wpa_printf(MSG_INFO, "Invalid WEP key '%s'", key); - return -1; - } - w->key_len = len / 2; - dl_list_add(&wt->wep, &w->list); - return 0; -} - - -int main(int argc, char *argv[]) -{ - int c; - const char *read_file = NULL; - const char *read_wired_file = NULL; - const char *write_file = NULL; - const char *ifname = NULL; - const char *ifname_wired = NULL; - struct wlantest wt; - int ctrl_iface = 0; - - wpa_debug_level = MSG_INFO; - wpa_debug_show_keys = 1; - - if (os_program_init()) - return -1; - - wlantest_init(&wt); - - for (;;) { - c = getopt(argc, argv, "cdf:hi:I:p:P:qr:R:w:W:"); - if (c < 0) - break; - switch (c) { - case 'c': - ctrl_iface = 1; - break; - case 'd': - if (wpa_debug_level > 0) - wpa_debug_level--; - break; - case 'f': - if (add_pmk_file(&wt, optarg) < 0) - return -1; - break; - case 'h': - usage(); - return 0; - case 'i': - ifname = optarg; - break; - case 'I': - ifname_wired = optarg; - break; - case 'p': - add_passphrase(&wt, optarg); - break; - case 'P': - add_secret(&wt, optarg); - break; - case 'q': - wpa_debug_level++; - break; - case 'r': - read_file = optarg; - break; - case 'R': - read_wired_file = optarg; - break; - case 'w': - write_file = optarg; - break; - case 'W': - if (add_wep(&wt, optarg) < 0) - return -1; - break; - default: - usage(); - return -1; - } - } - - if (ifname == NULL && ifname_wired == NULL && - read_file == NULL && read_wired_file == NULL) { - usage(); - return 0; - } - - if (eloop_init()) - return -1; - - if (write_file && write_pcap_init(&wt, write_file) < 0) - return -1; - - if (read_wired_file && read_wired_cap_file(&wt, read_wired_file) < 0) - return -1; - - if (read_file && read_cap_file(&wt, read_file) < 0) - return -1; - - if (ifname && monitor_init(&wt, ifname) < 0) - return -1; - - if (ifname_wired && monitor_init_wired(&wt, ifname_wired) < 0) - return -1; - - if (ctrl_iface && ctrl_init(&wt) < 0) - return -1; - - eloop_register_signal_terminate(wlantest_terminate, &wt); - - eloop_run(); - - wpa_printf(MSG_INFO, "Processed: rx_mgmt=%u rx_ctrl=%u rx_data=%u " - "fcs_error=%u", - wt.rx_mgmt, wt.rx_ctrl, wt.rx_data, wt.fcs_error); - - wlantest_deinit(&wt); - - eloop_destroy(); - os_program_deinit(); - - return 0; -} diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h deleted file mode 100644 index de8bc65..0000000 --- a/wlantest/wlantest.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * wlantest - IEEE 802.11 protocol monitoring and testing tool - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef WLANTEST_H -#define WLANTEST_H - -#include "utils/list.h" -#include "common/wpa_common.h" -#include "wlantest_ctrl.h" - -struct ieee802_11_elems; -struct radius_msg; -struct ieee80211_hdr; -struct wlantest_bss; - -#define MAX_RADIUS_SECRET_LEN 128 - -struct wlantest_radius_secret { - struct dl_list list; - char secret[MAX_RADIUS_SECRET_LEN]; -}; - -struct wlantest_passphrase { - struct dl_list list; - char passphrase[64]; - u8 ssid[32]; - size_t ssid_len; - u8 bssid[ETH_ALEN]; -}; - -struct wlantest_pmk { - struct dl_list list; - u8 pmk[32]; -}; - -struct wlantest_wep { - struct dl_list list; - size_t key_len; - u8 key[13]; -}; - -struct wlantest_sta { - struct dl_list list; - struct wlantest_bss *bss; - u8 addr[ETH_ALEN]; - enum { - STATE1 /* not authenticated */, - STATE2 /* authenticated */, - STATE3 /* associated */ - } state; - u16 aid; - u8 rsnie[257]; /* WPA/RSN IE */ - int proto; - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int rsn_capab; - u8 anonce[32]; /* ANonce from the previous EAPOL-Key msg 1/4 or 3/4 */ - u8 snonce[32]; /* SNonce from the previous EAPOL-Key msg 2/4 */ - struct wpa_ptk ptk; /* Derived PTK */ - int ptk_set; - struct wpa_ptk tptk; /* Derived PTK during rekeying */ - int tptk_set; - u8 rsc_tods[16 + 1][6]; - u8 rsc_fromds[16 + 1][6]; - u8 ap_sa_query_tr[2]; - u8 sta_sa_query_tr[2]; - u32 counters[NUM_WLANTEST_STA_COUNTER]; - u16 assocreq_capab_info; - u16 assocreq_listen_int; - u8 *assocreq_ies; - size_t assocreq_ies_len; - - /* Last ICMP Echo request information */ - u32 icmp_echo_req_src; - 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]; - - int pwrmgt; - int pspoll; - - u8 gtk[32]; - size_t gtk_len; - int gtk_idx; -}; - -struct wlantest_tdls { - struct dl_list list; - struct wlantest_sta *init; - struct wlantest_sta *resp; - struct tpk { - u8 kck[16]; - u8 tk[16]; - } tpk; - int link_up; - u8 dialog_token; - u8 rsc_init[16 + 1][6]; - u8 rsc_resp[16 + 1][6]; - u32 counters[NUM_WLANTEST_TDLS_COUNTER]; -}; - -struct wlantest_bss { - struct dl_list list; - u8 bssid[ETH_ALEN]; - u16 capab_info; - u16 prev_capab_info; - u8 ssid[32]; - size_t ssid_len; - int proberesp_seen; - int parse_error_reported; - u8 wpaie[257]; - u8 rsnie[257]; - int proto; - int pairwise_cipher; - int group_cipher; - int mgmt_group_cipher; - int key_mgmt; - int rsn_capab; - struct dl_list sta; /* struct wlantest_sta */ - struct dl_list pmk; /* struct wlantest_pmk */ - u8 gtk[4][32]; - size_t gtk_len[4]; - int gtk_idx; - u8 rsc[4][6]; - u8 igtk[6][16]; - int igtk_set[6]; - int igtk_idx; - u8 ipn[6][6]; - u32 counters[NUM_WLANTEST_BSS_COUNTER]; - struct dl_list tdls; /* struct wlantest_tdls */ -}; - -struct wlantest_radius { - struct dl_list list; - u32 srv; - u32 cli; - struct radius_msg *last_req; -}; - - -#define MAX_CTRL_CONNECTIONS 10 - -struct wlantest { - int monitor_sock; - int monitor_wired; - - int ctrl_sock; - int ctrl_socks[MAX_CTRL_CONNECTIONS]; - - struct dl_list passphrase; /* struct wlantest_passphrase */ - struct dl_list bss; /* struct wlantest_bss */ - struct dl_list secret; /* struct wlantest_radius_secret */ - struct dl_list radius; /* struct wlantest_radius */ - struct dl_list pmk; /* struct wlantest_pmk */ - struct dl_list wep; /* struct wlantest_wep */ - - unsigned int rx_mgmt; - unsigned int rx_ctrl; - unsigned int rx_data; - unsigned int fcs_error; - - 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 add_wep(struct wlantest *wt, const char *key); -int read_cap_file(struct wlantest *wt, const char *fname); -int read_wired_cap_file(struct wlantest *wt, const char *fname); -int write_pcap_init(struct wlantest *wt, const char *fname); -void write_pcap_deinit(struct wlantest *wt); -void write_pcap_captured(struct wlantest *wt, const u8 *buf, size_t len); -void write_pcap_decrypted(struct wlantest *wt, const u8 *buf1, size_t len1, - const u8 *buf2, size_t len2); -void wlantest_process(struct wlantest *wt, const u8 *data, size_t len); -void wlantest_process_prism(struct wlantest *wt, const u8 *data, size_t len); -void wlantest_process_80211(struct wlantest *wt, const u8 *data, size_t len); -void wlantest_process_wired(struct wlantest *wt, const u8 *data, size_t len); -u32 crc32(const u8 *frame, size_t frame_len); -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); -void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, - const u8 *dst, const u8 *src, const u8 *data, size_t len, - const u8 *peer_addr); -void rx_data_80211_encap(struct wlantest *wt, const u8 *bssid, - const u8 *sta_addr, const u8 *dst, const u8 *src, - const u8 *data, size_t len); - -struct wlantest_bss * bss_find(struct wlantest *wt, const u8 *bssid); -struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid); -void bss_deinit(struct wlantest_bss *bss); -void bss_update(struct wlantest *wt, struct wlantest_bss *bss, - struct ieee802_11_elems *elems); -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); -void sta_deinit(struct wlantest_sta *sta); -void sta_update_assoc(struct wlantest_sta *sta, - struct ieee802_11_elems *elems); - -u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, - const u8 *data, size_t data_len, size_t *decrypted_len); -u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, - u8 *pn, int keyid, size_t *encrypted_len); -void ccmp_get_pn(u8 *pn, const u8 *data); - -u8 * tkip_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, - const u8 *data, size_t data_len, size_t *decrypted_len); -u8 * tkip_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, - u8 *pn, int keyid, size_t *encrypted_len); -void tkip_get_pn(u8 *pn, const u8 *data); - -u8 * wep_decrypt(struct wlantest *wt, const struct ieee80211_hdr *hdr, - const u8 *data, size_t data_len, size_t *decrypted_len); - -int ctrl_init(struct wlantest *wt); -void ctrl_deinit(struct wlantest *wt); - -int wlantest_inject(struct wlantest *wt, struct wlantest_bss *bss, - struct wlantest_sta *sta, u8 *frame, size_t len, - enum wlantest_inject_protection prot); - -#endif /* WLANTEST_H */ diff --git a/wlantest/wlantest_cli.c b/wlantest/wlantest_cli.c deleted file mode 100644 index ce95081..0000000 --- a/wlantest/wlantest_cli.c +++ /dev/null @@ -1,1714 +0,0 @@ -/* - * wlantest controller - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <sys/un.h> - -#include "utils/common.h" -#include "utils/eloop.h" -#include "utils/edit.h" -#include "wlantest_ctrl.h" - - -static int get_cmd_arg_num(const char *str, int pos) -{ - int arg = 0, i; - - for (i = 0; i <= pos; i++) { - if (str[i] != ' ') { - arg++; - while (i <= pos && str[i] != ' ') - i++; - } - } - - if (arg > 0) - arg--; - return arg; -} - - -static int get_prev_arg_pos(const char *str, int pos) -{ - while (pos > 0 && str[pos - 1] != ' ') - pos--; - while (pos > 0 && str[pos - 1] == ' ') - pos--; - while (pos > 0 && str[pos - 1] != ' ') - pos--; - return pos; -} - - -static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr, - size_t *len) -{ - u8 *pos = buf; - - while (pos + 8 <= buf + buflen) { - enum wlantest_ctrl_attr a; - size_t alen; - a = WPA_GET_BE32(pos); - pos += 4; - alen = WPA_GET_BE32(pos); - pos += 4; - if (pos + alen > buf + buflen) { - printf("Invalid control message attribute\n"); - return NULL; - } - if (a == attr) { - *len = alen; - return pos; - } - pos += alen; - } - - return NULL; -} - - -static u8 * attr_hdr_add(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr, - size_t len) -{ - if (pos == NULL || end - pos < 8 + len) - return NULL; - WPA_PUT_BE32(pos, attr); - pos += 4; - WPA_PUT_BE32(pos, len); - pos += 4; - return pos; -} - - -static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr, - const char *str) -{ - size_t len = os_strlen(str); - - if (pos == NULL || end - pos < 8 + len) - return NULL; - WPA_PUT_BE32(pos, attr); - pos += 4; - WPA_PUT_BE32(pos, len); - pos += 4; - os_memcpy(pos, str, len); - pos += len; - return pos; -} - - -static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr, - u32 val) -{ - if (pos == NULL || end - pos < 12) - return NULL; - WPA_PUT_BE32(pos, attr); - pos += 4; - WPA_PUT_BE32(pos, 4); - pos += 4; - WPA_PUT_BE32(pos, val); - pos += 4; - return pos; -} - - -static int cmd_send_and_recv(int s, const u8 *cmd, size_t cmd_len, - u8 *resp, size_t max_resp_len) -{ - int res; - enum wlantest_ctrl_cmd cmd_resp; - - if (send(s, cmd, cmd_len, 0) < 0) - return -1; - res = recv(s, resp, max_resp_len, 0); - if (res < 4) - return -1; - - cmd_resp = WPA_GET_BE32(resp); - if (cmd_resp == WLANTEST_CTRL_SUCCESS) - return res; - - if (cmd_resp == WLANTEST_CTRL_UNKNOWN_CMD) - printf("Unknown command\n"); - else if (cmd_resp == WLANTEST_CTRL_INVALID_CMD) - printf("Invalid command\n"); - - return -1; -} - - -static int cmd_simple(int s, enum wlantest_ctrl_cmd cmd) -{ - u8 buf[4]; - int res; - WPA_PUT_BE32(buf, cmd); - res = cmd_send_and_recv(s, buf, sizeof(buf), buf, sizeof(buf)); - return res < 0 ? -1 : 0; -} - - -static char ** get_bssid_list(int s) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[4]; - u8 *bssid; - size_t len; - int rlen, i; - char **res; - - WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS); - rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp)); - if (rlen < 0) - return NULL; - - bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len); - if (bssid == NULL) - return NULL; - - res = os_zalloc((len / ETH_ALEN + 1) * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < len / ETH_ALEN; i++) { - res[i] = os_zalloc(18); - if (res[i] == NULL) - break; - os_snprintf(res[i], 18, MACSTR, MAC2STR(bssid + ETH_ALEN * i)); - } - - return res; -} - - -static char ** get_sta_list(int s, const u8 *bssid, int add_bcast) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *pos, *end; - u8 *addr; - size_t len; - int rlen, i; - char **res; - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA); - pos += 4; - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - os_memcpy(pos, bssid, ETH_ALEN); - pos += ETH_ALEN; - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return NULL; - - addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len); - if (addr == NULL) - return NULL; - - res = os_zalloc((len / ETH_ALEN + 1 + add_bcast) * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < len / ETH_ALEN; i++) { - res[i] = os_zalloc(18); - if (res[i] == NULL) - break; - os_snprintf(res[i], 18, MACSTR, MAC2STR(addr + ETH_ALEN * i)); - } - if (add_bcast) - res[i] = os_strdup("ff:ff:ff:ff:ff:ff"); - - return res; -} - - -static int cmd_ping(int s, int argc, char *argv[]) -{ - int res = cmd_simple(s, WLANTEST_CTRL_PING); - if (res == 0) - printf("PONG\n"); - return res == 0; -} - - -static int cmd_terminate(int s, int argc, char *argv[]) -{ - return cmd_simple(s, WLANTEST_CTRL_TERMINATE); -} - - -static int cmd_list_bss(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[4]; - u8 *bssid; - size_t len; - int rlen, i; - - WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS); - rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp)); - if (rlen < 0) - return -1; - - bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len); - if (bssid == NULL) - return -1; - - for (i = 0; i < len / ETH_ALEN; i++) - printf(MACSTR " ", MAC2STR(bssid + ETH_ALEN * i)); - printf("\n"); - - return 0; -} - - -static int cmd_list_sta(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *pos; - u8 *addr; - size_t len; - int rlen, i; - - if (argc < 1) { - printf("list_sta needs one argument: BSSID\n"); - return -1; - } - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA); - pos += 4; - WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[0], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[0]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - - addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len); - if (addr == NULL) - return -1; - - for (i = 0; i < len / ETH_ALEN; i++) - printf(MACSTR " ", MAC2STR(addr + ETH_ALEN * i)); - printf("\n"); - - return 0; -} - - -static char ** complete_list_sta(int s, const char *str, int pos) -{ - if (get_cmd_arg_num(str, pos) == 1) - return get_bssid_list(s); - return NULL; -} - - -static int cmd_flush(int s, int argc, char *argv[]) -{ - return cmd_simple(s, WLANTEST_CTRL_FLUSH); -} - - -static int cmd_clear_sta_counters(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *pos; - int rlen; - - if (argc < 2) { - printf("clear_sta_counters needs two arguments: BSSID and " - "STA address\n"); - return -1; - } - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_STA_COUNTERS); - pos += 4; - WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[0], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[0]); - return -1; - } - pos += ETH_ALEN; - - WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid STA address '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - printf("OK\n"); - return 0; -} - - -static char ** complete_clear_sta_counters(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - u8 addr[ETH_ALEN]; - - switch (arg) { - case 1: - res = get_bssid_list(s); - break; - case 2: - if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0) - break; - res = get_sta_list(s, addr, 0); - break; - } - - return res; -} - - -static int cmd_clear_bss_counters(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *pos; - int rlen; - - if (argc < 1) { - printf("clear_bss_counters needs one argument: BSSID\n"); - return -1; - } - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_BSS_COUNTERS); - pos += 4; - WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[0], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[0]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - printf("OK\n"); - return 0; -} - - -static char ** complete_clear_bss_counters(int s, const char *str, int pos) -{ - if (get_cmd_arg_num(str, pos) == 1) - return get_bssid_list(s); - return NULL; -} - - -static int cmd_clear_tdls_counters(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *pos; - int rlen; - - if (argc < 3) { - printf("clear_tdls_counters needs three arguments: BSSID, " - "STA1 address, STA2 address\n"); - return -1; - } - - pos = buf; - WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS); - pos += 4; - WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[0], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[0]); - return -1; - } - pos += ETH_ALEN; - - WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid STA1 address '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - WPA_PUT_BE32(pos, WLANTEST_ATTR_STA2_ADDR); - pos += 4; - WPA_PUT_BE32(pos, ETH_ALEN); - pos += 4; - if (hwaddr_aton(argv[2], pos) < 0) { - printf("Invalid STA2 address '%s'\n", argv[2]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - printf("OK\n"); - return 0; -} - - -static char ** complete_clear_tdls_counters(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - u8 addr[ETH_ALEN]; - - switch (arg) { - case 1: - res = get_bssid_list(s); - break; - case 2: - case 3: - if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0) - break; - res = get_sta_list(s, addr, 0); - break; - } - - return res; -} - - -struct sta_counters { - const char *name; - enum wlantest_sta_counter num; -}; - -static const struct sta_counters sta_counters[] = { - { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX }, - { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX }, - { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX }, - { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX }, - { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED }, - { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX }, - { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX }, - { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX }, - { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX }, - { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX }, - { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX }, - { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX }, - { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX }, - { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX }, - { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX }, - { "invalid_saqueryreq_tx", - WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX }, - { "invalid_saqueryreq_rx", - WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX }, - { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX }, - { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX }, - { "invalid_saqueryresp_tx", - WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX }, - { "invalid_saqueryresp_rx", - WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX }, - { "ping_ok", WLANTEST_STA_COUNTER_PING_OK }, - { "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 }, - { "deauth_rx_asleep", WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP }, - { "deauth_rx_awake", WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE }, - { "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP }, - { "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE }, - { "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX }, - { "deauth_rx_rc6", WLANTEST_STA_COUNTER_DEAUTH_RX_RC6 }, - { "deauth_rx_rc7", WLANTEST_STA_COUNTER_DEAUTH_RX_RC7 }, - { "disassoc_rx_rc6", WLANTEST_STA_COUNTER_DISASSOC_RX_RC6 }, - { "disassoc_rx_rc7", WLANTEST_STA_COUNTER_DISASSOC_RX_RC7 }, - { NULL, 0 } -}; - -static int cmd_get_sta_counter(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *end, *pos; - int rlen, i; - size_t len; - - if (argc != 3) { - printf("get_sta_counter needs at three arguments: " - "counter name, BSSID, and STA address\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER); - pos += 4; - - for (i = 0; sta_counters[i].name; i++) { - if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0) - break; - } - if (sta_counters[i].name == NULL) { - printf("Unknown STA counter '%s'\n", argv[0]); - printf("Counters:"); - for (i = 0; sta_counters[i].name; i++) - printf(" %s", sta_counters[i].name); - printf("\n"); - return -1; - } - - pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER, - sta_counters[i].num); - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN); - if (hwaddr_aton(argv[2], pos) < 0) { - printf("Invalid STA address '%s'\n", argv[2]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - - pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len); - if (pos == NULL || len != 4) - return -1; - printf("%u\n", WPA_GET_BE32(pos)); - return 0; -} - - -static char ** complete_get_sta_counter(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - int i, count; - u8 addr[ETH_ALEN]; - - switch (arg) { - case 1: - /* counter list */ - count = sizeof(sta_counters) / sizeof(sta_counters[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; sta_counters[i].name; i++) { - res[i] = os_strdup(sta_counters[i].name); - if (res[i] == NULL) - break; - } - break; - case 2: - res = get_bssid_list(s); - break; - case 3: - if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0) - break; - res = get_sta_list(s, addr, 0); - break; - } - - return res; -} - - -struct bss_counters { - const char *name; - enum wlantest_bss_counter num; -}; - -static const struct bss_counters bss_counters[] = { - { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE }, - { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE }, - { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE }, - { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH }, - { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC }, - { NULL, 0 } -}; - -static int cmd_get_bss_counter(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *end, *pos; - int rlen, i; - size_t len; - - if (argc != 2) { - printf("get_bss_counter needs at two arguments: " - "counter name and BSSID\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER); - pos += 4; - - for (i = 0; bss_counters[i].name; i++) { - if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0) - break; - } - if (bss_counters[i].name == NULL) { - printf("Unknown BSS counter '%s'\n", argv[0]); - printf("Counters:"); - for (i = 0; bss_counters[i].name; i++) - printf(" %s", bss_counters[i].name); - printf("\n"); - return -1; - } - - pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER, - bss_counters[i].num); - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - - pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len); - if (pos == NULL || len != 4) - return -1; - printf("%u\n", WPA_GET_BE32(pos)); - return 0; -} - - -static char ** complete_get_bss_counter(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - int i, count; - - switch (arg) { - case 1: - /* counter list */ - count = sizeof(bss_counters) / sizeof(bss_counters[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; bss_counters[i].name; i++) { - res[i] = os_strdup(bss_counters[i].name); - if (res[i] == NULL) - break; - } - break; - case 2: - res = get_bssid_list(s); - break; - } - - return res; -} - - -struct tdls_counters { - const char *name; - enum wlantest_tdls_counter num; -}; - -static const struct tdls_counters tdls_counters[] = { - { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK }, - { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK }, - { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH }, - { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH }, - { "setup_req", WLANTEST_TDLS_COUNTER_SETUP_REQ }, - { "setup_resp_ok", WLANTEST_TDLS_COUNTER_SETUP_RESP_OK }, - { "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL }, - { "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK }, - { "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL }, - { "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN }, - { NULL, 0 } -}; - -static int cmd_get_tdls_counter(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *end, *pos; - int rlen, i; - size_t len; - - if (argc != 4) { - printf("get_tdls_counter needs four arguments: " - "counter name, BSSID, STA1 address, STA2 address\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER); - pos += 4; - - for (i = 0; tdls_counters[i].name; i++) { - if (os_strcasecmp(tdls_counters[i].name, argv[0]) == 0) - break; - } - if (tdls_counters[i].name == NULL) { - printf("Unknown TDLS counter '%s'\n", argv[0]); - printf("Counters:"); - for (i = 0; tdls_counters[i].name; i++) - printf(" %s", tdls_counters[i].name); - printf("\n"); - return -1; - } - - pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER, - tdls_counters[i].num); - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN); - if (hwaddr_aton(argv[2], pos) < 0) { - printf("Invalid STA1 address '%s'\n", argv[2]); - return -1; - } - pos += ETH_ALEN; - - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR, ETH_ALEN); - if (hwaddr_aton(argv[3], pos) < 0) { - printf("Invalid STA2 address '%s'\n", argv[3]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - - pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len); - if (pos == NULL || len != 4) - return -1; - printf("%u\n", WPA_GET_BE32(pos)); - return 0; -} - - -static char ** complete_get_tdls_counter(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - int i, count; - u8 addr[ETH_ALEN]; - - switch (arg) { - case 1: - /* counter list */ - count = sizeof(tdls_counters) / sizeof(tdls_counters[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; tdls_counters[i].name; i++) { - res[i] = os_strdup(tdls_counters[i].name); - if (res[i] == NULL) - break; - } - break; - case 2: - res = get_bssid_list(s); - break; - case 3: - case 4: - if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0) - break; - res = get_sta_list(s, addr, 0); - break; - } - - return res; -} - - -struct inject_frames { - const char *name; - enum wlantest_inject_frame frame; -}; - -static const struct inject_frames inject_frames[] = { - { "auth", WLANTEST_FRAME_AUTH }, - { "assocreq", WLANTEST_FRAME_ASSOCREQ }, - { "reassocreq", WLANTEST_FRAME_REASSOCREQ }, - { "deauth", WLANTEST_FRAME_DEAUTH }, - { "disassoc", WLANTEST_FRAME_DISASSOC }, - { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ }, - { NULL, 0 } -}; - -static int cmd_inject(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *end, *pos; - int rlen, i; - enum wlantest_inject_protection prot; - - /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */ - - if (argc < 5) { - printf("inject needs five arguments: frame, protection, " - "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT); - pos += 4; - - for (i = 0; inject_frames[i].name; i++) { - if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0) - break; - } - if (inject_frames[i].name == NULL) { - printf("Unknown inject frame '%s'\n", argv[0]); - printf("Frames:"); - for (i = 0; inject_frames[i].name; i++) - printf(" %s", inject_frames[i].name); - printf("\n"); - return -1; - } - - pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME, - inject_frames[i].frame); - - if (os_strcasecmp(argv[1], "normal") == 0) - prot = WLANTEST_INJECT_NORMAL; - else if (os_strcasecmp(argv[1], "protected") == 0) - prot = WLANTEST_INJECT_PROTECTED; - else if (os_strcasecmp(argv[1], "unprotected") == 0) - prot = WLANTEST_INJECT_UNPROTECTED; - else if (os_strcasecmp(argv[1], "incorrect") == 0) - prot = WLANTEST_INJECT_INCORRECT_KEY; - else { - printf("Unknown protection type '%s'\n", argv[1]); - printf("Protection types: normal protected unprotected " - "incorrect\n"); - return -1; - } - pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot); - - if (os_strcasecmp(argv[2], "ap") == 0) { - pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP, - 1); - } else if (os_strcasecmp(argv[2], "sta") == 0) { - pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP, - 0); - } else { - printf("Unknown sender '%s'\n", argv[2]); - printf("Sender types: ap sta\n"); - return -1; - } - - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[3], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[3]); - return -1; - } - pos += ETH_ALEN; - - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN); - if (hwaddr_aton(argv[4], pos) < 0) { - printf("Invalid STA '%s'\n", argv[4]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - printf("OK\n"); - return 0; -} - - -static char ** complete_inject(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - int i, count; - u8 addr[ETH_ALEN]; - - switch (arg) { - case 1: - /* frame list */ - count = sizeof(inject_frames) / sizeof(inject_frames[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - break; - for (i = 0; inject_frames[i].name; i++) { - res[i] = os_strdup(inject_frames[i].name); - if (res[i] == NULL) - break; - } - break; - case 2: - res = os_zalloc(5 * sizeof(char *)); - if (res == NULL) - break; - res[0] = os_strdup("normal"); - if (res[0] == NULL) - break; - res[1] = os_strdup("protected"); - if (res[1] == NULL) - break; - res[2] = os_strdup("unprotected"); - if (res[2] == NULL) - break; - res[3] = os_strdup("incorrect"); - if (res[3] == NULL) - break; - break; - case 3: - res = os_zalloc(3 * sizeof(char *)); - if (res == NULL) - break; - res[0] = os_strdup("ap"); - if (res[0] == NULL) - break; - res[1] = os_strdup("sta"); - if (res[1] == NULL) - break; - break; - case 4: - res = get_bssid_list(s); - break; - case 5: - if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0) - break; - res = get_sta_list(s, addr, 1); - break; - } - - return res; -} - - -static u8 * add_hex(u8 *pos, u8 *end, const char *str) -{ - const char *s; - int val; - - s = str; - while (*s) { - while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' || - *s == ':') - s++; - if (*s == '\0') - break; - if (*s == '#') { - while (*s != '\0' && *s != '\r' && *s != '\n') - s++; - continue; - } - - val = hex2byte(s); - if (val < 0) { - printf("Invalid hex encoding '%s'\n", s); - return NULL; - } - if (pos == end) { - printf("Too long frame\n"); - return NULL; - } - *pos++ = val; - s += 2; - } - - return pos; -} - - -static int cmd_send(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[WLANTEST_CTRL_MAX_CMD_LEN], *end, *pos, *len_pos; - int rlen; - enum wlantest_inject_protection prot; - int arg; - - /* <prot> <raw frame as hex dump> */ - - if (argc < 2) { - printf("send needs two arguments: protected/unprotected, " - "raw frame as hex dump\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_SEND); - pos += 4; - - if (os_strcasecmp(argv[0], "normal") == 0) - prot = WLANTEST_INJECT_NORMAL; - else if (os_strcasecmp(argv[0], "protected") == 0) - prot = WLANTEST_INJECT_PROTECTED; - else if (os_strcasecmp(argv[0], "unprotected") == 0) - prot = WLANTEST_INJECT_UNPROTECTED; - else if (os_strcasecmp(argv[0], "incorrect") == 0) - prot = WLANTEST_INJECT_INCORRECT_KEY; - else { - printf("Unknown protection type '%s'\n", argv[1]); - printf("Protection types: normal protected unprotected " - "incorrect\n"); - return -1; - } - pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot); - - WPA_PUT_BE32(pos, WLANTEST_ATTR_FRAME); - pos += 4; - len_pos = pos; - pos += 4; - - for (arg = 1; pos && arg < argc; arg++) - pos = add_hex(pos, end, argv[arg]); - if (pos == NULL) - return -1; - - WPA_PUT_BE32(len_pos, pos - len_pos - 4); - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - printf("OK\n"); - return 0; -} - - -static char ** complete_send(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = os_zalloc(5 * sizeof(char *)); - if (res == NULL) - break; - res[0] = os_strdup("normal"); - if (res[0] == NULL) - break; - res[1] = os_strdup("protected"); - if (res[1] == NULL) - break; - res[2] = os_strdup("unprotected"); - if (res[2] == NULL) - break; - res[3] = os_strdup("incorrect"); - if (res[3] == NULL) - break; - break; - } - - return res; -} - - -static int cmd_version(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[4]; - char *version; - size_t len; - int rlen, i; - - WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION); - rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp)); - if (rlen < 0) - return -1; - - version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION, - &len); - if (version == NULL) - return -1; - - for (i = 0; i < len; i++) - putchar(version[i]); - printf("\n"); - - return 0; -} - - -static int cmd_add_passphrase(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *pos, *end; - size_t len; - int rlen; - - if (argc < 1) { - printf("add_passphrase needs one argument: passphrase\n"); - return -1; - } - - len = os_strlen(argv[0]); - if (len < 8 || len > 63) { - printf("Invalid passphrase '%s'\n", argv[0]); - return -1; - } - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE); - pos += 4; - pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE, - argv[0]); - if (argc > 1) { - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[3]); - return -1; - } - pos += ETH_ALEN; - } - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - return 0; -} - - -struct sta_infos { - const char *name; - enum wlantest_sta_info num; -}; - -static const struct sta_infos sta_infos[] = { - { "proto", WLANTEST_STA_INFO_PROTO }, - { "pairwise", WLANTEST_STA_INFO_PAIRWISE }, - { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT }, - { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB }, - { "state", WLANTEST_STA_INFO_STATE }, - { "gtk", WLANTEST_STA_INFO_GTK }, - { NULL, 0 } -}; - -static int cmd_info_sta(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *end, *pos; - int rlen, i; - size_t len; - char info[100]; - - if (argc != 3) { - printf("sta_info needs at three arguments: " - "counter name, BSSID, and STA address\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA); - pos += 4; - - for (i = 0; sta_infos[i].name; i++) { - if (os_strcasecmp(sta_infos[i].name, argv[0]) == 0) - break; - } - if (sta_infos[i].name == NULL) { - printf("Unknown STA info '%s'\n", argv[0]); - printf("Info fields:"); - for (i = 0; sta_infos[i].name; i++) - printf(" %s", sta_infos[i].name); - printf("\n"); - return -1; - } - - pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO, - sta_infos[i].num); - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN); - if (hwaddr_aton(argv[2], pos) < 0) { - printf("Invalid STA address '%s'\n", argv[2]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - - pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len); - if (pos == NULL) - return -1; - if (len >= sizeof(info)) - len = sizeof(info) - 1; - os_memcpy(info, pos, len); - info[len] = '\0'; - printf("%s\n", info); - return 0; -} - - -static char ** complete_info_sta(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - int i, count; - u8 addr[ETH_ALEN]; - - switch (arg) { - case 1: - /* counter list */ - count = sizeof(sta_infos) / sizeof(sta_infos[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; sta_infos[i].name; i++) { - res[i] = os_strdup(sta_infos[i].name); - if (res[i] == NULL) - break; - } - break; - case 2: - res = get_bssid_list(s); - break; - case 3: - if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0) - break; - res = get_sta_list(s, addr, 0); - break; - } - - return res; -} - - -struct bss_infos { - const char *name; - enum wlantest_bss_info num; -}; - -static const struct bss_infos bss_infos[] = { - { "proto", WLANTEST_BSS_INFO_PROTO }, - { "pairwise", WLANTEST_BSS_INFO_PAIRWISE }, - { "group", WLANTEST_BSS_INFO_GROUP }, - { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT }, - { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT }, - { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB }, - { NULL, 0 } -}; - -static int cmd_info_bss(int s, int argc, char *argv[]) -{ - u8 resp[WLANTEST_CTRL_MAX_RESP_LEN]; - u8 buf[100], *end, *pos; - int rlen, i; - size_t len; - char info[100]; - - if (argc != 2) { - printf("bss_info needs at two arguments: " - "field name and BSSID\n"); - return -1; - } - - pos = buf; - end = buf + sizeof(buf); - WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS); - pos += 4; - - for (i = 0; bss_infos[i].name; i++) { - if (os_strcasecmp(bss_infos[i].name, argv[0]) == 0) - break; - } - if (bss_infos[i].name == NULL) { - printf("Unknown BSS info '%s'\n", argv[0]); - printf("Info fields:"); - for (i = 0; bss_infos[i].name; i++) - printf(" %s", bss_infos[i].name); - printf("\n"); - return -1; - } - - pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO, - bss_infos[i].num); - pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN); - if (hwaddr_aton(argv[1], pos) < 0) { - printf("Invalid BSSID '%s'\n", argv[1]); - return -1; - } - pos += ETH_ALEN; - - rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp)); - if (rlen < 0) - return -1; - - pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len); - if (pos == NULL) - return -1; - if (len >= sizeof(info)) - len = sizeof(info) - 1; - os_memcpy(info, pos, len); - info[len] = '\0'; - printf("%s\n", info); - return 0; -} - - -static char ** complete_info_bss(int s, const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - int i, count; - - switch (arg) { - case 1: - /* counter list */ - count = sizeof(bss_infos) / sizeof(bss_infos[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; bss_infos[i].name; i++) { - res[i] = os_strdup(bss_infos[i].name); - if (res[i] == NULL) - break; - } - break; - case 2: - res = get_bssid_list(s); - break; - } - - return res; -} - - -struct wlantest_cli_cmd { - const char *cmd; - int (*handler)(int s, int argc, char *argv[]); - const char *usage; - char ** (*complete)(int s, const char *str, int pos); -}; - -static const struct wlantest_cli_cmd wlantest_cli_commands[] = { - { "ping", cmd_ping, "= test connection to wlantest", NULL }, - { "terminate", cmd_terminate, "= terminate wlantest", NULL }, - { "list_bss", cmd_list_bss, "= get BSS list", NULL }, - { "list_sta", cmd_list_sta, "<BSSID> = get STA list", - complete_list_sta }, - { "flush", cmd_flush, "= drop all collected BSS data", NULL }, - { "clear_sta_counters", cmd_clear_sta_counters, - "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters }, - { "clear_bss_counters", cmd_clear_bss_counters, - "<BSSID> = clear BSS counters", complete_clear_bss_counters }, - { "get_sta_counter", cmd_get_sta_counter, - "<counter> <BSSID> <STA> = get STA counter value", - complete_get_sta_counter }, - { "get_bss_counter", cmd_get_bss_counter, - "<counter> <BSSID> = get BSS counter value", - complete_get_bss_counter }, - { "inject", cmd_inject, - "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>", - complete_inject }, - { "send", cmd_send, - "<prot> <raw frame as hex dump>", - complete_send }, - { "version", cmd_version, "= get wlantest version", NULL }, - { "add_passphrase", cmd_add_passphrase, - "<passphrase> = add a known passphrase", NULL }, - { "info_sta", cmd_info_sta, - "<field> <BSSID> <STA> = get STA information", - complete_info_sta }, - { "info_bss", cmd_info_bss, - "<field> <BSSID> = get BSS information", - complete_info_bss }, - { "clear_tdls_counters", cmd_clear_tdls_counters, - "<BSSID> <STA1> <STA2> = clear TDLS counters", - complete_clear_tdls_counters }, - { "get_tdls_counter", cmd_get_tdls_counter, - "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value", - complete_get_tdls_counter }, - { "get_bss_counter", cmd_get_bss_counter, - "<counter> <BSSID> = get BSS counter value", - complete_get_bss_counter }, - { NULL, NULL, NULL, NULL } -}; - - -static int ctrl_command(int s, int argc, char *argv[]) -{ - const struct wlantest_cli_cmd *cmd, *match = NULL; - int count = 0; - int ret = 0; - - for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) { - if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0) - { - match = cmd; - if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { - /* exact match */ - count = 1; - break; - } - count++; - } - } - - if (count > 1) { - printf("Ambiguous command '%s'; possible commands:", argv[0]); - for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) { - if (os_strncasecmp(cmd->cmd, argv[0], - os_strlen(argv[0])) == 0) { - printf(" %s", cmd->cmd); - } - } - printf("\n"); - ret = 1; - } else if (count == 0) { - printf("Unknown command '%s'\n", argv[0]); - ret = 1; - } else { - ret = match->handler(s, argc - 1, &argv[1]); - } - - return ret; -} - - -struct wlantest_cli { - int s; -}; - - -#define max_args 10 - -static int tokenize_cmd(char *cmd, char *argv[]) -{ - char *pos; - int argc = 0; - - pos = cmd; - for (;;) { - while (*pos == ' ') - pos++; - if (*pos == '\0') - break; - argv[argc] = pos; - argc++; - if (argc == max_args) - break; - if (*pos == '"') { - char *pos2 = os_strrchr(pos, '"'); - if (pos2) - pos = pos2 + 1; - } - while (*pos != '\0' && *pos != ' ') - pos++; - if (*pos == ' ') - *pos++ = '\0'; - } - - return argc; -} - - -static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd) -{ - struct wlantest_cli *cli = ctx; - char *argv[max_args]; - int argc; - argc = tokenize_cmd(cmd, argv); - if (argc) { - int ret = ctrl_command(cli->s, argc, argv); - if (ret < 0) - printf("FAIL\n"); - } -} - - -static void wlantest_cli_eloop_terminate(int sig, void *signal_ctx) -{ - eloop_terminate(); -} - - -static void wlantest_cli_edit_eof_cb(void *ctx) -{ - eloop_terminate(); -} - - -static char ** wlantest_cli_cmd_list(void) -{ - char **res; - int i, count; - - count = sizeof(wlantest_cli_commands) / - sizeof(wlantest_cli_commands[0]); - res = os_zalloc(count * sizeof(char *)); - if (res == NULL) - return NULL; - - for (i = 0; wlantest_cli_commands[i].cmd; i++) { - res[i] = os_strdup(wlantest_cli_commands[i].cmd); - if (res[i] == NULL) - break; - } - - return res; -} - - -static char ** wlantest_cli_cmd_completion(struct wlantest_cli *cli, - const char *cmd, const char *str, - int pos) -{ - int i; - - for (i = 0; wlantest_cli_commands[i].cmd; i++) { - const struct wlantest_cli_cmd *c = &wlantest_cli_commands[i]; - if (os_strcasecmp(c->cmd, cmd) == 0) { - edit_clear_line(); - printf("\r%s\n", c->usage); - edit_redraw(); - if (c->complete) - return c->complete(cli->s, str, pos); - break; - } - } - - return NULL; -} - - -static char ** wlantest_cli_edit_completion_cb(void *ctx, const char *str, - int pos) -{ - struct wlantest_cli *cli = ctx; - char **res; - const char *end; - char *cmd; - - end = os_strchr(str, ' '); - if (end == NULL || str + pos < end) - return wlantest_cli_cmd_list(); - - cmd = os_malloc(pos + 1); - if (cmd == NULL) - return NULL; - os_memcpy(cmd, str, pos); - cmd[end - str] = '\0'; - res = wlantest_cli_cmd_completion(cli, cmd, str, pos); - os_free(cmd); - return res; -} - - -static void wlantest_cli_interactive(int s) -{ - struct wlantest_cli cli; - char *home, *hfile = NULL; - - if (eloop_init()) - return; - - home = getenv("HOME"); - if (home) { - const char *fname = ".wlantest_cli_history"; - int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; - hfile = os_malloc(hfile_len); - if (hfile) - os_snprintf(hfile, hfile_len, "%s/%s", home, fname); - } - - cli.s = s; - eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli); - edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb, - wlantest_cli_edit_completion_cb, &cli, hfile); - - eloop_run(); - - edit_deinit(hfile, NULL); - os_free(hfile); - eloop_destroy(); -} - - -int main(int argc, char *argv[]) -{ - int s; - struct sockaddr_un addr; - int ret = 0; - - if (os_program_init()) - return -1; - - s = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME, - sizeof(addr.sun_path) - 1); - if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("connect"); - close(s); - return -1; - } - - if (argc > 1) { - ret = ctrl_command(s, argc - 1, &argv[1]); - if (ret < 0) - printf("FAIL\n"); - } else { - wlantest_cli_interactive(s); - } - - close(s); - - os_program_deinit(); - - return ret; -} diff --git a/wlantest/wlantest_ctrl.h b/wlantest/wlantest_ctrl.h deleted file mode 100644 index 618cf8c..0000000 --- a/wlantest/wlantest_ctrl.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * wlantest control interface - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef WLANTEST_CTRL_H -#define WLANTEST_CTRL_H - -#define WLANTEST_SOCK_NAME "w1.fi.wlantest" -#define WLANTEST_CTRL_MAX_CMD_LEN 1000 -#define WLANTEST_CTRL_MAX_RESP_LEN 1000 - -enum wlantest_ctrl_cmd { - WLANTEST_CTRL_SUCCESS, - WLANTEST_CTRL_FAILURE, - WLANTEST_CTRL_INVALID_CMD, - WLANTEST_CTRL_UNKNOWN_CMD, - WLANTEST_CTRL_PING, - WLANTEST_CTRL_TERMINATE, - WLANTEST_CTRL_LIST_BSS, - WLANTEST_CTRL_LIST_STA, - WLANTEST_CTRL_FLUSH, - WLANTEST_CTRL_CLEAR_STA_COUNTERS, - WLANTEST_CTRL_CLEAR_BSS_COUNTERS, - WLANTEST_CTRL_GET_STA_COUNTER, - WLANTEST_CTRL_GET_BSS_COUNTER, - WLANTEST_CTRL_INJECT, - WLANTEST_CTRL_VERSION, - WLANTEST_CTRL_ADD_PASSPHRASE, - WLANTEST_CTRL_INFO_STA, - WLANTEST_CTRL_INFO_BSS, - WLANTEST_CTRL_SEND, - WLANTEST_CTRL_CLEAR_TDLS_COUNTERS, - WLANTEST_CTRL_GET_TDLS_COUNTER, -}; - -enum wlantest_ctrl_attr { - WLANTEST_ATTR_BSSID, - WLANTEST_ATTR_STA_ADDR, - WLANTEST_ATTR_STA_COUNTER, - WLANTEST_ATTR_BSS_COUNTER, - WLANTEST_ATTR_COUNTER, - WLANTEST_ATTR_INJECT_FRAME, - WLANTEST_ATTR_INJECT_SENDER_AP, - WLANTEST_ATTR_INJECT_PROTECTION, - WLANTEST_ATTR_VERSION, - WLANTEST_ATTR_PASSPHRASE, - WLANTEST_ATTR_STA_INFO, - WLANTEST_ATTR_BSS_INFO, - WLANTEST_ATTR_INFO, - WLANTEST_ATTR_FRAME, - WLANTEST_ATTR_TDLS_COUNTER, - WLANTEST_ATTR_STA2_ADDR, - WLANTEST_ATTR_WEPKEY, -}; - -enum wlantest_bss_counter { - WLANTEST_BSS_COUNTER_VALID_BIP_MMIE, - WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE, - WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE, - WLANTEST_BSS_COUNTER_BIP_DEAUTH, - WLANTEST_BSS_COUNTER_BIP_DISASSOC, - NUM_WLANTEST_BSS_COUNTER -}; - -enum wlantest_sta_counter { - WLANTEST_STA_COUNTER_AUTH_TX, - WLANTEST_STA_COUNTER_AUTH_RX, - WLANTEST_STA_COUNTER_ASSOCREQ_TX, - WLANTEST_STA_COUNTER_REASSOCREQ_TX, - WLANTEST_STA_COUNTER_PTK_LEARNED, - WLANTEST_STA_COUNTER_VALID_DEAUTH_TX, - WLANTEST_STA_COUNTER_VALID_DEAUTH_RX, - WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX, - WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX, - WLANTEST_STA_COUNTER_VALID_DISASSOC_TX, - WLANTEST_STA_COUNTER_VALID_DISASSOC_RX, - WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX, - WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX, - WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX, - WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX, - WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX, - WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX, - WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX, - WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX, - WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX, - WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX, - WLANTEST_STA_COUNTER_PING_OK, - 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, - WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP, - WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE, - WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP, - WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE, - WLANTEST_STA_COUNTER_PROT_DATA_TX, - WLANTEST_STA_COUNTER_DEAUTH_RX_RC6, - WLANTEST_STA_COUNTER_DEAUTH_RX_RC7, - WLANTEST_STA_COUNTER_DISASSOC_RX_RC6, - WLANTEST_STA_COUNTER_DISASSOC_RX_RC7, - NUM_WLANTEST_STA_COUNTER -}; - -enum wlantest_tdls_counter { - WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK, - WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK, - WLANTEST_TDLS_COUNTER_VALID_AP_PATH, - WLANTEST_TDLS_COUNTER_INVALID_AP_PATH, - WLANTEST_TDLS_COUNTER_SETUP_REQ, - WLANTEST_TDLS_COUNTER_SETUP_RESP_OK, - WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL, - WLANTEST_TDLS_COUNTER_SETUP_CONF_OK, - WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL, - WLANTEST_TDLS_COUNTER_TEARDOWN, - NUM_WLANTEST_TDLS_COUNTER -}; - -enum wlantest_inject_frame { - WLANTEST_FRAME_AUTH, - WLANTEST_FRAME_ASSOCREQ, - WLANTEST_FRAME_REASSOCREQ, - WLANTEST_FRAME_DEAUTH, - WLANTEST_FRAME_DISASSOC, - WLANTEST_FRAME_SAQUERYREQ, -}; - -/** - * enum wlantest_inject_protection - WLANTEST_CTRL_INJECT protection - * @WLANTEST_INJECT_NORMAL: Use normal rules (protect if key is set) - * @WLANTEST_INJECT_PROTECTED: Force protection (fail if not possible) - * @WLANTEST_INJECT_UNPROTECTED: Force unprotected - * @WLANTEST_INJECT_INCORRECT_KEY: Force protection with incorrect key - */ -enum wlantest_inject_protection { - WLANTEST_INJECT_NORMAL, - WLANTEST_INJECT_PROTECTED, - WLANTEST_INJECT_UNPROTECTED, - WLANTEST_INJECT_INCORRECT_KEY, -}; - -enum wlantest_sta_info { - WLANTEST_STA_INFO_PROTO, - WLANTEST_STA_INFO_PAIRWISE, - WLANTEST_STA_INFO_KEY_MGMT, - WLANTEST_STA_INFO_RSN_CAPAB, - WLANTEST_STA_INFO_STATE, - WLANTEST_STA_INFO_GTK, -}; - -enum wlantest_bss_info { - WLANTEST_BSS_INFO_PROTO, - WLANTEST_BSS_INFO_PAIRWISE, - WLANTEST_BSS_INFO_GROUP, - WLANTEST_BSS_INFO_GROUP_MGMT, - WLANTEST_BSS_INFO_KEY_MGMT, - WLANTEST_BSS_INFO_RSN_CAPAB, -}; - -#endif /* WLANTEST_CTRL_H */ diff --git a/wlantest/writepcap.c b/wlantest/writepcap.c deleted file mode 100644 index dac0597..0000000 --- a/wlantest/writepcap.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * PCAP capture file writer - * Copyright (c) 2010, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include <pcap.h> -#include <pcap-bpf.h> - -#include "utils/common.h" -#include "wlantest.h" - - -int write_pcap_init(struct wlantest *wt, const char *fname) -{ - wt->write_pcap = pcap_open_dead(DLT_IEEE802_11_RADIO, 4000); - if (wt->write_pcap == NULL) - return -1; - wt->write_pcap_dumper = pcap_dump_open(wt->write_pcap, fname); - if (wt->write_pcap_dumper == NULL) { - pcap_close(wt->write_pcap); - wt->write_pcap = NULL; - return -1; - } - - wpa_printf(MSG_DEBUG, "Writing PCAP dump to '%s'", fname); - - return 0; -} - - -void write_pcap_deinit(struct wlantest *wt) -{ - if (wt->write_pcap_dumper) { - pcap_dump_close(wt->write_pcap_dumper); - wt->write_pcap_dumper = NULL; - } - if (wt->write_pcap) { - pcap_close(wt->write_pcap); - wt->write_pcap = NULL; - } -} - - -void write_pcap_captured(struct wlantest *wt, const u8 *buf, size_t len) -{ - struct pcap_pkthdr h; - - if (!wt->write_pcap_dumper) - return; - - os_memset(&h, 0, sizeof(h)); - gettimeofday(&wt->write_pcap_time, NULL); - h.ts = wt->write_pcap_time; - h.caplen = len; - h.len = len; - pcap_dump(wt->write_pcap_dumper, &h, buf); -} - - -void write_pcap_decrypted(struct wlantest *wt, const u8 *buf1, size_t len1, - const u8 *buf2, size_t len2) -{ - struct pcap_pkthdr h; - u8 rtap[] = { - 0x00 /* rev */, - 0x00 /* pad */, - 0x08, 0x00, /* header len */ - 0x00, 0x00, 0x00, 0x00 /* present flags */ - }; - u8 *buf; - size_t len; - - if (!wt->write_pcap_dumper) - return; - - os_memset(&h, 0, sizeof(h)); - h.ts = wt->write_pcap_time; - len = sizeof(rtap) + len1 + len2; - buf = os_malloc(len); - if (buf == NULL) - return; - os_memcpy(buf, rtap, sizeof(rtap)); - if (buf1) { - os_memcpy(buf + sizeof(rtap), buf1, len1); - buf[sizeof(rtap) + 1] &= ~0x40; /* Clear Protected flag */ - } - if (buf2) - os_memcpy(buf + sizeof(rtap) + len1, buf2, len2); - h.caplen = len; - h.len = len; - pcap_dump(wt->write_pcap_dumper, &h, buf); - os_free(buf); -} |