Parse Packets in Pcap format
1. pcap_t* pcap_open_offline(const char* fname, char* errbuf)
Open a savefile in the tcpdump/libpcap format to read packets.
pcap_open_offline() is called to open a "savefile" for reading. fname specifies the name of the file to open. The file has the same format as those used by tcpdump(1) and tcpslice(1). The name "-" in a synonym for stdin. Alternatively, you may call pcap_fopen_offline() to read dumped data from an existing open stream fp. Note that on Windows, that stream should be opened in binary mode. errbuf is used to return error text and is only set when pcap_open_offline() or pcap_fopen_offline() fails and returns NULL.
Regular Usage pcap_t * pcap = pcap_open_offline(file.c_str(), errbuff);
2. pcap_next_ex
read the next packet from a pcap_t
#include <pcap/pcap.h>
pcap_next_ex() returns 1 if the packet was read without problems, 0 if packets are being read from a live capture and the timeout expired, -1 if an error occurred while reading the packet, and -2 if packets are being read from a ``savefile'' and there are no more packets to read from the savefile. If -1 is returned,pcap_geterr() or pcap_perror() may be called with p as an argument to fetch or display the error text.
Usage while(int returnValue = pcap_next_ex(pcap, &header, &data) >= 0)
3. Pcap 文件格式
上面介绍了两个用于解析 Pcap 文件的函数, 下面来分析下 Pcap 文件的具体格式
Pcap 文件组成如下:
Global Header
Packet Header (1) /* 第一个数据包 */
Packet Data (1)
Packet Header (2)
Packet Data (2)
…
3.1 Global Header
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;
};
有了上面两个函数, 我们可以直接跳过 Global Header. 因此 global header 不需要关心.
3.2 Packet Header
Packet 指的是 Pcap Packet, Header 的定义是
struct pcap_pkthdr {
struct timeval ts;
bpf_u_int32 caplen;
bpf_u_int32 len;
};
struct timeval {
long tv_sec;
suseconds_t tv_usec;
};
timeval 中, tv_sec 是秒, tv_usec 是毫秒, 使用的是 UTC 时间, 转化到大陆的时间需要加 8 小时.
3.3 Packet Data
Packet Data 是 TCP/IP 协议意义上的数据包, 在 Data 部分, 分别是
以太网帧头 14 字节
IP 头 20 字节
TCP 头一般 20 字节 or UDP 头 (根据 IP 头的协议属性确定)
Payload, 真正的数据.
IP 头部协议类型:
01 ICMP
02 IGMP
06 TCP
17 UDP
88 IGRP
89 OSPF
4. 需要注意
[1] 描述了配置 visual studio 2010 + winpcap 环境具体步骤, 但需要注意最后一步把 winpcap.lib 改成 wpcap.lib 否则编译报错.
[3] 给出了测试代码, 能够运行就表示配置成功, 注意, 假如创建的项目是 empty project, 那么需要在预处理器中额外添加 WIN32;
[4] 有人在 stackoverflow 提问, 使用 [2] 给出的代码得出的记过不对. 有人回答网络流与大小端模式的转化关系, 比如使用ntohl, ntohs, inet_ntoa 函数.
Reference
[1] http://www.rhyous.com/2011/11/12/how-to-compile-winpcap-with-visual-studio-2010/
[2] http://www.rhyous.com/2011/11/13/how-to-read-a-pcap-file-from-wireshark-with-c/
[3] http://blog.csdn.net/caodesheng110/article/details/7670588
[4] http://stackoverflow.com/questions/12999538/read-from-a-pcap-file-and-print-out-ip-addresses-and-port-numbers-in-c-but-my-r