nexmon – Rev 1

Subversion Repositories:
Rev:
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <endian.h>
#include <errno.h>
#include <string.h>
#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;
                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;
        }

#ifdef RADIOTAP_SUPPORT_OVERRIDES
        if (fcshdr) {
                iter.overrides = overrides;
                iter.n_overrides = sizeof(overrides)/sizeof(overrides[0]);
        }
#endif

        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;
}