Radiotap信息

Posted sudochen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Radiotap信息相关的知识,希望对你有一定的参考价值。

在Linux系统中用wireshark或tcpdump抓无线网卡数据包,每一数据帧前面都有一个叫radiotap的协议头,它包含了信号强度、噪声强度、信道、时间戳等信息。radiotap比传统的Prism或AVS头更有灵活性,成为ieee802.11事实上的标准。支持radiotap的系统较多,如Linux、FreeBSD、NetBSD、OpenBSD,还有Windows(需使用AirPcap)。它的头部定义如下:

struct ieee80211_radiotap_header {
    u_int8_t        it_version;     /* set to 0 */
    u_int8_t        it_pad;
    u_int16_t       it_len;         /* entire length */
    u_int32_t       it_present;     /* fields present */
} __attribute__((__packed__));

it_version:表示版本号,当前为0。
it_pad:没有使用,仅仅是为了结构体对齐。
it_len:表示长度,包括了radiotap头部和数据两部分,如果不需要了解radiotap,则可以直接跳到ieee802.11头部。
it_present:表示radiotap数据的位掩码。radiotap的数据紧跟其头部。当其中的位掩码为true时,表示有对应的数据,可以认为每一比特表示一种类型。比如bit5为1表示有通道数据,则可以获取到信号强度,反之就是没有对应的数据。因此,radiotap的长度其实是不固定的。bit31为1表示还有多个it_present。

radiotap的每个类型都是有严格顺序的,数据的字序是小端格式(little endian byte-order)——包括头部的it_len和it_present。

目前应用比较广的解析库是radiotap-library,在horst软件和Linux内核中都使用到。关于每个类型的解释,可以参考radiotap.h文件的ieee80211_radiotap_type注释。

通过以下方式,设置Ubuntu系统进入monitor模式:

$ sudo iw dev wlp5s0 interface add mon0 type monitor
$ sudo iw dev wlp5s0 del
$ sudo iw dev mon0 set channel 6
$ sudo ifconfig mon0 up

接着使用tcpdump抓包:

$ sudo tcpdump -i mon0 -w test.pcap
tcpdump: listening on mon0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), capture size 262144 bytes
^C2288 packets captured
2344 packets received by filter
0 packets dropped by kernel
5 packets dropped by interface
然后使用wireshark分析刚抓取到的包,如下图所示:
图片描述

使用radiotap-library库解析,示例代码如下:

#include <unistd.h>
#include <stdint.h>
#include <endian.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#include "radiotap_iter.h"


// 根据wireshark抓包抽取的radiotap头部数据
char radiotap_buf[][18] = {
                {0x00, 0x00, 0x12, 0x00, 0x2e, 0x48,
                 0x00, 0x00, 0x00, 0x02, 0x85, 0x09,
                 0xc0, 0x00, 0xc9, 0x00, 0x00, 0x00},
                {0x00, 0x00, 0x12, 0x00, 0x2e, 0x48,
                 0x00, 0x00, 0x00, 0x02, 0x85, 0x09,
                 0xa0, 0x00, 0xa8, 0x00, 0x00, 0x00}};

#define IEEE80211_CHAN_A (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
#define IEEE80211_CHAN_G (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)

static void print_radiotap_namespace(struct ieee80211_radiotap_iterator *iter)
{
    char signal = 0;
    uint32_t phy_freq = 0;

    switch (iter->this_arg_index) {
    case IEEE80211_RADIOTAP_TSFT:
        printf("	TSFT: %llu
", le64toh(*(unsigned long long *)iter->this_arg));
        break;

    case IEEE80211_RADIOTAP_FLAGS:
        printf("	flags: %02x
", *iter->this_arg);
        break;

    case IEEE80211_RADIOTAP_RATE:
        printf("	rate: %.2f Mbit/s
", (double)*iter->this_arg/2);
        break;

    case IEEE80211_RADIOTAP_CHANNEL:
        phy_freq = le16toh(*(uint16_t*)iter->this_arg); // 信道
        iter->this_arg = iter->this_arg + 2; // 通道信息如2G、5G,等
        int x = le16toh(*(uint16_t*)iter->this_arg);
        printf("	freq: %d type: ", phy_freq);

        if ((x & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) {
            printf("A
");
        } else if ((x & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) {
            printf("G
");
        } else if ((x & IEEE80211_CHAN_2GHZ) == IEEE80211_CHAN_2GHZ) {
            printf("B
");
        }
        break;

    case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
        signal = *(signed char*)iter->this_arg;
        printf("	signal: %d dBm
", signal);
        break;

    case IEEE80211_RADIOTAP_RX_FLAGS:
        printf("	RX flags: %#.4x
", le16toh(*(uint16_t *)iter->this_arg));
        break;

    case IEEE80211_RADIOTAP_ANTENNA:
        printf("	antenna: %x
", *iter->this_arg);
        break;

    case IEEE80211_RADIOTAP_RTS_RETRIES:
    case IEEE80211_RADIOTAP_DATA_RETRIES:
    case IEEE80211_RADIOTAP_FHSS:
    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_DB_ANTSIGNAL:
    case IEEE80211_RADIOTAP_DB_ANTNOISE:
    case IEEE80211_RADIOTAP_TX_FLAGS:
        break;

    default:
        printf("	BOGUS DATA
");
        break;
    }
}

int main(int argc, char** argv)
{
    struct ieee80211_radiotap_iterator iter;
    int err;
    int i, j;

    for (i = 0; i < sizeof(radiotap_buf)/sizeof(radiotap_buf[0]); i++) {
        printf("parsing [%d]
", i);

        err = ieee80211_radiotap_iterator_init(&iter, (struct ieee80211_radiotap_header *)radiotap_buf[i],
                                                sizeof(radiotap_buf[i]), NULL);
        if (err) {
            printf("not valid radiotap...
");
            return -1;
        }

        j = 0;

        /**
         * 遍历时,this_arg_index表示当前索引(如IEEE80211_RADIOTAP_TSFT等),
         * this_arg表示当前索引的值,this_arg_size表示值的大小。只有flag为true时才会进一步解析。
         */
        while (!(err = ieee80211_radiotap_iterator_next(&iter))) {
            printf("next[%d]: index: %d size: %d
",
                    j, iter.this_arg_index, iter.this_arg_size);
            if (iter.is_radiotap_ns) { // 表示是radiotap的命名空间
                print_radiotap_namespace(&iter);
            }

            j++;
        }

        printf("==================================
");
    }

    return 0;
}

以上是关于Radiotap信息的主要内容,如果未能解决你的问题,请参考以下文章

vbscript 各种自定义代码片段 - 有关详细信息,请参阅注释

GMSMarker 信息窗口内容(片段)未更新

错误记录Flutter 混合开发获取 BinaryMessenger 报错 ( FlutterActivityAndFragmentDelegate.getFlutterEngine() )(代码片段

将片段中的Firebase信息检索到recyclerview中

《java精品毕设》基于javaweb宠物领养平台管理系统(源码+毕设论文+sql):主要实现:个人中心,信息修改,填写领养信息,交流论坛,新闻,寄养信息,公告,宠物领养信息,我的寄养信息等(代码片段

PHP必用代码片段