ieee802.11数据radiotap介绍

之前写有文章介绍了在Linux系统用wireshark或tcpdump抓无线网卡数据包。分析包时发现每一数据帧前面都有一个叫radiotap的东西。它包含了如信号强度、频率等信息。当时没有研究,直接跳过。本文就对此介绍补充。首先介绍radiotap,然后利用radiotap解析库对一段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_present表示长度,包括了radiotap头部和数据两部分。此设计的好处在于,如果不需要了解radiotap,则可以跳过直接到ieee802.11头部。——半个月前写抓包程序时,还不了解radio,就是直接跳过的。第四个字段it_present表示radiotap数据的位掩码。radiotap的数据紧跟其头部。当其中的位掩码为true时,表示有对应的数据,可以认为每一比特表示一种类型。比如bit5为1表示有通道数据,则可以获取到信号强度。反之就是没有对应的数据。因此radiotap的长度其实是不固定的。bit31为1表示还有多个it_present。不过目前笔者还没有碰到此情况,没有深入了解。radiotap的每个类型都是有严格的顺序的。另外,radiotap数据的字序是小端格式(little endian byte-order)——包括头部的it_len和it_present。目前应用比较广的解析库是radiotap-library——在horst软件和Linux内核中都使用到。关于每个类型的解释,可以参考radiotap.h文件的ieee80211_radiotap_type注释。下面看一下wireshark抓到的包的radiotap头部数据:由图可见,radiotap包括的东西挺多的。解析radiotap解析库使用十分简单,先对此有个基本面的认知概念:1、首先完整代码如下:/**radiotap头部解析使用radiotap库,源码地址:https://github.com/radiotap/radiotap-library*/#include#include#include#include#include#include#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},

};

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("\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: %.2f Mbit/s\n", (double)*iter->this_arg/2);

break;

#define IEEE80211_CHAN_A \

(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)

#define IEEE80211_CHAN_G \

(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)

// 通信信息

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("\tfreq: %d type: ", phy_freq);

if ((x & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)

{

printf("A\n");

}

else if ((x & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)

{

printf("G\n");

}

else if ((x & IEEE80211_CHAN_2GHZ) == IEEE80211_CHAN_2GHZ)

{

printf("B\n");

}

break;

// 信号强度

case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:

signal = *(signed char*)iter->this_arg;

printf("\tsignal: %d dBm\n", signal);

break;

break;

// 接收标志

case IEEE80211_RADIOTAP_RX_FLAGS:

printf("\tRX flags: %#.4x\n", le16toh(*(uint16_t *)iter->this_arg));

break;

case IEEE80211_RADIOTAP_ANTENNA:

printf("\tantenna: %x\n", *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("\tBOGUS DATA\n");

break;

}

}

int main(void)

{

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]\n", 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...\n");

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\n",

j, iter.this_arg_index, iter.this_arg_size);

if (iter.is_radiotap_ns) // 表示是radiotap的命名空间

{

print_radiotap_namespace(&iter);

}

j++;

}

printf("==================================\n");

}

return 0;

}

执行结果:

parsing [0]

next[0]: index: 1 size: 1

flags: 00

next[1]: index: 2 size: 1

rate: 1.00 Mbit/s

next[2]: index: 3 size: 4

freq: 2437 type: G

next[3]: index: 5 size: 1

signal: -55 dBm

next[4]: index: 11 size: 1

antenna: 0

next[5]: index: 14 size: 2

RX flags: 0000

==================================

parsing [1]

next[0]: index: 1 size: 1

flags: 00

next[1]: index: 2 size: 1

rate: 1.00 Mbit/s

next[2]: index: 3 size: 4

freq: 2437 type: B

next[3]: index: 5 size: 1

signal: -88 dBm

next[4]: index: 11 size: 1

antenna: 0

next[5]: index: 14 size: 2

RX flags: 0000

==================================

参考资料:

http://www.radiotap.org/

https://github.com/radiotap/radiotap-library

李迟 2016.11.16 周三 晚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,738评论 0 33
  • 教程一:视频截图(Tutorial 01: Making Screencaps) 首先我们需要了解视频文件的一些基...
    90后的思维阅读 4,678评论 0 3
  • 2月7日 多云(也许会有阳光) 7点52分进站,取票,检票,飞奔到高铁站的时候,一列和谐号从左手指...
    仨木阅读 211评论 0 0
  • 1成不了陈寅恪,最好不要学他 清华四大导师之一的陈寅恪,在被聘入清华引起很多争议,因为他没有博士学位。 陈寅恪很有...
    李维坦阅读 618评论 1 0
  • 今天是父亲的生日,所以我想说一些欢快的事情,作为子女我就诙谐一点写部中篇回忆录,就当是孩子不讲大道理。 其实父母的...
    在路上的连Sir阅读 316评论 0 0