Skip to content

Commit

Permalink
Possibility to read and write packets with nanoseconds precision is a…
Browse files Browse the repository at this point in the history
…dded

Signed-off-by: Pavel <pavel.bashkirov@profitap.com>
  • Loading branch information
Akvinikym committed Jan 10, 2020
1 parent eae97f3 commit 2583f64
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ typedef struct _light_pcapng_t light_pcapng_t;

typedef struct _light_packet_header {
uint32_t interface_id;
struct timeval timestamp;
struct timespec timestamp;
uint32_t captured_length;
uint32_t original_length;
uint16_t data_link;
Expand Down
22 changes: 17 additions & 5 deletions 3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,10 @@ int light_get_next_packet(light_pcapng_t *pcapng, light_packet_header *packet_he
timestamp += epb->timestamp_low;
double timestamp_res = pcapng->file_info->timestamp_resolution[epb->interface_id];
packet_header->timestamp.tv_sec = timestamp * timestamp_res;
packet_header->timestamp.tv_usec = (timestamp - (packet_header->timestamp.tv_sec / timestamp_res))*timestamp_res*1000000;
packet_header->timestamp.tv_nsec =
(timestamp - (packet_header->timestamp.tv_sec / timestamp_res)) // number of time units less than seconds
* timestamp_res // shift . to the left to get 0.{previous_number}
* 1000000000; // get the nanoseconds
if (epb->interface_id < pcapng->file_info->interface_block_count)
packet_header->data_link = pcapng->file_info->link_types[epb->interface_id];

Expand All @@ -426,7 +429,7 @@ int light_get_next_packet(light_pcapng_t *pcapng, light_packet_header *packet_he
packet_header->captured_length = spb->original_packet_length;
packet_header->original_length = spb->original_packet_length;
packet_header->timestamp.tv_sec = 0;
packet_header->timestamp.tv_usec = 0;
packet_header->timestamp.tv_nsec = 0;
if (pcapng->file_info->interface_block_count > 0)
packet_header->data_link = pcapng->file_info->link_types[0];

Expand Down Expand Up @@ -462,6 +465,9 @@ void light_write_packet(light_pcapng_t *pcapng, const light_packet_header *packe

light_pcapng blocks_to_write = NULL;

// TODO: most probably, this section should be removed as soon as possibility to write interface blocks
// manually is added, as all this section does is basically creating "mock" interface blocks with default
// parameters in case interface ID of packet block to be written does not exist - was not read previously
if (iface_id >= pcapng->file_info->interface_block_count)
{
struct _light_interface_description_block interface_block;
Expand All @@ -471,6 +477,12 @@ void light_write_packet(light_pcapng_t *pcapng, const light_packet_header *packe

light_pcapng iface_block_pcapng = light_alloc_block(LIGHT_INTERFACE_BLOCK, (const uint32_t*)&interface_block, sizeof(struct _light_interface_description_block)+3*sizeof(uint32_t));

// let all written packets has a timestamp resolution in nsec - this way we will not loose precision at all;
// when a possibility to write interface blocks is added, the precision should be taken from them
uint8_t nsec_precision = 9;
light_option resolution_option = light_create_option(LIGHT_OPTION_IF_TSRESOL, sizeof(uint8_t), &nsec_precision);
light_add_option(NULL, iface_block_pcapng, resolution_option, LIGHT_FALSE);

blocks_to_write = iface_block_pcapng;
__append_interface_block_to_file_info(iface_block_pcapng, pcapng->file_info);
}
Expand All @@ -481,9 +493,9 @@ void light_write_packet(light_pcapng_t *pcapng, const light_packet_header *packe
//memset(epb_memory, 0, option_size); should be redundant with calloc
struct _light_enhanced_packet_block *epb = (struct _light_enhanced_packet_block *)epb_memory;
epb->interface_id = iface_id;
uint64_t timestamp_usec = (uint64_t)packet_header->timestamp.tv_sec * (uint64_t)1000000 + (uint64_t)packet_header->timestamp.tv_usec;
epb->timestamp_high = timestamp_usec >> 32;
epb->timestamp_low = timestamp_usec & 0xFFFFFFFF;
uint64_t timestamp_nsec = (uint64_t)packet_header->timestamp.tv_sec * (uint64_t)1000000000 + (uint64_t)packet_header->timestamp.tv_nsec;
epb->timestamp_high = timestamp_nsec >> 32;
epb->timestamp_low = timestamp_nsec & 0xFFFFFFFF;
epb->capture_packet_length = packet_header->captured_length;
epb->original_capture_length = packet_header->original_length;

Expand Down
6 changes: 4 additions & 2 deletions Packet++/header/RawPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ namespace pcpp
uint8_t* m_RawData;
int m_RawDataLen;
int m_FrameLength;
timeval m_TimeStamp;
timespec m_TimeStamp;
bool m_DeleteRawDataAtDestructor;
bool m_RawPacketSet;
LinkLayerType m_LinkLayerType;
Expand All @@ -241,6 +241,7 @@ namespace pcpp
* @param[in] layerType The link layer type of this raw packet. The default is Ethernet
*/
RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET);
RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET);

/**
* A default constructor that initializes class'es attributes to default value:
Expand Down Expand Up @@ -287,6 +288,7 @@ namespace pcpp
* @return True if raw data was set successfully, false otherwise
*/
virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);

/**
* Get raw data pointer
Expand Down Expand Up @@ -315,7 +317,7 @@ namespace pcpp
* Get raw data timestamp
* @return Raw data timestamp
*/
timeval getPacketTimeStamp() const { return m_TimeStamp; }
timespec getPacketTimeStamp() const { return m_TimeStamp; }

/**
* Get an indication whether raw data was already set for this instance.
Expand Down
5 changes: 2 additions & 3 deletions Packet++/src/Packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ void Packet::reallocateRawData(size_t newSize)

// allocate a new array with size newSize
m_MaxPacketLen = newSize;

// set the new array to RawPacket
if (!m_RawPacket->reallocateData(m_MaxPacketLen))
{
Expand Down Expand Up @@ -657,7 +656,7 @@ std::string Packet::printPacketInfo(bool timeAsLocalTime) const
dataLenStream << m_RawPacket->getRawDataLen();

// convert raw packet timestamp to printable format
timeval timestamp = m_RawPacket->getPacketTimeStamp();
timespec timestamp = m_RawPacket->getPacketTimeStamp();
time_t nowtime = timestamp.tv_sec;
struct tm *nowtm = NULL;
if (timeAsLocalTime)
Expand All @@ -669,7 +668,7 @@ std::string Packet::printPacketInfo(bool timeAsLocalTime) const
if (nowtm != NULL)
{
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, sizeof(buf), "%s.%06lu", tmbuf, (unsigned long)timestamp.tv_usec);
snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec);
}
else
snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000");
Expand Down
16 changes: 16 additions & 0 deletions Packet++/src/RawPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ void RawPacket::init()
}

RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType)
{
timespec nsec_time;
TIMEVAL_TO_TIMESPEC(&timestamp, &nsec_time)
init();
m_DeleteRawDataAtDestructor = deleteRawDataAtDestructor;
setRawData(pRawData, rawDataLen, nsec_time, layerType);
}

RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType)
{
init();
m_DeleteRawDataAtDestructor = deleteRawDataAtDestructor;
Expand Down Expand Up @@ -80,6 +89,13 @@ void RawPacket::copyDataFrom(const RawPacket& other, bool allocateData)
}

bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType, int frameLength)
{
timespec nsec_time;
TIMEVAL_TO_TIMESPEC(&timestamp, &nsec_time)
return setRawData(pRawData, rawDataLen, nsec_time, layerType, frameLength);
}

bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType, int frameLength)
{
if(frameLength == -1)
frameLength = rawDataLen;
Expand Down
10 changes: 7 additions & 3 deletions Packet++/src/TcpReassembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ void TcpReassembly::reassemblePacket(Packet& tcpData)
tcpReassemblyData->connData.srcPort = be16toh(tcpLayer->getTcpHeader()->portSrc);
tcpReassemblyData->connData.dstPort = be16toh(tcpLayer->getTcpHeader()->portDst);
tcpReassemblyData->connData.flowKey = flowKey;
timeval ts = tcpData.getRawPacket()->getPacketTimeStamp();
tcpReassemblyData->connData.setStartTime(ts);
timespec ts = tcpData.getRawPacket()->getPacketTimeStamp();
timeval ts_usec;
TIMESPEC_TO_TIMEVAL(&ts_usec, &ts);
tcpReassemblyData->connData.setStartTime(ts_usec);

m_ConnectionList[flowKey] = tcpReassemblyData;
m_ConnectionInfo[flowKey] = tcpReassemblyData->connData;
Expand All @@ -207,7 +209,9 @@ void TcpReassembly::reassemblePacket(Packet& tcpData)
else // connection already exists
{
tcpReassemblyData = iter->second;
timeval currTime = tcpData.getRawPacket()->getPacketTimeStamp();
timespec currTime_nsec = tcpData.getRawPacket()->getPacketTimeStamp();
timeval currTime;
TIMESPEC_TO_TIMEVAL(&currTime, &currTime_nsec);
if (currTime.tv_sec > tcpReassemblyData->connData.endTime.tv_sec)
{
tcpReassemblyData->connData.setEndTime(currTime);
Expand Down
4 changes: 2 additions & 2 deletions Pcap++/header/PcapFileDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ namespace pcpp
PcapNgFileReaderDevice(const PcapNgFileReaderDevice& other);
PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other);

bool matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timeval packetTimestamp, uint16_t linkType);
bool matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timespec packetTimestamp, uint16_t linkType);

public:
/**
Expand Down Expand Up @@ -402,7 +402,7 @@ namespace pcpp
PcapNgFileWriterDevice(const PcapFileWriterDevice& other);
PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other);

bool matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timeval packetTimestamp, uint16_t linkType);
bool matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timespec packetTimestamp, uint16_t linkType);

public:

Expand Down
3 changes: 2 additions & 1 deletion Pcap++/src/PcapDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ bool IPcapDevice::matchPacketWithFilter(std::string filterAsString, RawPacket* r
struct pcap_pkthdr pktHdr;
pktHdr.caplen = rawPacket->getRawDataLen();
pktHdr.len = rawPacket->getRawDataLen();
pktHdr.ts = rawPacket->getPacketTimeStamp();
timespec ts = rawPacket->getPacketTimeStamp();
TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &ts)

return (pcap_offline_filter(&prog, &pktHdr, rawPacket->getRawData()) != 0);
}
Expand Down
11 changes: 6 additions & 5 deletions Pcap++/src/PcapFileDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ PcapNgFileReaderDevice::PcapNgFileReaderDevice(const char* fileName) : IFileRead
m_BpfInitialized = false;
}

bool PcapNgFileReaderDevice::matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timeval packetTimestamp, uint16_t linkType)
bool PcapNgFileReaderDevice::matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timespec packetTimestamp, uint16_t linkType)
{
if (m_CurFilter == "")
return true;
Expand All @@ -219,7 +219,7 @@ bool PcapNgFileReaderDevice::matchPacketWithFilter(const uint8_t* packetData, si
struct pcap_pkthdr pktHdr;
pktHdr.caplen = packetLen;
pktHdr.len = packetLen;
pktHdr.ts = packetTimestamp;
TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packetTimestamp);
return (pcap_offline_filter(&m_Bpf, &pktHdr, packetData) != 0);
}

Expand Down Expand Up @@ -460,7 +460,8 @@ bool PcapFileWriterDevice::writePacket(RawPacket const& packet)
pcap_pkthdr pktHdr;
pktHdr.caplen = ((RawPacket&)packet).getRawDataLen();
pktHdr.len = ((RawPacket&)packet).getFrameLength();
pktHdr.ts = ((RawPacket&)packet).getPacketTimeStamp();
timespec packet_timestamp = ((RawPacket&)packet).getPacketTimeStamp();
TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packet_timestamp)
if (!m_AppendMode)
pcap_dump((uint8_t*)m_PcapDumpHandler, &pktHdr, ((RawPacket&)packet).getRawData());
else
Expand Down Expand Up @@ -651,7 +652,7 @@ PcapNgFileWriterDevice::PcapNgFileWriterDevice(const char* fileName, int compres
m_BpfInitialized = false;
}

bool PcapNgFileWriterDevice::matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timeval packetTimestamp, uint16_t linkType)
bool PcapNgFileWriterDevice::matchPacketWithFilter(const uint8_t* packetData, size_t packetLen, timespec packetTimestamp, uint16_t linkType)
{
if (m_CurFilter == "")
return true;
Expand All @@ -676,7 +677,7 @@ bool PcapNgFileWriterDevice::matchPacketWithFilter(const uint8_t* packetData, si
struct pcap_pkthdr pktHdr;
pktHdr.caplen = packetLen;
pktHdr.len = packetLen;
pktHdr.ts = packetTimestamp;
TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packetTimestamp)
return (pcap_offline_filter(&m_Bpf, &pktHdr, packetData) != 0);
}

Expand Down
3 changes: 2 additions & 1 deletion Pcap++/src/PcapFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ bool GeneralFilter::matchPacketWithFilter(RawPacket* rawPacket)
struct pcap_pkthdr pktHdr;
pktHdr.caplen = rawPacket->getRawDataLen();
pktHdr.len = rawPacket->getRawDataLen();
pktHdr.ts = rawPacket->getPacketTimeStamp();
timespec ts = rawPacket->getPacketTimeStamp();
TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &ts)

return (pcap_offline_filter(m_program, &pktHdr, rawPacket->getRawData()) != 0);
}
Expand Down
6 changes: 3 additions & 3 deletions Tests/Pcap++Test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1224,13 +1224,13 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv)
PTF_ASSERT((rawPacket.getPacketTimeStamp().tv_sec - rawPacket2.getPacketTimeStamp().tv_sec) < 2, "Timestamps are differ in more than 2 secs");
}

if (rawPacket.getPacketTimeStamp().tv_usec < rawPacket2.getPacketTimeStamp().tv_usec)
if (rawPacket.getPacketTimeStamp().tv_nsec < rawPacket2.getPacketTimeStamp().tv_nsec)
{
PTF_ASSERT((rawPacket2.getPacketTimeStamp().tv_usec - rawPacket.getPacketTimeStamp().tv_usec) < 100, "Timestamps are differ in more than 100 usecs");
PTF_ASSERT((rawPacket2.getPacketTimeStamp().tv_nsec - rawPacket.getPacketTimeStamp().tv_nsec) < 100, "Timestamps are differ in more than 100 nsecs");
}
else
{
PTF_ASSERT((rawPacket.getPacketTimeStamp().tv_usec - rawPacket2.getPacketTimeStamp().tv_usec) < 100, "Timestamps are differ in more than 100 usecs");
PTF_ASSERT((rawPacket.getPacketTimeStamp().tv_nsec - rawPacket2.getPacketTimeStamp().tv_nsec) < 100, "Timestamps are differ in more than 100 nsecs");
}

}
Expand Down

0 comments on commit 2583f64

Please sign in to comment.