I am working on developing a customized packet sniffer for Windows 7 64 bit host system (NIC card is Realtek PCIe GBE Family Controller) and am using WinPcap 4.3.1 library using C programming and Cygwin development platform. I am able to read outgoing and incoming TCP and UDP packets through my program. However, I am stuck in a problem of not able to get correct timestamp in microsecond from the struct pcap_pkthdr structure. Following is the code snippet from the program where the problem exists:
...
int getPacket;
struct pcap_pkthdr *header;
const u_char *pkt_data;
/* Sniff the packets */
while((getPacket= pcap_next_ex(handle, &header, &pkt_data)) >= 0)
{
printf("\n 1) Epoch is: %ld",header->ts.tv_sec&0x00000000ffffffff);
printf("\n 2) Microsecond is: %ld",header->ts.tv_usec);
...
Following is the console output that I got for these 2 printf() statements in a run:
1) Epoch is: 1460262399
2) Microsecond is: 1576252997999
Time in seconds (header->ts.tv_sec&0x00000000ffffffff) is correct as it translates to 2016-04-09::23:26:39 (yy-mm-dd::hh-mm-ss format)
However, the Microsecond (header->ts.tv_usec) is not correct as the hex value of Microsecond is 0x16F0000016F that always shows this kind of repeating pattern (with different values) at the low and high octet positions. I have analyzed memory dumps and found the same values that makes me believe that the header->ts.tv_usec is not filled correctly by the NPF driver.
I did a lot of search and could not find this issue reported anywhere. Also, I tested the code on separate AMD and Intel machines and the issue seems to linger.
Any suggestion(s) to solve this problem would be highly appreciated.
Actually, in WinPcap, there are only 32 bits in tv_sec
.
WinPcap uses Microsoft's definition of struct timeval
- it does not require Cygwin, so it can't use Cygwin's definition - and, in that definition, tv_sec
and tv_usec
are both long
, and, in MSVC, long
is 32-bit even on 64-bit platforms. (You need a different data type for a 64-bit integer.)
From your test, Cygwin's struct timeval
has a 64-bit tv_sec
and a 64-bit tv_usec
on 64-bit platforms. Therefore:
tv_sec
field, so only the lower 32 bits will be valid, and will think that some random locations in memory are the tv_usec
field, so you'll see the behavior that you're reporting.