我正在尝试用C语言解析pcap文件。我不想使用libpcap。但出于某种原因,我无法做到。你知道我怎么能这样做吗?这是我的尝试:
fseek(f,24,0);
while(count<20)//reading 20 packets
{
fread(header,sizeof(struct pcap_pkthdr),1,f);
//after this I'm printing values header fields
fseek(f,ntohl(header->caplen),1);
count++;
}
输出与libpcap不同。
答案 0 :(得分:4)
struct pcap_pkthdr
是 NOT 定义pcap文件中数据包标头格式的结构;它是定义使用libpcap或WinPcap为程序提供的包头格式的结构。
在pcap文件中定义数据包标头格式的结构在任何pcap包含文件中都是 NOT ,因为libpcap / WinPcap提供了读取这些标头的例程,并根据需要将它们转换为{ {1}}标题。与pcap_pkthdr
不同,pcap文件中数据包标头中的时间戳始终具有32位“秒”字段和32位“微秒”字段,即使在struct pcap_pkthdr
和{{time_t
的系统上也是如此。 1 {} tv_sec
中的值为64位。
即,结构由
定义struct timeval
其中struct pcap_timeval {
bpf_int32 tv_sec; /* seconds */
bpf_int32 tv_usec; /* microseconds */
};
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_sf_pkthdr
,则必须进行字节交换struct pcap_sf_pkthdr
,ts.tv_sec
,ts.tv_usec
和{{1} } IF 该文件写在一台机器上,该机器的字节顺序与您正在读取该文件的机器不同。像caplen
这样简单的事情 NOT 工作 - 例如,如果您的文件与您正在读取它的文件写在同一台机器上,则不需要进行字节交换。
ONLY 使用该方法的方法是 READ 文件头,而不是仅使用len
跳过它。如果文件头中的“幻数”具有值ntohl()
,那么您不需要进行任何字节交换;如果它具有值fseek()
,则需要对文件头和0xa1b2c3d4
中的值进行字节交换。请注意,如果您在PowerPC / Power Architecture计算机或MIPS计算机等大端计算机上运行,0xd4c3b2a1
和struct pcap_sf_pkthdr
将 NOT 字节交换IBM大型机或....
另请注意,并非所有捕获文件都是pcap文件;如果它们是pcap-NG文件,则必须以完全不同的方式阅读。 Libpcap 1.1及更高版本知道如何读取pcap-NG文件(libpcap / WinPcap API不够强大,无法处理所有 pcap-NG文件,但它可以处理pcap-NG文件只有一个部分,只有来自一个网络适配器的数据包,libpcap 1.1及更高版本可以读取这些数据包)。我建议,正如解开建议的那样,你使用libpcap / WinPcap来读取捕获文件,而不是编写自己的代码来实现它。
答案 1 :(得分:1)
确保正确处理pcap文件格式的字节顺序。
此外,直接从磁盘加载整个结构很少是安全的,因为编译器可以在结构字段之间自由插入填充,这将使磁盘中的字节与内存中的字节不匹配。
我建议你使用官方图书馆,从那以后这些问题就已经得到了解决。
答案 2 :(得分:0)
尝试类似的东西:
struct dump_pcap_pkthdr {
struct timeval ts; /* time stamp */
unsigned int caplen; /* length of portion present */
unsigned int len; /* length this packet (off wire) */
};
struct dump_pcap_file_header {
unsigned int magic;
unsigned short version_major;
unsigned short version_minor;
int thiszone; /* gmt to local correction */
unsigned int sigfigs; /* accuracy of timestamps */
unsigned int snaplen; /* max length saved portion of each pkt */
unsigned int linktype; /* data link type (LINKTYPE_*) */
};
static void read_pcap_file(char *file)
{
int fd = -1;
struct dump_pcap_pkthdr packet_header = {0};
struct dump_pcap_file_header pcap_header = {0};
fd = open(file, O_RDONLY);
if(fd < 0) {
printf("Fail open file: %s\n", file);
return;
}
if(read(fd, &pcap_header, sizeof(pcap_header)) != sizeof(pcap_header)) {
printf("Failed to read TCPDump Header from file: %s\n", file);
return;
}
while(1)
{
r = read(fd, &packet_header, sizeof(packet_header));
if(r != sizeof(packet_header))
break;
//print data
lseek(fd, packet_header.caplen, SEEK_CUR);
}
close(fd);
}