Skip to content
Merged
83 changes: 75 additions & 8 deletions Packet++/header/Layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,59 @@ namespace pcpp

class Packet;

namespace internal
{
/// @brief Holds information about a Layer's data and object ownership.
struct LayerAllocationInfo
{
/// @brief Pointer to the Packet this layer is attached to (if any).
///
/// If the layer is attached to a Packet, the layer's memory span (data) is considered managed by the
/// Packet. The Packet is responsible for keeping the layer's memory span valid and updating it should it
/// become necessary as long as the layer is attached to it.
///
/// In an event the Packet is destroyed, all of its attached layers's memory views are considered invalid.
/// Accessing layer data after the Packet is destroyed results in undefined behavior.
///
/// If nullptr, the layer is not attached to any Packet and is considered unmanaged.
/// It also means the layer's memory span is considered owned by the layer itself and will be freed when
/// the layer is destroyed.
Packet* attachedPacket = nullptr;

/// @brief Controls if the layer object is considered managed by the attached Packet
///
/// If 'true', the Layer object is considered managed by the attached Packet and will be tracked and freed
/// by it
///
/// If 'false', the Layer object is considered unmanaged and the user is responsible for freeing it.
/// This is commonly the case for layers created on the stack and attached to a Packet.
bool managedByPacket = false;

/// @brief Sets the state of attachment to a specified Packet
/// @param packet Pointer to the Packet this layer is attached to (or nullptr if not attached to any Packet)
/// @param managed True if the layer object's lifetime is to be managed by the Packet, false otherwise
/// @param force If true, bypasses the check for existing attachment. Default is false.
/// @throws std::runtime_error if the layer is already attached to a Packet and 'force' is false
void attachPacket(Packet* packet, bool managed, bool force = false)
{
if (!force && attachedPacket != nullptr)
{
throw std::runtime_error("Layer is already attached to a Packet");
}

attachedPacket = packet;
managedByPacket = managed;
}

/// @brief Clears the attachment to any Packet, resetting to unmanaged state.
void detach()
{
attachedPacket = nullptr;
managedByPacket = false;
}
};
} // namespace internal

/// @class Layer
/// Layer is the base class for all protocol layers. Each protocol supported in PcapPlusPlus has a class that
/// inherits Layer.
Expand Down Expand Up @@ -125,7 +178,7 @@ namespace pcpp
/// by the layer itself
bool isAllocatedToPacket() const
{
return m_Packet != nullptr;
return m_AllocationInfo.attachedPacket != nullptr;
}

/// Copy the raw data of this layer to another array
Expand Down Expand Up @@ -160,26 +213,40 @@ namespace pcpp
protected:
uint8_t* m_Data;
size_t m_DataLen;
Packet* m_Packet;
ProtocolType m_Protocol;
Layer* m_NextLayer;
Layer* m_PrevLayer;
bool m_IsAllocatedInPacket;

Layer()
: m_Data(nullptr), m_DataLen(0), m_Packet(nullptr), m_Protocol(UnknownProtocol), m_NextLayer(nullptr),
m_PrevLayer(nullptr), m_IsAllocatedInPacket(false)
private:
internal::LayerAllocationInfo m_AllocationInfo;

protected:
Layer() : m_Data(nullptr), m_DataLen(0), m_Protocol(UnknownProtocol), m_NextLayer(nullptr), m_PrevLayer(nullptr)
{}

Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType protocol = UnknownProtocol)
: m_Data(data), m_DataLen(dataLen), m_Packet(packet), m_Protocol(protocol), m_NextLayer(nullptr),
m_PrevLayer(prevLayer), m_IsAllocatedInPacket(false)
: m_Data(data), m_DataLen(dataLen), m_Protocol(protocol), m_NextLayer(nullptr), m_PrevLayer(prevLayer),
m_AllocationInfo{ packet, false }
{}

// Copy c'tor
Layer(const Layer& other);
Layer& operator=(const Layer& other);

/// @brief Get a pointer to the Packet this layer is attached to (if any).
/// @return A pointer to the Packet this layer is attached to, or nullptr if the layer is not attached.
Packet* getAttachedPacket()
{
return m_AllocationInfo.attachedPacket;
}

