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);
}