一、pcap文件格式
一共三部分:
①Global Header:文件头(共24bytes),它定义了本文件的读取规则、最大储存长度限制等内容。
- Magic:4Byte:标记文件开始,并用来识别文件自己和字节顺序。0xa1b2c3d4用来表示按照原来的顺序读取,0xd4c3b2a1表示下面的字节都要交换顺序读取。考虑到计算机内存的存储结构,一般会采用0xd4c3b2a1,即所有字节都需要交换顺序读取。
- Major:2Byte: 当前文件主要的版本号,一般为 0x0200【实际上因为需要交换读取顺序,所以计算机看到的应该是 0x0002】
- Minor:2Byte: 当前文件次要的版本号,一般为 0x0400【计算机看到的应该是 0x0004】
- ThisZone:4Byte:当地的标准时间,如果用的是GMT则全零,一般都直接写 0000 0000
- SigFigs:4Byte:时间戳的精度,设置为 全零 即可
- SnapLen:4Byte:最大的存储长度,如果想把整个包抓下来,设置为 ffff 0000,但一般来说 ff7f 0000就足够了【计算机看到的应该是 0000 ff7f 】
- LinkType:4Byte:链路类型,常用类型有以下几种,其他的,需要用的时候再查就行了。
- 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
- Packet Header(共 16 Byte) Packet Header可以有多个,每个Packet Header后面会跟着一串Packet Data,Packet Header定义了Packet Data的长度、时间戳等信息。
小端数据存在内存的小端,表示该数据为小端存放。
②Packet Header:可以有多个,每个Packet Header后面会跟着一串Packet Data,Packet Header定义了Packet Data的长度、时间戳等信息。
报文长度,有可能包有2k,但实际只抓到了一半,即1k,len=2k,caplen=1k。
③Packet Data:...
文件结构图例:
二、pcap文件解析API
1.初始化
char errbuf[PCAP_ERRBUF_SIZE];
函数名称:pcap_t *pcap_open_offline(char *fname, char *ebuf)
函数功能:打开以前保存捕获数据包的文件,用于读取。
参数说明:fname参数指定打开的文件名,ebuf表示错误信息的输出。
返回值:文件句柄。函数出错返回NULL,并将错误返回给ebuf。
2.业务处理
我们业务是从pcap文件里边去解析每一个报文
每一个报文包含一个packet header + packet data
需要一个循环来读取每一个报文
typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,
const u_char *bytes);
int pcap_loop(pcap_t *p, int cnt,
pcap_handler callback, u_char *user);
这是一个循环的函数,用来解析pcap文件中的每个报文
p : 句柄 ,pcap_open拿到的
cnt : 遍历多少个报文,如果值为0或者-1 ,遍历所有报文
callback : 回调函数
具体回调逻辑可以大概认为如下:
while(文件还没有到达最后)
{
遍历一个packet header + packet data;
callback(user自定义参数,&packetHeader,&packetData);
}
user: 自定义回调参数,就是每次调用我们的回调函数的时候会传进来
返回值:
成功返回0,出错失败返回-1
3 垃圾回收
void pcap_close(pcap_t *p);
p就是pcap_open得到的句柄
报文数量实例:
#include <stdio.h>
#include <pcap/pcap.h>
void usage(const char *argv0){
fprintf(stderr, "usage: %s <pcap_file>\n", argv0); // stderr会输出到屏幕
}
void pcap_callback(u_char *user, const struct pcap_pkthdr* h, const u_char *bytes){
static int count = 0;
++count;
printf("count:%d\n", count);
}
int main(int argc, char** argv){
if (argc != 2){
usage(argv[0]);
return -1;
}
char errbuf[PCAP_ERRBUF_SIZE]={0};
pcap_t *handle = pcap_open_offline(argv[1], errbuf);
if(!handle){
fprintf(stderr, "Error in pcap_open_offline: %s\n", errbuf);
return -1;
}
pcap_loop(handle, 0, pcap_callback, NULL);
pcap_close(handle);
}