#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#if defined(__APPLE__)
#include <machine/endian.h>
#else
#include <endian.h>
#endif
#include "radiotap_iter.h"
static int fcshdr = 0;
static const struct radiotap_align_size align_size_000000_00[] = {
[0] = { .align = 1, .size = 4, },
[52] = { .align = 1, .size = 4, },
};
static const struct ieee80211_radiotap_namespace vns_array[] = {
{
.oui = 0x000000,
.subns = 0,
.n_bits = sizeof(align_size_000000_00),
.align_size = align_size_000000_00,
},
};
static const struct ieee80211_radiotap_vendor_namespaces vns = {
.ns = vns_array,
.n_ns = sizeof(vns_array)/sizeof(vns_array[0]),
};
static void print_radiotap_namespace(struct ieee80211_radiotap_iterator *iter)
{
switch (iter->this_arg_index) {
case IEEE80211_RADIOTAP_TSFT:
printf("\tTSFT: %llu\n", le64toh(*(unsigned long long *)iter->this_arg));
break;
case IEEE80211_RADIOTAP_FLAGS:
printf("\tflags: %02x\n", *iter->this_arg);
break;
case IEEE80211_RADIOTAP_RATE:
printf("\trate: %lf\n", (double)*iter->this_arg/2);
break;
case IEEE80211_RADIOTAP_CHANNEL:
case IEEE80211_RADIOTAP_FHSS:
case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
case IEEE80211_RADIOTAP_DBM_ANTNOISE:
case IEEE80211_RADIOTAP_LOCK_QUALITY:
case IEEE80211_RADIOTAP_TX_ATTENUATION:
case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
case IEEE80211_RADIOTAP_DBM_TX_POWER:
case IEEE80211_RADIOTAP_ANTENNA:
case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
case IEEE80211_RADIOTAP_DB_ANTNOISE:
case IEEE80211_RADIOTAP_TX_FLAGS:
break;
case IEEE80211_RADIOTAP_RX_FLAGS:
if (fcshdr) {
printf("\tFCS in header: %.8x\n",
le32toh(*(uint32_t *)iter->this_arg));
break;
}
printf("\tRX flags: %#.4x\n",
le16toh(*(uint16_t *)iter->this_arg));
break;
case IEEE80211_RADIOTAP_RTS_RETRIES:
case IEEE80211_RADIOTAP_DATA_RETRIES:
break;
default:
printf("\tBOGUS DATA\n");
break;
}
}
static void print_test_namespace(struct ieee80211_radiotap_iterator *iter)
{
switch (iter->this_arg_index) {
case 0:
case 52:
printf("\t00:00:00-00|%d: %.2x/%.2x/%.2x/%.2x\n",
iter->this_arg_index,
*iter->this_arg, *(iter->this_arg + 1),
*(iter->this_arg + 2), *(iter->this_arg + 3));
break;
default:
printf("\tBOGUS DATA - vendor ns %d\n", iter->this_arg_index);
break;
}
}
static const struct radiotap_override overrides[] = {
{ .field = 14, .align = 4, .size = 4, }
};
int main(int argc, char *argv[])
{
struct ieee80211_radiotap_iterator iter;
struct stat statbuf;
int fd, err, fnidx = 1, i;
void *data;
if (argc != 2 && argc != 3) {
fprintf(stderr, "usage: parse [--fcshdr] <file>\n");
fprintf(stderr, " --fcshdr: read bit 14 as FCS\n");
return 2;
}
if (strcmp(argv[1], "--fcshdr") == 0) {
fcshdr = 1;
fnidx++;
}
fd = open(argv[fnidx], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "cannot open file %s\n", argv[fnidx]);
return 2;
}
if (fstat(fd, &statbuf)) {
perror("fstat");
return 2;
}
data = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
err = ieee80211_radiotap_iterator_init(&iter, data, statbuf.st_size, &vns);
if (err) {
printf("malformed radiotap header (init returns %d)\n", err);
return 3;
}
if (fcshdr) {
iter.overrides = overrides;
iter.n_overrides = sizeof(overrides)/sizeof(overrides[0]);
}
while (!(err = ieee80211_radiotap_iterator_next(&iter))) {
if (iter.this_arg_index == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
printf("\tvendor NS (%.2x-%.2x-%.2x:%d, %d bytes)\n",
iter.this_arg[0], iter.this_arg[1],
iter.this_arg[2], iter.this_arg[3],
iter.this_arg_size - 6);
for (i = 6; i < iter.this_arg_size; i++) {
if (i % 8 == 6)
printf("\t\t");
else
printf(" ");
printf("%.2x", iter.this_arg[i]);
}
printf("\n");
} else if (iter.is_radiotap_ns)
print_radiotap_namespace(&iter);
else if (iter.current_namespace == &vns_array[0])
print_test_namespace(&iter);
}
if (err != -ENOENT) {
printf("malformed radiotap data\n");
return 3;
}
return 0;
}