/// @brief Get a pointer to the Packet this layer is attached to (if any).
/// @return A const pointer to the Packet this layer is attached to, or nullptr if the layer is not attached.
Packet const* getAttachedPacket() const
{
return m_AllocationInfo.attachedPacket;
}

void setNextLayer(Layer* nextLayer)
{
m_NextLayer = nextLayer;
Expand Down
14 changes: 7 additions & 7 deletions Packet++/src/BgpLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace pcpp
uint8_t* payload = m_Data + headerLen;
size_t payloadLen = m_DataLen - headerLen;

m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, getAttachedPacket());
}

std::string BgpLayer::toString() const
Expand Down Expand Up @@ -120,10 +120,10 @@ namespace pcpp

bool BgpLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend)
{
if (m_Packet != nullptr)
if (getAttachedPacket() != nullptr)
{
int rawPacketLen = m_Packet->getRawPacket()->getRawDataLen();
const uint8_t* rawPacketPtr = m_Packet->getRawPacket()->getRawData();
int rawPacketLen = getAttachedPacket()->getRawPacket()->getRawDataLen();
const uint8_t* rawPacketPtr = getAttachedPacket()->getRawPacket()->getRawData();

if (m_Data - rawPacketPtr + static_cast<ptrdiff_t>(offsetInLayer) > static_cast<ptrdiff_t>(rawPacketLen))
{
Expand All @@ -143,10 +143,10 @@ namespace pcpp

bool BgpLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten)
{
if (m_Packet != nullptr)
if (getAttachedPacket() != nullptr)
{
int rawPacketLen = m_Packet->getRawPacket()->getRawDataLen();
const uint8_t* rawPacketPtr = m_Packet->getRawPacket()->getRawData();
int rawPacketLen = getAttachedPacket()->getRawPacket()->getRawDataLen();
const uint8_t* rawPacketPtr = getAttachedPacket()->getRawPacket()->getRawData();

if (m_Data - rawPacketPtr + static_cast<ptrdiff_t>(offsetInLayer) +
static_cast<ptrdiff_t>(numOfBytesToShorten) >
Expand Down
10 changes: 5 additions & 5 deletions Packet++/src/CiscoHdlcLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,20 @@ namespace pcpp
case CISCO_HDLC_TYPE_IP:
{
m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
}
case CISCO_HDLC_TYPE_IPV6:
{
m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
}
default:
{
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions Packet++/src/CotpLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ namespace pcpp
size_t payloadLen = m_DataLen - headerLen;

if (S7CommLayer::isDataValid(payload, payloadLen))
m_NextLayer = new S7CommLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new S7CommLayer(payload, payloadLen, this, getAttachedPacket());
else
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
}
} // namespace pcpp
2 changes: 1 addition & 1 deletion Packet++/src/DoIpLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ namespace pcpp
uint8_t* payload = m_Data + headerLen;
size_t payloadLen = m_DataLen - headerLen;

constructNextLayer<PayloadLayer>(payload, payloadLen, m_Packet);
constructNextLayer<PayloadLayer>(payload, payloadLen, getAttachedPacket());
}
}

Expand Down
4 changes: 2 additions & 2 deletions Packet++/src/EthDot3Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ namespace pcpp
size_t payloadLen = m_DataLen - sizeof(ether_dot3_header);

if (LLCLayer::isDataValid(payload, payloadLen))
m_NextLayer = new LLCLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new LLCLayer(payload, payloadLen, this, getAttachedPacket());
else
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
}

std::string EthDot3Layer::toString() const
Expand Down
20 changes: 11 additions & 9 deletions Packet++/src/EthLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,37 @@ namespace pcpp
switch (be16toh(hdr->etherType))
{
case PCPP_ETHERTYPE_IP:
tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen, getAttachedPacket());
break;
case PCPP_ETHERTYPE_IPV6:
tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen, getAttachedPacket());
break;
case PCPP_ETHERTYPE_ARP:
tryConstructNextLayerWithFallback<ArpLayer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<ArpLayer, PayloadLayer>(payload, payloadLen, getAttachedPacket());
break;
case PCPP_ETHERTYPE_VLAN:
case PCPP_ETHERTYPE_IEEE_802_1AD:
tryConstructNextLayerWithFallback<VlanLayer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<VlanLayer, PayloadLayer>(payload, payloadLen, getAttachedPacket());
break;
case PCPP_ETHERTYPE_PPPOES:
tryConstructNextLayerWithFallback<PPPoESessionLayer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<PPPoESessionLayer, PayloadLayer>(payload, payloadLen,
getAttachedPacket());
break;
case PCPP_ETHERTYPE_PPPOED:
tryConstructNextLayerWithFallback<PPPoEDiscoveryLayer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<PPPoEDiscoveryLayer, PayloadLayer>(payload, payloadLen,
getAttachedPacket());
break;
case PCPP_ETHERTYPE_MPLS:
tryConstructNextLayerWithFallback<MplsLayer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<MplsLayer, PayloadLayer>(payload, payloadLen, getAttachedPacket());
break;
case PCPP_ETHERTYPE_WAKE_ON_LAN:
tryConstructNextLayerWithFallback<WakeOnLanLayer, PayloadLayer>(payload, payloadLen, m_Packet);
tryConstructNextLayerWithFallback<WakeOnLanLayer, PayloadLayer>(payload, payloadLen, getAttachedPacket());
break;
}

