使用libpcap读取纳秒级pcap文件

使用libpcap读取纳秒级pcap文件,c,wireshark,libpcap,C,Wireshark,Libpcap,我有一个纳秒libpcap(nanosec.pcap)文件,可以使用Wireshark显示纳秒时间戳(例如2.123456789)。现在我想用C语言打开纳秒级libpcap文件,并获得如下源代码。当我尝试使用pcap_open_offine()打开nanosec.pcap时,它将返回“未知文件格式”错误。此外,通过将nanosec.pcap头上的幻数更改为普通pcap头上的幻数(0x1A2B3C4D),我从终端(Ubuntu)得到了一个分段错误。这里的任何专家都可以提出建议,如何使用libpca

我有一个纳秒libpcap(nanosec.pcap)文件,可以使用Wireshark显示纳秒时间戳(例如2.123456789)。现在我想用C语言打开纳秒级libpcap文件,并获得如下源代码。当我尝试使用pcap_open_offine()打开nanosec.pcap时,它将返回“未知文件格式”错误。此外,通过将nanosec.pcap头上的幻数更改为普通pcap头上的幻数(0x1A2B3C4D),我从终端(Ubuntu)得到了一个分段错误。这里的任何专家都可以提出建议,如何使用libpcap显示时间戳的纳秒部分?提前谢谢! 代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <netinet/if_ether.h>

#include <pcap.h>

struct UDP_hdr {
u_short uh_sport;       /* source port */
u_short uh_dport;       /* destination port */
u_short uh_ulen;        /* datagram length */
u_short uh_sum;         /* datagram checksum */
};


/* Some helper functions, which we define at the end of this file. */

/* Returns a string representation of a timestamp. */
const char *timestamp_string(struct timeval ts);

/* Report a problem with dumping the packet with the given timestamp. */
void problem_pkt(struct timeval ts, const char *reason);

/* Report the specific problem of a packet being too short. */
void too_short(struct timeval ts, const char *truncated_hdr);

void dump_UDP_packet(const unsigned char *packet, struct timeval ts,
        unsigned int capture_len)
{
struct ip *ip;
struct UDP_hdr *udp;
unsigned int IP_header_length;

/* For simplicity, we assume Ethernet encapsulation. */

if (capture_len < sizeof(struct ether_header))
    {
    /* We didn't even capture a full Ethernet header, so we
     * can't analyze this any further.
     */
    too_short(ts, "Ethernet header");
    return;
    }

/* Skip over the Ethernet header. */
packet += sizeof(struct ether_header);
capture_len -= sizeof(struct ether_header);

if (capture_len < sizeof(struct ip))
    { /* Didn't capture a full IP header */
    too_short(ts, "IP header");
    return;
    }

ip = (struct ip*) packet;
IP_header_length = ip->ip_hl * 4;   /* ip_hl is in 4-byte words */

if (capture_len < IP_header_length)
    { /* didn't capture the full IP header including options */
    too_short(ts, "IP header with options");
    return;
    }

if (ip->ip_p != IPPROTO_UDP)
    {
    problem_pkt(ts, "non-UDP packet");
    return;
    }

/* Skip over the IP header to get to the UDP header. */
packet += IP_header_length;
capture_len -= IP_header_length;

if (capture_len < sizeof(struct UDP_hdr))
    {
    too_short(ts, "UDP header");
    return;
    }

udp = (struct UDP_hdr*) packet;

printf("%s UDP src_port=%d dst_port=%d length=%d\n",
    timestamp_string(ts),
    ntohs(udp->uh_sport),
    ntohs(udp->uh_dport),
    ntohs(udp->uh_ulen));
}


int main(int argc, char *argv[])
{
pcap_t *pcap;
const unsigned char *packet;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_pkthdr header;

/* Skip over the program name. */
++argv; --argc;

/* We expect exactly one argument, the name of the file to dump. */
if ( argc != 1 )
    {
    fprintf(stderr, "program requires one argument, the trace file to dump\n");
    exit(1);
    }

pcap = pcap_open_offline(argv[0], errbuf);
if (pcap == NULL)
    {
    fprintf(stderr, "error reading pcap file: %s\n", errbuf);
    exit(1);
    }

/* Now just loop through extracting packets as long as we have
 * some to read.
 */
while ((packet = pcap_next(pcap, &header)) != NULL)
    dump_UDP_packet(packet, header.ts, header.caplen);

// terminate
return 0;
}


/* Note, this routine returns a pointer into a static buffer, and
 * so each call overwrites the value returned by the previous call.
*/
const char *timestamp_string(struct timeval ts)
{
static char timestamp_string_buf[256];

sprintf(timestamp_string_buf, "%d.%09d",
    (int) ts.tv_sec, (int) ts.tv_usec);

return timestamp_string_buf;
}

