一、pcap文件格式(该部分引用网络资料) pcap文件格式及文件解析
第一部分:PCAP包文件格式
(一)、基本格式:
文件头 数据包头 数据报 数据包头 数据报…
(二)、文件头:
文件头结构体,libpcap源码中定义如下
struct pcap_file_header
{
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone; /* gmt to local correction */
bpf_u_int32 sigfigs; /* accuracy of timestamps */
bpf_u_int32 snaplen; /* max length saved portion of each pkt */
bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
};
说明:
1、标识位:32位的,这个标识位的值是16进制的 0xa1b2c3d4。
2、主版本号:16位, 默认值为0x2。
3、副版本号:16位,默认值为0x04。
4、区域时间:32位,实际上该值并未使用,因此可以将该位设置为0。
5、精确时间戳:32位,实际上该值并未使用,因此可以将该值设置为0。
6、数据包最大长度:32位,该值设置所抓获的数据包的最大长度,如果所有数据包都要抓获,将该值设置为65535;例如:想获取数据包的前64字节,可将该值设置为64。
7、链路层类型:32位, 数据包的链路层包头决定了链路层的类型。
以下是数据值与链路层类型的对应表
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数据包头:
struct pcap_sf_pkthdr
{
struct pcap_timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
struct pcap_timeval
{
bpf_int32 tv_sec; /* seconds */
bpf_int32 tv_usec; /* microseconds */
};
说明:
1、时间戳,包括:
秒计时:32位,一个UNIX格式的精确到秒时间值,用来记录数据包抓获的时间,记录方式是记录从格林尼治时间的1970年1月1日 00:00:00 到抓包时经过的秒数;
微秒计时:32位, 抓取数据包时的微秒值。
2、数据包长度:32位 ,标识所抓获的数据包保存在pcap文件中的实际长度,以字节为单位。
3、数据包实际长度: 所抓获的数据包的真实长度,如果文件中保存不是完整的数据包,那么这个值可能要比前面的数据包长度的值大。
(四)、packet数据:
即Packet(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就是说:PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置。我们需要靠第一个Packet包确定。最后,Packet数据部分的格式其实就是标准的网路协议格式了可以任何网络教材上找得到。
二、写pcap文件
官网上关于libpcap的介绍挺全面,可以参考,以下为写pcap文件的代码,这里只列出需要调用的函数,函数参数原型参考官方文档。
说明:/* … …*/表示省略的代码。头文件为#include <pcap.h>,编译时链接-lpcap
如果没有安装libpcap动态库的话,centos下,镜像源和网络正常的情况下,安装命令为:
yum install libpcap
yum install libpcap-devel
int test
{
pcap_dumper_t *pdumper;
pcap_t *handler;
handler = pcap_open_dead(1, 65535); /* 不限制包的长度 */
pdumper = pcap_dump_open(handler, pcap_path); /* handler是函数内部malloc的,查看了下源代码没有释放,所以还是需要调用者释放的 */
if(handler)
{
free(handler);
handler = NULL;
}
struct pcap_pkthdr hdr;
hdr.ts.tv_sec = 0;
hdr.ts.tv_usec = 0;
DataUnit *p = ptr_head;
int len = 0;
int loop_count = 0;
char sessid[SESSLEN+1] = {0};
/* 获取文件中的第一个会话id */
memcpy(sessid, p->sessid, strlen(p->sessid));
sessid[strlen(p->sessid)] = '\0';
int count_len = 0;
char *buf = NULL;
/* 构造数据包结束标识 */
char end_flag[SESSLEN + 1];
loop_count = 0;
while(loop_count < SESSLEN)
{
end_flag[loop_count] = 'F';
loop_count++;
}
end_flag[SESSLEN] = '\0';
loop_count = 500;
// while((strcmp(sessid ,p->sessid) == 0) && (count_len++ < FILEPACKETS)){
while((count_len++ < FILEPACKETS) && (loop_count--))
{
if(strcmp(p->sessid, end_flag) == 0)
break;
len = (p+1)->offset - p->offset;
printf("packet len = %d\n", len);
buf = (char*)malloc(len+1);
if(NULL == buf)
goto err_exit_free;
memcpy(buf, ptr_read + p->offset, len);
/* 构造数据包头 */
hdr.caplen = len;
hdr.len = len;
/* 数据包写入 */
pcap_dump((u_char*)pdumper, &hdr, buf);
free(buf);
buf = NULL;
p++;
}
/* 清空缓冲区 */
pcap_dump_flush(pdumper);
pcap_dump_close(pdumper);
}