#ifndef PACKETPP_LAYER #define PACKETPP_LAYER #include #include #include "ProtocolType.h" #include /// @file /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { /** * @class IDataContainer * An interface (virtual abstract class) that indicates an object that holds a pointer to a buffer data. The Layer class is an example * of such object, hence it inherits this interface */ class IDataContainer { public: /** * Get a pointer to the data * @param[in] offset Get a pointer in a certain offset. Default is 0 - get a pointer to start of data * @return A pointer to the data */ virtual uint8_t* getDataPtr(size_t offset = 0) const = 0; virtual ~IDataContainer() {} }; class Packet; /** * @class Layer * Layer is the base class for all protocol layers. Each protocol supported in PcapPlusPlus has a class that inherits Layer. * The protocol layer class expose all properties and methods relevant for viewing and editing protocol fields. * For example: a pointer to a structured header (e.g tcphdr, iphdr, etc.), protocol header size, payload size, compute * fields that can be automatically computed, print protocol data to string, etc. * Each protocol instance is obviously part of a protocol stack (which construct a packet). This protocol stack is represented * in PcapPlusPlus in a linked list, and each layer is an element in this list. That's why each layer has properties to the next and previous * layer in the protocol stack * The Layer class, as a base class, is abstract and the user can't create an instance of it (it has a private constructor) * Each layer holds a pointer to the relevant place in the packet. The layer sees all the data from this pointer forward until the * end of the packet. Here is an example packet showing this concept: * @verbatim ==================================================== |Eth |IPv4 |TCP |Packet | |Header |Header |Header |Payload | ==================================================== |--------------------------------------------------| EthLayer data |---------------------------------------| IPv4Layer data |---------------------------| TcpLayer data |----------------| PayloadLayer data @endverbatim * */ class Layer : public IDataContainer { friend class Packet; public: /** * A destructor for this class. Frees the data if it was allocated by the layer constructor (see isAllocatedToPacket() for more info) */ virtual ~Layer(); /** * @return A pointer to the next layer in the protocol stack or NULL if the layer is the last one */ Layer* getNextLayer() const { return m_NextLayer; } /** * @return A pointer to the previous layer in the protocol stack or NULL if the layer is the first one */ Layer* getPrevLayer() const { return m_PrevLayer; } /** * @return The protocol enum */ ProtocolType getProtocol() const { return m_Protocol; } /** * @return A pointer to the layer raw data. In most cases it'll be a pointer to the first byte of the header */ uint8_t* getData() const { return m_Data; } /** * @return The length in bytes of the data from the first byte of the header until the end of the packet */ size_t getDataLen() const { return m_DataLen; } /** * @return A pointer for the layer payload, meaning the first byte after the header */ uint8_t* getLayerPayload() const { return m_Data + getHeaderLen(); } /** * @return The size in bytes of the payload */ size_t getLayerPayloadSize() const { return m_DataLen - getHeaderLen(); } /** * Raw data in layers can come from one of sources: * 1. from an existing packet - this is the case when parsing packets received from files or the network. In this case the data was * already allocated by someone else, and layer only holds the pointer to the relevant place inside this data * 2. when creating packets, data is allocated when layer is created. In this case the layer is responsible for freeing it as well * * @return Returns true if the data was allocated by an external source (a packet) or false if it was allocated by the layer itself */ bool isAllocatedToPacket() const { return m_Packet != NULL; } /** * Copy the raw data of this layer to another array * @param[out] toArr The destination byte array */ void copyData(uint8_t* toArr) const; // implement abstract methods uint8_t* getDataPtr(size_t offset = 0) const { return (uint8_t*)(m_Data + offset); } // abstract methods /** * Each layer is responsible for parsing the next layer */ virtual void parseNextLayer() = 0; /** * @return The header length in bytes */ virtual size_t getHeaderLen() const = 0; /** * Each layer can compute field values automatically using this method. This is an abstract method */ virtual void computeCalculateFields() = 0; /** * @return A string representation of the layer most important data (should look like the layer description in Wireshark) */ virtual std::string toString() const = 0; /** * @return The OSI Model layer this protocol belongs to */ virtual OsiModelLayer getOsiModelLayer() const = 0; 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(NULL), m_DataLen(0), m_Packet(NULL), m_Protocol(UnknownProtocol), m_NextLayer(NULL), m_PrevLayer(NULL), m_IsAllocatedInPacket(false) { } Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : m_Data(data), m_DataLen(dataLen), m_Packet(packet), m_Protocol(UnknownProtocol), m_NextLayer(NULL), m_PrevLayer(prevLayer), m_IsAllocatedInPacket(false) {} // Copy c'tor Layer(const Layer& other); Layer& operator=(const Layer& other); void setNextLayer(Layer* nextLayer) { m_NextLayer = nextLayer; } void setPrevLayer(Layer* prevLayer) { m_PrevLayer = prevLayer; } virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend); virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten); }; } // namespace pcpp inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer &layer) { os << layer.toString(); return os; } #endif /* PACKETPP_LAYER */