wlantest: Add preliminary version of IEEE 802.11 protocol testing tool

This tool can be used to capture IEEE 802.11 frames either from a
monitor interface for realtime capturing or from pcap files for
offline analysis. This version is only adding basic infrastructure for
going through the frames and parsing their headers.
This commit is contained in:
Jouni Malinen 2010-11-06 16:20:45 +02:00
parent 6fc58a89e1
commit a149fcc77d
8 changed files with 767 additions and 0 deletions

View file

@ -71,6 +71,12 @@
#define WLAN_FC_STYPE_CFPOLL 6 #define WLAN_FC_STYPE_CFPOLL 6
#define WLAN_FC_STYPE_CFACKPOLL 7 #define WLAN_FC_STYPE_CFACKPOLL 7
#define WLAN_FC_STYPE_QOS_DATA 8 #define WLAN_FC_STYPE_QOS_DATA 8
#define WLAN_FC_STYPE_QOS_DATA_CFACK 9
#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10
#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11
#define WLAN_FC_STYPE_QOS_NULL 12
#define WLAN_FC_STYPE_QOS_CFPOLL 14
#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
/* Authentication algorithms */ /* Authentication algorithms */
#define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_OPEN 0

81
wlantest/Makefile Normal file
View file

@ -0,0 +1,81 @@
ALL=wlantest
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
OBJS += wlantest.o
OBJS += readpcap.o
OBJS += monitor.o
OBJS += process.o
OBJS += crc32.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
wlantest: $(OBJS) $(LIBWLANTEST)
$(LDO) $(LDFLAGS) -o wlantest $(OBJS) -L. -lwlantest $(LIBS)
clean:
$(MAKE) -C ../src clean
rm -f core *~ *.o *.d libwlantest.a libwlantest.so $(ALL)
-include $(OBJS:%.o=%.d)

90
wlantest/crc32.c Normal file
View file

@ -0,0 +1,90 @@
/*
* 32-bit CRC for FCS calculation
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING 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;
}

87
wlantest/monitor.c Normal file
View file

@ -0,0 +1,87 @@
/*
* Linux packet socket monitor
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING 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;
}
wlantest_process(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;
}
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;
}
}

289
wlantest/process.c Normal file
View file

@ -0,0 +1,289 @@
/*
* Received frame processing
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING 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 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(struct wlantest *wt, const u8 *data, size_t len)
{
const struct ieee80211_hdr *hdr;
u16 fc, stype;
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);
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));
}
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(struct wlantest *wt, const u8 *data, size_t len)
{
const struct ieee80211_hdr *hdr;
u16 fc;
if (len < 24)
return;
hdr = (const struct ieee80211_hdr *) data;
fc = le_to_host16(hdr->frame_control);
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));
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));
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));
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;
}
}
static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
{
const struct ieee80211_hdr *hdr;
u16 fc;
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;
}
switch (WLAN_FC_GET_TYPE(fc)) {
case WLAN_FC_TYPE_MGMT:
rx_mgmt(wt, data, len);
break;
case WLAN_FC_TYPE_CTRL:
if (len < 10)
return;
wt->rx_ctrl++;
break;
case WLAN_FC_TYPE_DATA:
rx_data(wt, data, len);
break;
default:
wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected type %d",
WLAN_FC_GET_TYPE(fc));
break;
}
}
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;
}
}
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);
}

73
wlantest/readpcap.c Normal file
View file

@ -0,0 +1,73 @@
/*
* PCAP capture file reader
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "utils/includes.h"
#include <pcap/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;
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(wt, data, hdr->caplen);
}
pcap_close(pcap);
wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count);
return 0;
}

108
wlantest/wlantest.c Normal file
View file

@ -0,0 +1,108 @@
/*
* wlantest - IEEE 802.11 protocol monitoring and testing tool
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "wlantest.h"
extern int wpa_debug_level;
static void wlantest_terminate(int sig, void *signal_ctx)
{
eloop_terminate();
}
static void usage(void)
{
printf("wlantest [-ddhqq] [-i<ifname>] [-r<pcap file>]\n");
}
int main(int argc, char *argv[])
{
int c;
const char *read_file = NULL;
const char *ifname = NULL;
struct wlantest wt;
wpa_debug_level = MSG_INFO;
if (os_program_init())
return -1;
os_memset(&wt, 0, sizeof(wt));
wt.monitor_sock = -1;
for (;;) {
c = getopt(argc, argv, "dhi:r:q");
if (c < 0)
break;
switch (c) {
case 'd':
if (wpa_debug_level > 0)
wpa_debug_level--;
break;
case 'h':
usage();
return 0;
case 'i':
ifname = optarg;
break;
case 'q':
wpa_debug_level++;
break;
case 'r':
read_file = optarg;
break;
default:
usage();
return -1;
}
}
if (ifname == NULL && read_file == NULL) {
usage();
return 0;
}
if (eloop_init())
return -1;
if (read_file && read_cap_file(&wt, read_file) < 0)
return -1;
if (ifname && monitor_init(&wt, ifname) < 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);
if (ifname)
monitor_deinit(&wt);
eloop_destroy();
os_program_deinit();
return 0;
}

33
wlantest/wlantest.h Normal file
View file

@ -0,0 +1,33 @@
/*
* wlantest - IEEE 802.11 protocol monitoring and testing tool
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef WLANTEST_H
#define WLANTEST_H
struct wlantest {
int monitor_sock;
unsigned int rx_mgmt;
unsigned int rx_ctrl;
unsigned int rx_data;
unsigned int fcs_error;
};
int read_cap_file(struct wlantest *wt, const char *fname);
void wlantest_process(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);
void monitor_deinit(struct wlantest *wt);
#endif /* WLANTEST_H */