代码中的一些错误 - libpcap

时间:2012-02-14 11:40:19

标签: c network-programming pcap libpcap

我正在尝试用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不同。

3 个答案:

答案 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_pkthdrts.tv_sects.tv_usec和{{1} } IF 该文件写在一台机器上,该机器的字节顺序与您正在读取该文件的机器不同。像caplen这样简单的事情 NOT 工作 - 例如,如果您的文件与您正在读取它的文件写在同一台机器上,则不需要进行字节交换。

ONLY 使用该方法的方法是 READ 文件头,而不是仅使用len跳过它。如果文件头中的“幻数”具有值ntohl(),那么您不需要进行任何字节交换;如果它具有值fseek(),则需要对文件头和0xa1b2c3d4中的值进行字节交换。请注意,如果您在PowerPC / Power Architecture计算机或MIPS计算机等大端计算机上运行,​​0xd4c3b2a1struct 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);
}