blob: 81ad805486066f97c995441166cb743faa112b30 [file] [log] [blame]
#define LOG_MODULE PacketLogModulePacket
#include <Packet.h>
#include <EthLayer.h>
#include <SllLayer.h>
#include <NullLoopbackLayer.h>
#include <IPv4Layer.h>
#include <IPv6Layer.h>
#include <PayloadLayer.h>
#include <Logger.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(NULL),
m_FirstLayer(NULL),
m_LastLayer(NULL),
m_ProtocolTypes(UnknownProtocol),
m_MaxPacketLen(maxPacketLen),
m_FreeRawPacket(true)
{
timeval time;
gettimeofday(&time, NULL);
uint8_t* data = new uint8_t[m_MaxPacketLen];
memset(data, 0, m_MaxPacketLen);
m_RawPacket = new RawPacket((const uint8_t*)data, 0, time, true, LINKTYPE_ETHERNET);
}
void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
{
destructPacketData();
m_FirstLayer = NULL;
m_LastLayer = NULL;
m_ProtocolTypes = UnknownProtocol;
m_MaxPacketLen = rawPacket->getRawDataLen();
m_FreeRawPacket = freeRawPacket;
m_RawPacket = rawPacket;
if (m_RawPacket && m_RawPacket->getLinkLayerType() == LINKTYPE_LINUX_SLL)
{
m_FirstLayer = new SllLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
}
else if (m_RawPacket && m_RawPacket->getLinkLayerType() == LINKTYPE_NULL)
{
m_FirstLayer = new NullLoopbackLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
}
else if (m_RawPacket && (m_RawPacket->getLinkLayerType() == LINKTYPE_RAW || m_RawPacket->getLinkLayerType() == LINKTYPE_DLT_RAW1 || m_RawPacket->getLinkLayerType() == LINKTYPE_DLT_RAW2))
{
uint8_t ipVer = m_RawPacket->getRawData()[0] & 0xf0;
if (ipVer == 0x40)
m_FirstLayer = new IPv4Layer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), NULL, this);
else if (ipVer == 0x60)
m_FirstLayer = new IPv6Layer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), NULL, this);
else
m_FirstLayer = new PayloadLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), NULL, this);
}
else
{
m_FirstLayer = new EthLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
}
m_LastLayer = m_FirstLayer;
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL && (curLayer->getProtocol() & parseUntil) == 0 && curLayer->getOsiModelLayer() <= parseUntilLayer)
{
m_ProtocolTypes |= curLayer->getProtocol();
curLayer->parseNextLayer();
m_LayersAllocatedInPacket.push_back(curLayer);
curLayer = curLayer->getNextLayer();
if (curLayer != NULL)
m_LastLayer = curLayer;
}
if (curLayer != NULL && (curLayer->getProtocol() & parseUntil) != 0)
{
m_ProtocolTypes |= curLayer->getProtocol();
m_LayersAllocatedInPacket.push_back(curLayer);
}
if (curLayer != NULL && curLayer->getOsiModelLayer() > parseUntilLayer)
{
m_LastLayer = curLayer->getPrevLayer();
delete curLayer;
m_LastLayer->m_NextLayer = NULL;
}
}
Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
{
m_FreeRawPacket = false;
m_RawPacket = NULL;
setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer);
}
Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil)
{
m_FreeRawPacket = false;
m_RawPacket = NULL;
setRawPacket(rawPacket, false, parseUntil, OsiModelLayerUnknown);
}
Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer)
{
m_FreeRawPacket = false;
m_RawPacket = NULL;
setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer);
}
Packet::Packet(const Packet& other)
{
copyDataFrom(other);
}
void Packet::destructPacketData()
{
std::vector<Layer*>::iterator iter = m_LayersAllocatedInPacket.begin();
while (iter != m_LayersAllocatedInPacket.end())
{
delete (*iter);
iter = m_LayersAllocatedInPacket.erase(iter);
}
if (m_RawPacket != NULL && 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 = new EthLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
m_LastLayer = m_FirstLayer;
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL)
{
curLayer->parseNextLayer();
m_LayersAllocatedInPacket.push_back(curLayer);
curLayer = curLayer->getNextLayer();
if (curLayer != NULL)
m_LastLayer = curLayer;
}
}
void Packet::reallocateRawData(size_t newSize)
{
LOG_DEBUG("Allocating packet to new size: %d", (int)newSize);
// allocate a new array with size newSize
m_MaxPacketLen = newSize;
// set the new array to RawPacket
if (!m_RawPacket->reallocateData(m_MaxPacketLen))
{
LOG_ERROR("Couldn't reallocate data of raw packet to %d bytes", (int)m_MaxPacketLen);
return;
}
// set all data pointers in layers to the new array address
const uint8_t* dataPtr = m_RawPacket->getRawData();
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL)
{
LOG_DEBUG("Setting new data pointer to layer '%s'", typeid(curLayer).name());
curLayer->m_Data = (uint8_t*)dataPtr;
dataPtr += curLayer->getHeaderLen();
curLayer = curLayer->getNextLayer();
}
}
bool Packet::addLayer(Layer* newLayer)
{
return insertLayer(m_LastLayer, newLayer);
}
bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer)
{
if (newLayer == NULL)
{
LOG_ERROR("Layer to add is NULL");
return false;
}
if (newLayer->isAllocatedToPacket())
{
LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet");
return false;
}
if (m_RawPacket->getRawDataLen() + newLayer->getHeaderLen() > m_MaxPacketLen)
{
// reallocate to maximum value of: twice the max size of the packet or max size + new required length
if (m_RawPacket->getRawDataLen() + newLayer->getHeaderLen() > m_MaxPacketLen*2)
reallocateRawData(m_RawPacket->getRawDataLen() + newLayer->getHeaderLen() + m_MaxPacketLen);
else
reallocateRawData(m_MaxPacketLen*2);
}
size_t appendDataLen = newLayer->getHeaderLen();
// insert layer data to raw packet
int indexToInsertData = 0;
if (prevLayer != NULL)
indexToInsertData = prevLayer->m_Data+prevLayer->getHeaderLen() - m_RawPacket->getRawData();
m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, appendDataLen);
//delete previous layer data
delete[] newLayer->m_Data;
// add layer to layers linked list
if (prevLayer != NULL)
{
newLayer->setNextLayer(prevLayer->getNextLayer());
newLayer->setPrevLayer(prevLayer);
prevLayer->setNextLayer(newLayer);
}
else //prevLayer == NULL
{
newLayer->setNextLayer(m_FirstLayer);
if (m_FirstLayer != NULL)
m_FirstLayer->setPrevLayer(newLayer);
m_FirstLayer = newLayer;
}
if (newLayer->getNextLayer() == NULL)
m_LastLayer = newLayer;
// assign layer with this packet only
newLayer->m_Packet = this;
// re-calculate all layers data ptr and data length
const uint8_t* dataPtr = m_RawPacket->getRawData();
int dataLen = m_RawPacket->getRawDataLen();
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL)
{
curLayer->m_Data = (uint8_t*)dataPtr;
curLayer->m_DataLen = dataLen;
dataPtr += curLayer->getHeaderLen();
dataLen -= curLayer->getHeaderLen();
curLayer = curLayer->getNextLayer();
}
// add layer protocol to protocol collection
m_ProtocolTypes |= newLayer->getProtocol();
return true;
}
bool Packet::removeLayer(Layer* layer)
{
if (layer == NULL)
{
LOG_ERROR("Layer is NULL");
return false;
}
// verify layer is allocated to a packet
if (!layer->isAllocatedToPacket())
{
LOG_ERROR("Layer isn't allocated to any packet");
return false;
}
// verify layer is allocated to *this* packet
Layer* curLayer = layer;
while (curLayer->m_PrevLayer != NULL)
curLayer = curLayer->m_PrevLayer;
if (curLayer != m_FirstLayer)
{
LOG_ERROR("Layer isn't allocated to this packet");
return false;
}
// remove data from raw packet
size_t numOfBytesToRemove = layer->getHeaderLen();
int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData();
if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove))
{
LOG_ERROR("Couldn't remove data from packet");
return false;
}
// remove layer from layers linked list
if (layer->m_PrevLayer != NULL)
layer->m_PrevLayer->setNextLayer(layer->m_NextLayer);
if (layer->m_NextLayer != NULL)
layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer);
// take care of head and tail ptrs
if (m_FirstLayer == layer)
m_FirstLayer = layer->m_NextLayer;
if (m_LastLayer == layer)
m_LastLayer = layer->m_PrevLayer;
layer->setNextLayer(NULL);
layer->setPrevLayer(NULL);
// re-calculate all layers data ptr and data length
const uint8_t* dataPtr = m_RawPacket->getRawData();
int dataLen = m_RawPacket->getRawDataLen();
curLayer = m_FirstLayer;
bool anotherLayerWithSameProtocolExists = false;
while (curLayer != NULL)
{
curLayer->m_Data = (uint8_t*)dataPtr;
curLayer->m_DataLen = dataLen;
if (curLayer->getProtocol() == layer->getProtocol())
anotherLayerWithSameProtocolExists = true;
dataPtr += curLayer->getHeaderLen();
dataLen -= curLayer->getHeaderLen();
curLayer = curLayer->getNextLayer();
}
// remove layer protocol from protocol list if necessary
if (!anotherLayerWithSameProtocolExists)
m_ProtocolTypes &= ~((uint64_t)layer->getProtocol());
return true;
}
bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend)
{
if (layer == NULL)
{
LOG_ERROR("Layer is NULL");
return false;
}
// verify layer is allocated to this packet
if (!(layer->m_Packet == this))
{
LOG_ERROR("Layer isn't allocated to this packet");
return false;
}
if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen)
{
// reallocate to maximum value of: twice the max size of the packet or max size + new required length
if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen*2)
reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen);
else
reallocateRawData(m_MaxPacketLen*2);
}
// insert layer data to raw packet
int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
uint8_t* tempData = new uint8_t[numOfBytesToExtend];
m_RawPacket->insertData(indexToInsertData, tempData, numOfBytesToExtend);
delete[] tempData;
// re-calculate all layers data ptr and data length
const uint8_t* dataPtr = m_RawPacket->getRawData();
int dataLen = m_RawPacket->getRawDataLen();
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL)
{
curLayer->m_Data = (uint8_t*)dataPtr;
curLayer->m_DataLen = dataLen;
// assuming header length of the layer that requested to be extended hasn't been enlarged yet
size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0);
dataPtr += headerLen;
dataLen -= headerLen;
curLayer = curLayer->getNextLayer();
}
return true;
}
bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten)
{
if (layer == NULL)
{
LOG_ERROR("Layer is NULL");
return false;
}
// verify layer is allocated to this packet
if (!(layer->m_Packet == this))
{
LOG_ERROR("Layer isn't allocated to this packet");
return false;
}
// remove data from raw packet
int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten))
{
LOG_ERROR("Couldn't remove data from packet");
return false;
}
// re-calculate all layers data ptr and data length
const uint8_t* dataPtr = m_RawPacket->getRawData();
int dataLen = m_RawPacket->getRawDataLen();
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL)
{
curLayer->m_Data = (uint8_t*)dataPtr;
curLayer->m_DataLen = dataLen;
// assuming header length of the layer that requested to be extended hasn't been enlarged yet
size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0);
dataPtr += headerLen;
dataLen -= headerLen;
curLayer = curLayer->getNextLayer();
}
return true;
}
void Packet::computeCalculateFields()
{
// calculated fields should be calculated from top layer to bottom layer
Layer* curLayer = m_LastLayer;
while (curLayer != NULL)
{
curLayer->computeCalculateFields();
curLayer = curLayer->getPrevLayer();
}
}
Packet::~Packet()
{
destructPacketData();
}
std::string Packet::printPacketInfo(bool timeAsLocalTime)
{
std::ostringstream dataLenStream;
dataLenStream << m_RawPacket->getRawDataLen();
// convert raw packet timestamp to printable format
timeval timestamp = m_RawPacket->getPacketTimeStamp();
time_t nowtime = timestamp.tv_sec;
struct tm *nowtm = NULL;
if (timeAsLocalTime)
nowtm = localtime(&nowtime);
else
nowtm = gmtime(&nowtime);
char tmbuf[64], buf[64];
if (nowtm != NULL)
{
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, sizeof(buf), "%s.%06lu", tmbuf, timestamp.tv_usec);
}
else
snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000");
return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf);
}
std::string Packet::printToString(bool timeAsLocalTime)
{
std::vector<std::string> stringList;
std::string result;
printToStringList(stringList, timeAsLocalTime);
for (std::vector<std::string>::iterator iter = stringList.begin(); iter != stringList.end(); iter++)
{
result += *iter + "\n";
}
return result;
}
void Packet::printToStringList(std::vector<std::string>& result, bool timeAsLocalTime)
{
result.clear();
result.push_back(printPacketInfo(timeAsLocalTime));
Layer* curLayer = m_FirstLayer;
while (curLayer != NULL)
{
result.push_back(curLayer->toString());
curLayer = curLayer->getNextLayer();
}
}
} // namespace pcpp