您的位置:首页 > 其它

解析pcap文件及读取实现源码

2012-06-17 22:37 846 查看
转自:http://imzc.net/archives/181/%E8%A7%A3%E6%9E%90pcap%E6%96%87%E4%BB%B6%E5%8F%8A%E6%BA%90%E7%A0%81/

下面pcap文件格式介绍是在网上转的,根据理解,写了个程序来进行解析pcap文件,后续再实现合并pcap功能(wireshark已经自带命令行合并pcap文件工具,在这里只是为了分析pcap文件和学习)。
==========================
默认的*.pcap文件保存格式。



Pcap文件头24B各字段说明:

Magic:4B:0x1A 2B 3C 4D:用来标示文件的开始
Major:2B,0×02 00:当前文件主要的版本号
Minor:2B,0×04 00当前文件次要的版本号
ThisZone:4B当地的标准时间;全零
SigFigs:4B时间戳的精度;全零
SnapLen:4B最大的存储长度
LinkType:4B链路类型
常用类型:
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 包头和Packet数据组成
字段说明:
Timestamp:时间戳高位,精确到seconds
Timestamp:时间戳低位,精确到microseconds
Caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
Len:离线数据长度网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等。
Packet 数据: 即 Packet(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就 是说:PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置。我们需要靠第一个Packet包确定。 最后,Packet数据部分的格式其实就是标准的网路协议格式了可以任何网络教材上找得到。
===========================
我的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

//
//  pcap.h
//  pcaptest
//
//  Created by zc on 12-1-24.
//  Copyright 2012年 __MyCompanyName__. All rights reserved.
//

#ifndef pcaptest_pcap_h
#define pcaptest_pcap_h

typedef unsigned int  bpf_u_int32;
typedef unsigned short  u_short;
typedef int bpf_int32;

/*
Pcap文件头24B各字段说明:
Magic:4B:0x1A 2B 3C 4D:用来标示文件的开始
Major:2B,0x02 00:当前文件主要的版本号
Minor:2B,0x04 00当前文件次要的版本号
ThisZone:4B当地的标准时间;全零
SigFigs:4B时间戳的精度;全零
SnapLen:4B最大的存储长度
LinkType:4B链路类型
常用类型:
 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
*/
typedef struct pcap_file_header {
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone;
bpf_u_int32 sigfigs;
bpf_u_int32 snaplen;
bpf_u_int32 linktype;
}pcap_file_header;

/*
Packet 包头和Packet数据组成
字段说明:
Timestamp:时间戳高位,精确到seconds
Timestamp:时间戳低位,精确到microseconds
Caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
Len:离线数据长度:网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等。
Packet 数据:即 Packet(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就 是说:PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置。我们需要靠第一个Packet包确定。
*/

typedef struct  timestamp{
bpf_u_int32 timestamp_s;
bpf_u_int32 timestamp_ms;
}timestamp;

typedef struct pcap_header{
timestamp ts;
bpf_u_int32 capture_len;
bpf_u_int32 len;

}pcap_header;

void prinfPcapFileHeader(pcap_file_header *pfh);
void printfPcapHeader(pcap_header *ph);
void printPcap(void * data,size_t size);

#endif

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
7071
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

//
//  pcap.c
//  pcaptest
//
//  Created by zc on 12-1-24.
//  Copyright 2012年 __MyCompanyName__. All rights reserved.
//

#include <stdio.h>
#include "pcap.h"

void prinfPcapFileHeader(pcap_file_header *pfh){
if (pfh==NULL) {
return;
}
printf("=====================\n"
"magic:0x%0x\n"
"version_major:%u\n"
"version_minor:%u\n"
"thiszone:%d\n"
"sigfigs:%u\n"
"snaplen:%u\n"
"linktype:%u\n"
"=====================\n",
pfh->magic,
pfh->version_major,
pfh->version_minor,
pfh->thiszone,
pfh->sigfigs,
pfh->snaplen,
pfh->linktype);
}

void printfPcapHeader(pcap_header *ph){
if (ph==NULL) {
return;
}
printf("=====================\n"
"ts.timestamp_s:%u\n"
"ts.timestamp_ms:%u\n"
"capture_len:%u\n"
"len:%d\n"
"=====================\n",
ph->ts.timestamp_s,
ph->ts.timestamp_ms,
ph->capture_len,
ph->len);

}

void printPcap(void * data,size_t size){
unsigned  short iPos = 0;
//int * p = (int *)data;
//unsigned short* p = (unsigned short *)data;
if (data==NULL) {
return;
}

printf("\n==data:0x%x,len:%lu=========",data,size);

for (iPos=0; iPos < size/sizeof(unsigned short); iPos++) {
//printf(" %x ",(int)( * (p+iPos) ));
//unsigned short a = ntohs(p[iPos]);

unsigned short a = ntohs( *((unsigned short *)data + iPos ) );
if (iPos%8==0) printf("\n");
if (iPos%4==0) printf(" ");

printf("%04x",a);

}
/*
for (iPos=0; iPos <= size/sizeof(int); iPos++) {
//printf(" %x ",(int)( * (p+iPos) ));
int a = ntohl(p[iPos]);

//int a = ntohl( *((int *)data + iPos ) );
if (iPos %4==0) printf("\n");

printf("%08x ",a);

}
*/
printf("\n============\n");
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
7071
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

//
//  main.c
//  pcaptest
//
//  Created by zc on 12-1-24.
//  Copyright 2012年 __MyCompanyName__. All rights reserved.
//

#include <stdio.h>
#include <arpa/inet.h>
#include "pcap.h"

#define PCAP_FILE "ping.pcap"
#define MAX_ETH_FRAME 1514
#define ERROR_FILE_OPEN_FAILED -1
#define ERROR_MEM_ALLOC_FAILED -2
#define ERROR_PCAP_PARSE_FAILED -3

int main (int argc, const char * argv[])
{

printf("sizeof:int %lu,unsigned int %lu,char %lu,unsigned char %lu,short:%lu,unsigned short:%lu\n",
sizeof(int),sizeof(unsigned int),sizeof(char),sizeof(unsigned char),sizeof(short),sizeof(unsigned short));

pcap_file_header  pfh;
pcap_header  ph;
int count=0;
void * buff = NULL;
int readSize=0;
int ret = 0;

FILE *fp = fopen(PCAP_FILE, "rw");

if (fp==NULL) {
fprintf(stderr, "Open file %s error.",PCAP_FILE);
ret = ERROR_FILE_OPEN_FAILED;
goto ERROR;
}

fread(&pfh, sizeof(pcap_file_header), 1, fp);
prinfPcapFileHeader(&pfh);
//fseek(fp, 0, sizeof(pcap_file_header));

buff = (void *)malloc(MAX_ETH_FRAME);
for (count=1; ; count++) {
memset(buff,0,MAX_ETH_FRAME);
//read pcap header to get a packet
//get only a pcap head count .
readSize=fread(&ph, sizeof(pcap_header), 1, fp);
if (readSize<=0) {
break;
}
printfPcapHeader(&ph);

if (buff==NULL) {
fprintf(stderr, "malloc memory failed.\n");
ret = ERROR_MEM_ALLOC_FAILED;
goto ERROR;
}

//get a packet contents.
//read ph.capture_len bytes.
readSize=fread(buff,1,ph.capture_len, fp);
if (readSize != ph.capture_len) {
free(buff);
fprintf(stderr, "pcap file parse error.\n");
ret = ERROR_PCAP_PARSE_FAILED;
goto ERROR;
}
printPcap(buff, ph.capture_len);

printf("===count:%d,readSize:%d===\n",count,readSize);

if (feof(fp) || readSize <=0 ) {
break;
}
}

ERROR:
//free
if (buff) {
free(buff);
buff=NULL;
}
if (fp) {
fclose(fp);
fp=NULL;
}

return ret;
}

Makefile:

1
2
3
4
5
6
7
8
9
10
11

objects = main.o pcap.o

pcaptest : $(objects)
gcc -o pcaptest  $(objects)

main.o:pcap.h
pcap.o:pcap.h

.PHONY : clean
clean :
rm pcaptest  $(objects)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