使用libpcap的阅读纳秒PCAP文件 [英] Read nanosecond pcap file using libpcap
问题描述
我有一个纳秒的libpcap(nanosec.pcap)文件和纳秒时间标记(例如2.123456789)能够通过使用Wireshark的显示。现在我想用C语言来打开纳秒libpcap的文件,并在源$ C $ C如下。当我尝试使用pcap_open_offine()打开的nanosec.pcap,它将返回未知文件格式的错误。此外,通过在nanosec.pcap到正常PCAP(0x1A2B3C4D),我的头改变幻数从终端(Ubuntu的)有一个分段错误。这里任何专家能指点我怎么能显示使用libpcap的时间戳的纳秒部分?提前致谢!
以下是code:
的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;#包括LT&; netinet / in.h中>
#包括LT&; netinet / ip.h>
#包括LT&;净/ if.h中>
#包括LT&; netinet / if_ether.h>#包括LT&;&pcap.h GT;结构UDP_hdr {
u_short uh_sport; / *源端口* /
u_short uh_dport; /* 目的端口 */
u_short uh_ulen; / *数据报长度* /
u_short uh_sum; / *数据报校验* /
};
/ *一些辅助功能,这是我们在这个文件的末尾定义。 * // *返回一个字符串,再一个时间戳的presentation。 * /
为const char * timestamp_string(timeval结构TS);/ *报告与给定的时间戳倾销包有问题。 * /
无效problem_pkt(timeval结构TS,为const char *的原因);/ *报告的数据包太短的具体问题。 * /
无效TOO_SHORT(timeval结构TS,为const char * truncated_hdr);无效dump_UDP_packet(const的无符号字符*包,timeval结构TS,
unsigned int类型capture_len)
{
结构IP * IP;
结构UDP_hdr * UDP;
无符号整型IP_header_length;/ *为简单起见,我们假定以太网封装。 * /如果(capture_len<的sizeof(结构ether_header))
{
/ *我们甚至没有捕获完整的以太网头,所以我们
*无法进一步分析这一点。
* /
TOO_SHORT(TS,以太网报头);
返回;
}/ *跳过以太网头。 * /
包+ = sizeof的(结构ether_header);
capture_len - = sizeof的(结构ether_header);如果(capture_len<的sizeof(结构IP))
{/ *没有捕获一个完整的IP报头* /
TOO_SHORT(TS,IP报头);
返回;
}IP =(IP结构*)包;
IP_header_length = IP-> ip_hl * 4; / * ip_hl是4字节字* /如果(capture_len< IP_header_length)
{/ *没有捕获完整的IP头包括期权* /
TOO_SHORT(TS,IP报头的选项);
返回;
}如果(IP->!ip_p = IPPROTO_UDP)
{
problem_pkt(TS,非UDP包);
返回;
}/ *跳过IP头去的UDP报头。 * /
包+ = IP_header_length;
capture_len - = IP_header_length;如果(capture_len<的sizeof(结构UDP_hdr))
{
TOO_SHORT(TS,UDP报头);
返回;
}UDP =(结构UDP_hdr *)包;的printf(%S UDP src_port =%d个dst_port =%d个长度=%d个\\ N,
timestamp_string(TS),
还有ntohs(UDP-GT&; uh_sport)
还有ntohs(UDP-GT&; uh_dport)
还有ntohs(UDP-GT&; uh_ulen));
}
INT主(INT ARGC,CHAR *的argv [])
{
pcap_t * PCAP;
const的无符号字符*包;
烧焦errbuf [PCAP_ERRBUF_SIZE]
结构pcap_pkthdr头;/ *跳过程序名称。 * /
++ argv的; --argc;/ *我们预计,只有一个参数,文件的名称倾倒。 * /
如果(argc个!= 1)
{
fprintf中(标准错误,节目需要一个参数,跟踪文件转储\\ n);
出口(1);
}PCAP = pcap_open_offline(的argv [0],errbuf);
如果(PCAP == NULL)
{
fprintf中(标准错误,错误读取PCAP文件:%s \\ n,errbuf);
出口(1);
}/ *现在只是通过提取分组循环,只要我们有
*一些阅读。
* /
而((包= pcap_next(PCAP,和放大器;!头))= NULL)
dump_UDP_packet(包,header.ts,header.caplen);//终止
返回0;
}
/ *注意,这个程序返回一个指针到一个静态缓冲区,
*所以每次调用覆盖由previous调用的返回值。
* /
为const char * timestamp_string(timeval结构TS)
{
静态字符timestamp_string_buf [256];sprintf的(timestamp_string_buf,%d个%09D
(INT)ts.tv_sec,(INT)ts.tv_usec);返回timestamp_string_buf;
}无效problem_pkt(timeval结构TS,为const char *的原因)
{
fprintf中(标准错误,%S:%S \\ n,timestamp_string(TS),原因);
}无效TOO_SHORT(timeval结构TS,为const char * truncated_hdr)
{
fprintf中(标准错误,时间戳%s的数据包将被截断,缺乏一个完整%S \\ n,
timestamp_string(TS),truncated_hdr);
}
在这里任何专家能指点我怎么能显示时间戳的纳秒部分通过使用libpcap的?
块引用>使用libpcap的顶部的最-Git的主干版本,打开捕获文件以
pcap_open_offline_with_tstamp_ precision(路径,PCAP_TSTAMP_ preCISION_NANO,errbuf);
和治疗
timeval结构
在pcap_pkthdr
结构是秒和纳秒,而不是秒和毫秒(即,让你的程序对待tv_usec
为纳秒,而不是微秒 - 有点混乱,但我不知道有一个丑陋的解决方案少)I have a nanosecond libpcap (nanosec.pcap) file and the nanosecond timestamp (eg 2.123456789) can be displayed by using Wireshark. Now i would like to open the nanosecond libpcap file using C language and have the source code as following. When I try to open the the nanosec.pcap by using pcap_open_offine(), it would return "unknown file format" error. Additionally, by changing the magic number at the header of nanosec.pcap to that of normal pcap (0x1A2B3C4D) and I got a segmentation fault error from the terminal (Ubuntu). Any expert here could advice how could I display the nanosecond part of the timestamp by using libpcap? Thanks in advance! Following is the code:
#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); }
解决方案Any expert here could advice how could I display the nanosecond part of the timestamp by using libpcap?
Use the top-of-the-Git-trunk version of libpcap, open the capture file with
pcap_open_offline_with_tstamp_precision(pathname, PCAP_TSTAMP_PRECISION_NANO, errbuf);
and treat the
struct timeval
in thepcap_pkthdr
structure as being seconds and nanoseconds rather than seconds and microseconds (i.e., have your program treattv_usec
as nanoseconds rather than microseconds - a bit confusing, but I'm not sure there's a less-ugly solution).这篇关于使用libpcap的阅读纳秒PCAP文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!