// If no next layer was constructed, assume it's a payload layer
if (!hasNextLayer())
constructNextLayer<PayloadLayer>(payload, payloadLen, m_Packet);
constructNextLayer<PayloadLayer>(payload, payloadLen, getAttachedPacket());
}

void EthLayer::computeCalculateFields()
Expand Down
34 changes: 17 additions & 17 deletions Packet++/src/GreLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,41 +206,41 @@ namespace pcpp
{
case PCPP_ETHERTYPE_IP:
m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
case PCPP_ETHERTYPE_IPV6:
m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
case PCPP_ETHERTYPE_VLAN:
m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new VlanLayer(payload, payloadLen, this, getAttachedPacket());
break;
case PCPP_ETHERTYPE_MPLS:
m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new MplsLayer(payload, payloadLen, this, getAttachedPacket());
break;
case PCPP_ETHERTYPE_PPP:
m_NextLayer = PPP_PPTPLayer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new PPP_PPTPLayer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new PPP_PPTPLayer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
case PCPP_ETHERTYPE_ETHBRIDGE:
if (EthLayer::isDataValid(payload, payloadLen))
{
m_NextLayer = new EthLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new EthLayer(payload, payloadLen, this, getAttachedPacket());
}
else if (EthDot3Layer::isDataValid(payload, payloadLen))
{
m_NextLayer = new EthDot3Layer(payload, payloadLen, this, m_Packet);
m_NextLayer = new EthDot3Layer(payload, payloadLen, this, getAttachedPacket());
}
else
{
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
}
break;
default:
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
}
}

Expand Down Expand Up @@ -576,16 +576,16 @@ namespace pcpp
{
case PCPP_PPP_IP:
m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
case PCPP_PPP_IPV6:
m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
break;
default:
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
break;
}
}
Expand Down
14 changes: 7 additions & 7 deletions Packet++/src/GtpLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,18 +590,18 @@ namespace pcpp
if (subProto >= 0x45 && subProto <= 0x4e)
{
m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
}
else if ((subProto & 0xf0) == 0x60)
{
m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, getAttachedPacket()))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, getAttachedPacket()));
}
else
{
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
m_NextLayer = new PayloadLayer(payload, payloadLen, this, getAttachedPacket());
}
}

Expand Down Expand Up @@ -1315,11 +1315,11 @@ namespace pcpp

if (getHeader()->piggybacking && GtpV2Layer::isDataValid(nextLayerData, nextLayerDataLen))
{
m_NextLayer = new GtpV2Layer(nextLayerData, nextLayerDataLen, this, m_Packet);
m_NextLayer = new GtpV2Layer(nextLayerData, nextLayerDataLen, this, getAttachedPacket());
}
else
{
m_NextLayer = new PayloadLayer(nextLayerData, nextLayerDataLen, this, m_Packet);
m_NextLayer = new PayloadLayer(nextLayerData, nextLayerDataLen, this, getAttachedPacket());
}
}

Expand Down
Loading
Loading