void problem_pkt(struct timeval ts, const char *reason)
{
fprintf(stderr, "%s: %s\n", timestamp_string(ts), reason);
}

void too_short(struct timeval ts, const char *truncated_hdr)
{
fprintf(stderr, "packet with timestamp %s is truncated and lacks a full %s\n",
    timestamp_string(ts), truncated_hdr);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构UDP_hdr{
u_short uh_sport;/*源端口*/
u_short uh_dport;/*目的港*/
u_short uh_ulen;/*数据报长度*/
u_short uh_sum;/*数据报校验和*/
};
/*我们在本文件末尾定义了一些帮助函数*/
/*返回时间戳的字符串表示形式*/
常量字符*时间戳字符串(struct timeval ts);
/*报告使用给定时间戳转储数据包的问题*/
无效问题(结构时间值ts,常量字符*原因);
/*报告数据包太短的具体问题*/
void太短(struct timeval ts,const char*truncated_hdr);
无效转储_UDP_数据包(const unsigned char*数据包,struct timeval ts,
无符号整数捕获(n)
{
结构ip*ip;
结构UDP_hdr*UDP;
无符号整数IP头长度;
/*为简单起见,我们假设以太网封装*/
if(捕获长度IP_hl*4;/*IP_hl为4字节字*/
if(捕获长度ip\U p!=IPPROTO\U UDP)
{
问题(ts,“非UDP数据包”);
返回;
}
/*跳过IP头以转到UDP头*/
数据包+=IP_头_长度;
捕获长度-=IP头长度;
if(捕获长度uh_运动),
ntohs(udp->uh_dport),
ntohs(udp->uh_-ulen));
}
int main(int argc,char*argv[])
{
pcap_t*pcap;
常量无符号字符*数据包;
字符errbuf[PCAP_errbuf_SIZE];
结构pcap_pkthdr头;
/*跳过程序名*/
++argv;--argc;
/*我们只需要一个参数,即要转储的文件名*/
如果(argc!=1)
{
fprintf(stderr,“程序需要一个参数,即要转储的跟踪文件”);
出口(1);
}
pcap=pcap\u open\u offline(argv[0],errbuf);
如果(pcap==NULL)
{
fprintf(stderr,“读取pcap文件时出错:%s\n”,errbuf);
出口(1);
}
/*现在只要我们有足够的时间循环提取数据包
*有些人喜欢读书。
*/
while((packet=pcap_next(pcap和头))!=NULL)
dump_UDP_数据包(数据包,header.ts,header.caplen);
//终止
返回0;
}
/*注意,此例程将指针返回到静态缓冲区,然后
*因此,每次调用都会覆盖上一次调用返回的值。
*/
常量字符*时间戳字符串(struct timeval ts)
{
静态字符时间戳_字符串_buf[256];
sprintf(时间戳\u字符串\u buf,“%d.%09d”,
(int)ts.tv_sec(int)ts.tv_usec),;
返回时间戳\u字符串\u buf;
}
无效问题(结构时间值ts,常量字符*原因)
{
fprintf(stderr,“%s:%s\n”,时间戳字符串(ts),原因);
}
void太短(struct timeval ts,const char*截断的\u hdr)
{
fprintf(stderr,“时间戳为%s的数据包被截断,并且缺少完整的%s\n”,
时间戳(ts),截断的(hdr);
}
这里的任何专家都可以提出建议,如何使用libpcap显示时间戳的纳秒部分

使用Git trunk版本的libpcap的顶部,用

pcap_open_offline_with_tstamp_precision(pathname, PCAP_TSTAMP_PRECISION_NANO, errbuf);

并将
pcap\u pkthdr
结构中的
struct timeval
视为秒和纳秒,而不是秒和微秒(也就是说,让您的程序将
tv\u usec
视为纳秒而不是微秒-有点混乱,但我不确定是否有一个不那么难看的解决方案).

您是指位于的libpcap主机吗?我会尝试一下,或者你从git clone获得的git://bpf.tcpdump.org/libpcap,根据。嗨,盖伊先生,运气不好,我用这种方法再次出现了一个分段错误(核心转储)。如何将timeval视为纳秒?换成电视节目?我已经安装了libpcap主机,它甚至无法运行代码。好心的建议。盖伊先生,我已经指出分段错误来自while循环,
packet=pcap\u next(pcap,&header))!=空的,你知道为什么吗?我是如何连续读取所有数据包的?对于libpcap master,正确运行上述代码需要做哪些更改?我在使用libpcap master运行上述代码时遇到问题,libpcap-1.4.0可以毫无问题地运行。故障来自savefile.c(第402行)和pcap.c(第219行)。有什么线索吗?