libraries/pcappp/include/pcapplusplus/Layer.h

198 lines
6.3 KiB
C++

#ifndef PACKETPP_LAYER
#define PACKETPP_LAYER
#include <stdint.h>
#include <stdio.h>
#include "ProtocolType.h"
#include <string>
/// @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 proprties 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 */