0
votes

I'm having some trouble with a packet capture utility that I am writing. I'm currently using pcapy to open a live bytestream and dpkt to decode the packets. I want to also write the packets to a .pcap file, which workse with the dpkt.Writer object, however the timestamps that are recorded in the pcap file are from when the writer writes the packet to the pcap file, not when the network interface or kernel received the message.

I understand from the documentation that when writing you can supply the ts for the writer to use, however I do not understand how to extract it from the header of the received packet. From examples I can find, which show how to print the timestamp from reading a file, it would seem that I could simply print the first value of the tuple i receive from the bytestream, however when i do I get the following error:

TypeError: int() argument must be a string, a bytes-like object or a number, not 'Pkthdr'

The error is clear enough: i have to find the timestamp attribute in the Pkthdr object no doubt, but i can't find any documentation/examples in either the pcapy project or dpkt that explains how to parse the 'header'

I have also tried to use the pypcap library for the live capture, but the output is the same. I have also attempted the same code on python 2.7.5 as i read that dpkt may not fully support python3 yet, but same result on either version

#!/usr/bin/env python3.6
import pcapy
import dpkt

cap = pcapy.open_live("eth0", 65435, True, 100)
writer = dpkt.pcap.Writer(open("test.pcap", 'wb+'))
while True:
    (header,packet) = cap.next()
    writer.writepkt(packet, header)
    print('packet printed')

To prove that the timestamps in the pcap are from the time of writing, i added sleep period before writing the same packet again. You will see that the two show a ~1 second difference in the header timestamp:

#!/usr/bin/env python3.6
import pcapy
import dpkt
import time

cap = pcapy.open_live("em2", 65435, True, 100)
writer = dpkt.pcap.Writer(open("test.pcap", 'wb+'))
while True:
    (header,packet) = cap.next()
    writer.writepkt(packet, )
    time.sleep(1)
    writer.writepkt(packet, )
    print('packet printed')

I'm not terribly dependent on either pcapy or dpkt, so i'm willing to switch out either of these libraries if there is a better method, however I have a feeling that someone with a little more experience could show me how to dig into the Pkthdr object, extract the timestamp as a str, and then insert it as the 'ts' argument when writing to the pcap:

ts = %unpack from header%
writer.writepkt(packet, ts)

edit: so i had a look at the source code for the pkthdr object in the pcapy module and found something useful: It appears that there is a function called 'getts' to get the timestamp from the object:

static PyMethodDef p_methods[] = {
  {"getts", (PyCFunction) p_getts, METH_VARARGS, "get timestamp tuple 
(seconds, microseconds) since the Epoch"},
  {"getcaplen", (PyCFunction) p_getcaplen, METH_VARARGS, "returns the length 
of portion present"},
  {"getlen", (PyCFunction) p_getlen, METH_VARARGS, "returns the length of 
the packet (off wire)"},
  {NULL, NULL}  /* sentinel */
};

in my python code I called the function like this:

timestamp = header.getts()

And it returned a tuple that contains the seconds and microseconds of the header, e.g. (1555710256, 942645). Next step is to concatenate this into a single number and enter it into the dpkt writer ts. I'll post a working example hopefully very soon

1

1 Answers

0
votes

Ok, I adequately solved my issue. timestamp precision is in microseconds, and is the same across both copies in the .pcap.

#!/usr/bin/env python3.6
import pcapy
import dpkt
import time

cap = pcapy.open_live("em2", 65435, True, 100)
(header,packet) = cap.next()
timestamp = header.getts()
print (timestamp)
writer = dpkt.pcap.Writer(open("test.pcap", 'wb+'))
while True:
    (header,packet) = cap.next()
    ts = header.getts()
    now = time.time()
    print (ts)
    timestamp = ts[0] + (float(ts[1])/1000000))
    writer.writepkt(packet, timestamp)
    time.sleep(1)
    writer.writepkt(packet, timestamp)
    print('packet printed')