#define LOG_MODULE PacketLogModulePacket
#include "Packet.h"
#include "EthLayer.h"
#include "EthDot3Layer.h"
#include "SllLayer.h"
#include "Sll2Layer.h"
#include "NflogLayer.h"
#include "NullLoopbackLayer.h"
#include "IPv4Layer.h"
#include "IPv6Layer.h"
#include "PayloadLayer.h"
#include "PacketTrailerLayer.h"
#include "Logger.h"
#include "EndianPortable.h"
#include <string.h>
#include <typeinfo>
#include <sstream>
#ifdef _MSC_VER
#include <time.h>
#include "SystemUtils.h"
#endif
namespace pcpp
{
Packet::Packet(size_t maxPacketLen) :
m_RawPacket(nullptr),
m_FirstLayer(nullptr),
m_LastLayer(nullptr),
m_ProtocolTypes(UnknownProtocol),
m_MaxPacketLen(maxPacketLen),
m_FreeRawPacket(true),
m_CanReallocateData(true)
{
timeval time;
gettimeofday(&time, nullptr);
uint8_t* data = new uint8_t[maxPacketLen];
memset(data, 0, maxPacketLen);
m_RawPacket = new RawPacket(data, 0, time, true, LINKTYPE_ETHERNET);
}
Packet::Packet(uint8_t* buffer, size_t bufferSize) :
m_RawPacket(nullptr),
m_FirstLayer(nullptr),
m_LastLayer(nullptr),
m_ProtocolTypes(UnknownProtocol),
m_MaxPacketLen(bufferSize),
m_FreeRawPacket(true),
m_CanReallocateData(false)
{
timeval time;
gettimeofday(&time, nullptr);
memset(buffer, 0, bufferSize);
m_RawPacket = new RawPacket(buffer, 0, time, false, LINKTYPE_ETHERNET);
}
void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
{
destructPacketData();
m_FirstLayer = nullptr;
m_LastLayer = nullptr;
m_ProtocolTypes = UnknownProtocol;
m_MaxPacketLen = rawPacket->getRawDataLen();
m_FreeRawPacket = freeRawPacket;
m_RawPacket = rawPacket;
m_CanReallocateData = true;
if (m_RawPacket == nullptr)
return;
LinkLayerType linkType = m_RawPacket->getLinkLayerType();
m_FirstLayer = createFirstLayer(linkType);
m_LastLayer = m_FirstLayer;
Layer* curLayer = m_FirstLayer;
while (curLayer != nullptr && (curLayer->getProtocol() & parseUntil) == 0 && curLayer->getOsiModelLayer() <= parseUntilLayer)
{
m_ProtocolTypes |= curLayer->getProtocol();
curLayer->parseNextLayer();
curLayer->m_IsAllocatedInPacket = true;
curLayer = curLayer->getNextLayer();
if (curLayer != nullptr)
m_LastLayer = curLayer;
}
if (curLayer != nullptr && (curLayer->getProtocol() & parseUntil) != 0)
{
m_ProtocolTypes |= curLayer->getProtocol();
curLayer->m_IsAllocatedInPacket = true;
}
if (curLayer != nullptr && curLayer->getOsiModelLayer() > parseUntilLayer)
{
m_LastLayer = curLayer->getPrevLayer();
delete curLayer;
m_LastLayer->m_NextLayer = nullptr;
}
if (m_LastLayer != nullptr && parseUntil == UnknownProtocol && parseUntilLayer == OsiModelLayerUnknown)
{
int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) - (m_LastLayer->getData() + m_LastLayer->getDataLen()));
if (trailerLen > 0)
{
PacketTrailerLayer* trailerLayer = new PacketTrailerLayer(
(uint8_t*)(m_LastLayer->getData() + m_LastLayer->getDataLen()),
trailerLen,
m_LastLayer,
this);
trailerLayer->m_IsAllocatedInPacket = true;
m_LastLayer->setNextLayer(trailerLayer);
m_LastLayer = trailerLayer;
m_ProtocolTypes |= trailerLayer->getProtocol();
}
}
}
Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
{
m_FreeRawPacket = false;
m_RawPacket = nullptr;
m_FirstLayer = nullptr;
setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer);
}
Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil)
{
m_FreeRawPacket = false;
m_RawPacket = nullptr;
m_FirstLayer = nullptr;
setRawPacket(rawPacket, false, parseUntil, OsiModelLayerUnknown);
}
Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer)
{
m_FreeRawPacket = false;
m_RawPacket = nullptr;
m_FirstLayer = nullptr;
setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer);
}
void Packet::destructPacketData()
{
Layer* curLayer = m_FirstLayer;
while (curLayer != nullptr)
{
Layer* nextLayer = curLayer->getNextLayer();
if (curLayer->m_IsAllocatedInPacket)
delete curLayer;
curLayer = nextLayer;
}
if (m_RawPacket != nullptr && m_FreeRawPacket)
{
delete m_RawPacket;
}
}
Packet& Packet::operator=(const Packet& other)
{
destructPacketData();
copyDataFrom(other);
return *this;
}
void Packet::copyDataFrom(const Packet& other)
{
m_RawPacket = new RawPacket(*(other.m_RawPacket));
m_FreeRawPacket = true;
m_MaxPacketLen = other.m_MaxPacketLen;
m_ProtocolTypes = other.m_ProtocolTypes;
m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType());
m_LastLayer = m_FirstLayer;
m_CanReallocateData = true;
Layer* curLayer = m_FirstLayer;
while (curLayer != nullptr)
{
curLayer->parseNextLayer();
curLayer->m_IsAllocatedInPacket = true;
curLayer = curLayer->getNextLayer();
if (curLayer != nullptr)
m_LastLayer = curLayer;
}
}
void Packet::reallocateRawData(size_t newSize)
{
PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize);
m_MaxPacketLen = newSize;
if (!m_RawPacket->reallocateData(m_MaxPacketLen))
{
PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes");
return;
}
const uint8_t* dataPtr = m_RawPacket->getRawData();
Layer* curLayer = m_FirstLayer;
while (curLayer != nullptr)
{
PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'");
curLayer->m_Data = (uint8_t*)dataPtr;
dataPtr += curLayer->getHeaderLen();
curLayer = curLayer->getNextLayer();
}
}
bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket)
{
if (newLayer == nullptr)
{
PCPP_LOG_ERROR("Layer to add is NULL");
return false;
}
if (newLayer->isAllocatedToPacket())
{
PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet");
return false;
}
if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer)
{
PCPP_LOG_ERROR("Cannot insert layer after packet trailer");
return false;
}
size_t newLayerHeaderLen = newLayer->getHeaderLen();
if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen)
{
if (!m_CanReallocateData)
{
PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: " << m_MaxPacketLen << " bytes");
return false;
}
if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen*2)
reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen);
else
reallocateRawData(m_MaxPacketLen*2);
}
int indexToInsertData = 0;
if (prevLayer != nullptr)
indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData();
m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen);
delete[] newLayer->m_Data;
if (prevLayer != nullptr)
{
newLayer->setNextLayer(prevLayer->getNextLayer());
newLayer->setPrevLayer(prevLayer);
prevLayer->setNextLayer(newLayer);
}
else {
newLayer->setNextLayer(m_FirstLayer);
if (m_FirstLayer != nullptr)
m_FirstLayer->setPrevLayer(newLayer);
m_FirstLayer = newLayer;
}
if (newLayer->getNextLayer() == nullptr)
m_LastLayer = newLayer;
else
newLayer->getNextLayer()->setPrevLayer(newLayer);
newLayer->m_Packet = this;
if(ownInPacket)
newLayer->m_IsAllocatedInPacket = true;
const uint8_t* dataPtr = m_RawPacket->getRawData();
size_t dataLen = (size_t)m_RawPacket->getRawDataLen();
size_t packetTrailerLen = 0;
if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
packetTrailerLen = m_LastLayer->getDataLen();
Layer* curLayer = m_FirstLayer;
while (curLayer != nullptr)
{
curLayer->m_Data = (uint8_t*)dataPtr;
if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
curLayer->m_DataLen = dataLen;
else
curLayer->m_DataLen = dataLen - packetTrailerLen;
dataPtr += curLayer->getHeaderLen();
dataLen -= curLayer->getHeaderLen();
curLayer = curLayer->getNextLayer();
}
m_ProtocolTypes |= newLayer->getProtocol();
return true;
}
bool Packet::removeLayer(ProtocolType layerType, int index)
{
Layer* layerToRemove = getLayerOfType(layerType, index);
if (layerToRemove != nullptr)
{
return removeLayer(layerToRemove, true);
}
else
{
PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
return false;
}
}
bool Packet::removeFirstLayer()
{
Layer* firstLayer = getFirstLayer();
if (firstLayer == nullptr)
{
PCPP_LOG_ERROR("Packet has no layers");
return false;
}
return removeLayer(firstLayer, true);
}
bool Packet::removeLastLayer()
{
Layer* lastLayer = getLastLayer();
if (lastLayer == nullptr)
{
PCPP_LOG_ERROR("Packet has no layers");
return false;
}
return removeLayer(lastLayer, true);
}
bool Packet::removeAllLayersAfter(Layer* layer)
{
Layer* curLayer = layer->getNextLayer();
while (curLayer != nullptr)
{
Layer* tempLayer = curLayer->getNextLayer();
if (!removeLayer(curLayer, true))
return false;
curLayer = tempLayer;
}
return true;
}
Layer* Packet::detachLayer(ProtocolType layerType, int index)
{
Layer* layerToDetach = getLayerOfType(layerType, index);
if (layerToDetach != nullptr)
{
if (removeLayer(layerToDetach, false))
return layerToDetach;
else
return nullptr;
}
else
{
PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
return nullptr;
}
}
bool Packet::removeLayer(Layer* layer, bool tryToDelete)
{
if (layer == nullptr)
{
PCPP_LOG_ERROR("Layer is NULL");
return false;
}
if (!layer->isAllocatedToPacket())
{
PCPP_LOG_ERROR("Layer isn't allocated to any packet");
return false;
}
Layer* curLayer = layer;
while (curLayer->m_PrevLayer != nullptr)
curLayer = curLayer->m_PrevLayer;
if (curLayer != m_FirstLayer)
{
PCPP_LOG_ERROR("Layer isn't allocated to this packet");
return false;
}
size_t headerLen = layer->getHeaderLen();
size_t layerOldDataSize = headerLen;
uint8_t* layerOldData = new uint8_t[layerOldDataSize];
memcpy(layerOldData, layer->m_Data, layerOldDataSize);
size_t numOfBytesToRemove = headerLen;
int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData();
if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove))
{
PCPP_LOG_ERROR("Couldn't remove data from packet");
delete [] layerOldData;
return false;
}
if (layer->m_PrevLayer != nullptr)
layer->m_PrevLayer->setNextLayer(layer->m_NextLayer);
if (layer->m_NextLayer != nullptr)
layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer);
if (m_FirstLayer == layer)
m_FirstLayer = layer->m_NextLayer;
if (m_LastLayer == layer)
m_LastLayer = layer->m_PrevLayer;
layer->setNextLayer(nullptr);
layer->setPrevLayer(nullptr);
size_t packetTrailerLen = 0;
if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
packetTrailerLen = m_LastLayer->getDataLen();
const uint8_t* dataPtr = m_RawPacket->getRawData();
size_t dataLen = (size_t)m_RawPacket->getRawDataLen();
curLayer = m_FirstLayer;
bool anotherLayerWithSameProtocolExists = false;
while (curLayer != nullptr)
{
curLayer->m_Data = (uint8_t*)dataPtr;
if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
curLayer->m_DataLen = dataLen;
else
curLayer->m_DataLen = dataLen - packetTrailerLen;
if (curLayer->getProtocol() == layer->getProtocol())
anotherLayerWithSameProtocolExists = true;
dataPtr += curLayer->getHeaderLen();
dataLen -= curLayer->getHeaderLen();
curLayer = curLayer->getNextLayer();
}
if (!anotherLayerWithSameProtocolExists)
m_ProtocolTypes &= ~((uint64_t)layer->getProtocol());
if (tryToDelete && layer->m_IsAllocatedInPacket)
{
delete layer;
delete [] layerOldData;
}
else
{
layer->m_Packet = nullptr;
layer->m_Data = layerOldData;
layer->m_DataLen = layerOldDataSize;
}
return true;
}
Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const
{
Layer* curLayer = getFirstLayer();
int curIndex = 0;
while (curLayer != nullptr)
{
if (curLayer->getProtocol() == layerType)
{
if (curIndex < index)
curIndex++;
else
break;
}
curLayer = curLayer->getNextLayer();
}
return curLayer;
}
bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend)
{
if (layer == nullptr)
{
PCPP_LOG_ERROR("Layer is NULL");
return false;
}
if (!(layer->m_Packet == this))
{
PCPP_LOG_ERROR("Layer isn't allocated to this packet");
return false;
}
if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen)
{
if (!m_CanReallocateData)
{
PCPP_LOG_ERROR("With the layer extended size the packet will exceed the size of the pre-allocated buffer: " << m_MaxPacketLen << " bytes");
return false;
}
if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen*2)
reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen);
else
reallocateRawData(m_MaxPacketLen*2);
}
int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend);
const uint8_t* dataPtr = m_RawPacket->getRawData();
Layer* curLayer = m_FirstLayer;
bool passedExtendedLayer = false;
while (curLayer != nullptr)
{
curLayer->m_Data = (uint8_t*)dataPtr;
if (curLayer->getPrevLayer() == layer)
passedExtendedLayer = true;
if (!passedExtendedLayer)
curLayer->m_DataLen += numOfBytesToExtend;
size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0);
dataPtr += headerLen;
curLayer = curLayer->getNextLayer();
}
return true;
}
bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten)
{
if (layer == nullptr)
{
PCPP_LOG_ERROR("Layer is NULL");
return false;
}
if (!(layer->m_Packet == this))
{
PCPP_LOG_ERROR("Layer isn't allocated to this packet");
return false;
}
int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten))
{
PCPP_LOG_ERROR("Couldn't remove data from packet");
return false;
}
const uint8_t* dataPtr = m_RawPacket->getRawData();
Layer* curLayer = m_FirstLayer;
bool passedExtendedLayer = false;
while (curLayer != nullptr)
{
curLayer->m_Data = (uint8_t*)dataPtr;
if (curLayer->getPrevLayer() == layer)
passedExtendedLayer = true;
if (!passedExtendedLayer)
curLayer->m_DataLen -= numOfBytesToShorten;
size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0);
dataPtr += headerLen;
curLayer = curLayer->getNextLayer();
}
return true;
}
void Packet::computeCalculateFields()
{
Layer* curLayer = m_LastLayer;
while (curLayer != nullptr)
{
curLayer->computeCalculateFields();
curLayer = curLayer->getPrevLayer();
}
}
std::string Packet::printPacketInfo(bool timeAsLocalTime) const
{
std::ostringstream dataLenStream;
dataLenStream << m_RawPacket->getRawDataLen();
timespec timestamp = m_RawPacket->getPacketTimeStamp();
time_t nowtime = timestamp.tv_sec;
struct tm *nowtm = nullptr;
#if __cplusplus > 199711L && !defined(_WIN32)
struct tm nowtm_r;
if (timeAsLocalTime)
nowtm = localtime_r(&nowtime, &nowtm_r);
else
nowtm = gmtime_r(&nowtime, &nowtm_r);
if (nowtm != nullptr)
nowtm = &nowtm_r;
#else
if (timeAsLocalTime)
nowtm = localtime(&nowtime);
else
nowtm = gmtime(&nowtime);
#endif
char buf[128];
if (nowtm != nullptr)
{
char tmbuf[64];
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec);
}
else
snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000");
return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf);
}
Layer* Packet::createFirstLayer(LinkLayerType linkType)
{
size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen();
if (rawDataLen == 0)
return nullptr;
const uint8_t* rawData = m_RawPacket->getRawData();
if (linkType == LINKTYPE_ETHERNET)
{
if (EthLayer::isDataValid(rawData, rawDataLen))
{
return new EthLayer((uint8_t*)rawData, rawDataLen, this);
}
else if (EthDot3Layer::isDataValid(rawData, rawDataLen))
{
return new EthDot3Layer((uint8_t*)rawData, rawDataLen, this);
}
else
{
return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this);
}
}
else if (linkType == LINKTYPE_LINUX_SLL)
{
return new SllLayer((uint8_t*)rawData, rawDataLen, this);
}
else if (linkType == LINKTYPE_LINUX_SLL2 && Sll2Layer::isDataValid(rawData, rawDataLen))
{
return new Sll2Layer((uint8_t*)rawData, rawDataLen, this);
}
else if (linkType == LINKTYPE_NULL)
{
if (rawDataLen >= sizeof(uint32_t))
return new NullLoopbackLayer((uint8_t*)rawData, rawDataLen, this);
else return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this);
}
else if (linkType == LINKTYPE_RAW || linkType == LINKTYPE_DLT_RAW1 || linkType == LINKTYPE_DLT_RAW2)
{
uint8_t ipVer = rawData[0] & 0xf0;
if (ipVer == 0x40)
{
return IPv4Layer::isDataValid(rawData, rawDataLen)
? static_cast<Layer*>(new IPv4Layer((uint8_t*)rawData, rawDataLen, nullptr, this))
: static_cast<Layer*>(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this));
}
else if (ipVer == 0x60)
{
return IPv6Layer::isDataValid(rawData, rawDataLen)
? static_cast<Layer*>(new IPv6Layer((uint8_t*)rawData, rawDataLen, nullptr, this))
: static_cast<Layer*>(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this));
}
else
{
return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this);
}
}
else if (linkType == LINKTYPE_IPV4)
{
return IPv4Layer::isDataValid(rawData, rawDataLen)
? static_cast<Layer*>(new IPv4Layer((uint8_t*)rawData, rawDataLen, nullptr, this))
: static_cast<Layer*>(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this));
}
else if (linkType == LINKTYPE_IPV6)
{
return IPv6Layer::isDataValid(rawData, rawDataLen)
? static_cast<Layer*>(new IPv6Layer((uint8_t*)rawData, rawDataLen, nullptr, this))
: static_cast<Layer*>(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this));
}
else if (linkType == LINKTYPE_NFLOG)
{
return NflogLayer::isDataValid(rawData, rawDataLen)
? static_cast<Layer*>(new NflogLayer((uint8_t*)rawData, rawDataLen, this))
: static_cast<Layer*>(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this));
}
return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this);
}
std::string Packet::toString(bool timeAsLocalTime) const
{
std::vector<std::string> stringList;
std::string result;
toStringList(stringList, timeAsLocalTime);
for (std::vector<std::string>::iterator iter = stringList.begin(); iter != stringList.end(); iter++)
{
result += *iter + '\n';
}
return result;
}
void Packet::toStringList(std::vector<std::string>& result, bool timeAsLocalTime) const
{
result.clear();
result.push_back(printPacketInfo(timeAsLocalTime));
Layer* curLayer = m_FirstLayer;
while (curLayer != nullptr)
{
result.push_back(curLayer->toString());
curLayer = curLayer->getNextLayer();
}
}
}