pcap包解析
pacp包解析在接触激光雷达的时候,不可避免的第一步就是看硬件说明书以及调试厂商发的样例数据。一般情况下,厂商在存储硬件的数据包的时候,都是通过存储pacp包实现的,所以如何读取pacp包,并从中解析出真正有用的数据就变得很重要,接下来我们一步步讲。1.pacp包结构一个Pcap文件包括“Pcap报头”,“数据区”两个部分,其中数据区又分成多个数据包,每个包有报头和数据两个部分,总体结构可见...
pcap包解析
在接触激光雷达的时候,不可避免的第一步就是看硬件说明书以及调试厂商发的样例数据。一般情况下,厂商在存储硬件的数据包的时候,都是通过存储pcap包实现的,所以如何读取pcap包,并从中解析出真正有用的数据就变得很重要,接下来我们一步步讲。
1.pcap包结构
一个Pcap文件包括“Pcap报头”,“数据区”两个部分,其中数据区又分成多个数据包,每个包有报头和数据两个部分,总体结构可见下图(注意所有字节都是连续的):
1.1 pcap报头
“Pcap报头”大小为24个字节,具体结构如下图:
各个字段含义:
Magic(4B): 标记文件开始,并用来识别文件和字节顺序。值可以为0xa1b2c3d4或者0xd4c3b2a1,如果是0xa1b2c3d4表示是大端模式,按照原来的顺序一个字节一个字节的读,如果是0xd4c3b2a1表示小端模式,下面的字节都要交换顺序。现在的电脑大部分是小端模式。
Major(2B): 当前文件的主要版本号,一般为0x0200
Minor(2B): 当前文件的次要版本号,一般为0x0400
ThisZone(4B): 当地的标准事件,如果用的是GMT则全零,一般全零
SigFigs(4B): 时间戳的精度,一般为全零
SnapLen(4B): 最大的存储长度,设置所抓获的数据包的最大长度,如果所有数据包都要抓获,将值设置为65535
LinkType(4B): 链路类型。解析数据包首先要判断它的LinkType,所以这个值很重要。一般的值为1,即以太网。
常用的LinkType(链路类型):
值 | 类型描述 |
---|---|
0 | BSD loopback devices, except for later OpenBSD |
1 | Ethernet, and Linux loopback devices |
6 | 802.5 Token Ring |
7 | ARCnet |
8 | SLIP |
9 | PPP |
10 | FDDI |
100 | LLC/SNAP-encapsulated ATM |
101 | “raw IP”, with no link |
102 | BSD/OS SLIP |
103 | BSD/OS PPP |
104 | Cisco HDLC |
105 | 802.11 |
108 | later OpenBSD loopback devices (with the AF_value in network byte order) |
113 | special Linux “cooked” capture |
114 | LocalTalk |
1.2 数据报头
数据报头可以有多个,每个数据报头16字节,后面都跟着真正的数据包。如下图所示:
以下是各个字段含义:
Timestamp(4B): 时间戳高位,精确到seconds,这是Unix时间戳。捕获数据包的时间一般是根据这个值
Timestamp(4B): 时间戳低位,能够精确到microseconds
Caplen(4B): 当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
Len(4B): 离线数据长度,网路中实际数据帧的长度,一般不大于Caplen,多数情况下和Caplen值一样
这一步中,一定要根据Caplen决定接下来要读的数据长度,至于为什么要这么做,后面解释。
1.3 数据
这里就是抓取到的一个网络包,对于激光雷达一般为以太帧,当然,如果你是分析其他网络包,视具体情况而定。这里以以太帧为例,雷达发送的数据在以太帧的数据部分(ipv4报文)中的数据中,这里有点绕,让我们慢慢解析。
1.3.1Ethernet帧:
解析pcap包,获取到一个数据块时,这个数据块就是以太帧,一般结构如下:
1.目标地址(destination address,DA):6 字节
2.源地址(source address,SA):6 字节
3.类型(type)字段:用于辨别上层协议,2 字节(0x08 0x00 为IPv4)
4.数据(data):64 到1500 字节
1.3.2 ipv4报文
以太帧结构中的type决定数据部分存储什么样的报文,我实际使用时为ipv4,所以数据部分为ipv4报文,所以解析以太帧中的数据部分就是解析ipv4报文,ipv4报文头结构如下:
更加详细的解释可以参考
- 这里有一点需要注意,选项部分有多长,得去查资料,我懒得找,就需要自己解析看看,一般雷达发送的数据存在ipv4报的数据部分,也就是除去报头后剩余的字节,会有一个开始标志,这个开始标志在说明书中一定有说明,这样就可以确定选项部分有多长,然后正确获取雷达发送的数据,然后就可以根据说明书进行一步步解析。
2.软件解析pcap
这里用的软件是Wireshark,一个蓝色鱼鳍图标,下载完成后可以直接打开pcap文件,辅助你解析pcap包数据块。下面是打开一个pcap文件后的结果(数据部分为防止泄密,打码了):
软件中已经解析了pcap文件中的每个数据块,最上方显示了所有数据块的大致信息,中间显示了某个数据块的详细信息,下方显示了某个数据块的原始数据。
-
以太帧头
-
ipv4报头
-
UDP报头
- ipv4数据部分(雷达数据(黄色部分))
3.代码解析(linux)
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char const *argv[]) {
/* code */
FILE *pcap_file;
if ((pcap_file = fopen("path/to/pcap file", "rb")) == NULL) {
cout << "cannot open file!\n";
}
char buffer[24];
// read pcap head
fread(buffer, 24, 1, pcap_file);
//read 3000 ethernet package
for (int p = 0; p < 3000; p++) {
// read package head
char package_head[16];
fread(package_head, 16, 1, pcap_file);
//read package data length
int package_data_length =
(int)(unsigned char)package_head[8] +
((int)(unsigned char)package_head[9]) * pow(16.0, 2.0) +
((int)(unsigned char)package_head[10]) * pow(16.0, 4.0) +
((int)(unsigned char)package_head[11]) * pow(16.0, 6.0);
char package_data[package_data_length];
fread(package_data, package_data_length, 1, pcap_file);
//deal package to analysis point
ReadEthernetPackage(package_data);
}
fclose(pcap_file);
return 0;
}
4.问题
-
为什么要读package head中的长度,以此决定后面的数据长度?
这是个坑,一定要读,因为有时候雷达厂商发给你的pcap包里面可能包含一些奇奇怪怪的东西,我被坑过。
更多推荐
所有评论(0)