280 lines
8.4 KiB
C++
280 lines
8.4 KiB
C++
#ifndef PACKETPP_IPV6_LAYER
|
|
#define PACKETPP_IPV6_LAYER
|
|
|
|
#include "Layer.h"
|
|
#include "IPLayer.h"
|
|
#include "IPv6Extensions.h"
|
|
#include "IpAddress.h"
|
|
|
|
/// @file
|
|
|
|
/**
|
|
* \namespace pcpp
|
|
* \brief The main namespace for the PcapPlusPlus lib
|
|
*/
|
|
namespace pcpp
|
|
{
|
|
|
|
/**
|
|
* @struct ip6_hdr
|
|
* Represents IPv6 protocol header
|
|
*/
|
|
#pragma pack(push, 1)
|
|
struct ip6_hdr
|
|
{
|
|
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
|
/** Traffic class */
|
|
uint8_t trafficClass:4,
|
|
/** IP version number, has the value of 6 for IPv6 */
|
|
ipVersion:4;
|
|
#else
|
|
/** IP version number, has the value of 6 for IPv6 */
|
|
uint8_t ipVersion:4,
|
|
/** Traffic class */
|
|
trafficClass:4;
|
|
#endif
|
|
/** Flow label */
|
|
uint8_t flowLabel[3];
|
|
/** The size of the payload in octets, including any extension headers */
|
|
uint16_t payloadLength;
|
|
/** Specifies the type of the next header (protocol). Must be one of ::IPProtocolTypes */
|
|
uint8_t nextHeader;
|
|
/** Replaces the time to live field of IPv4 */
|
|
uint8_t hopLimit;
|
|
/** Source address */
|
|
uint8_t ipSrc[16];
|
|
/** Destination address */
|
|
uint8_t ipDst[16];
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
|
|
/**
|
|
* @class IPv6Layer
|
|
* Represents an IPv6 protocol layer
|
|
*/
|
|
class IPv6Layer : public Layer, public IPLayer
|
|
{
|
|
public:
|
|
/**
|
|
* A constructor that creates the layer from an existing packet raw data
|
|
* @param[in] data A pointer to the raw data (will be casted to @ref ip6_hdr)
|
|
* @param[in] dataLen Size of the data in bytes
|
|
* @param[in] prevLayer A pointer to the previous layer
|
|
* @param[in] packet A pointer to the Packet instance where layer will be stored in
|
|
*/
|
|
IPv6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
|
|
|
/**
|
|
* A constructor that allocates a new IPv6 header with empty fields
|
|
*/
|
|
IPv6Layer();
|
|
|
|
/**
|
|
* A constructor that allocates a new IPv6 header with source and destination IPv6 addresses
|
|
* @param[in] srcIP Source IPv6 address
|
|
* @param[in] dstIP Destination IPv6 address
|
|
*/
|
|
IPv6Layer(const IPv6Address& srcIP, const IPv6Address& dstIP);
|
|
|
|
/**
|
|
* A copy constructor that copies the entire header from the other IPv6Layer (including IPv6 extensions)
|
|
*/
|
|
IPv6Layer(const IPv6Layer& other);
|
|
|
|
/**
|
|
* A destructor for this layer
|
|
*/
|
|
~IPv6Layer();
|
|
|
|
/**
|
|
* An assignment operator that first delete all data from current layer and then copy the entire header from the other IPv6Layer (including IPv6 extensions)
|
|
*/
|
|
IPv6Layer& operator=(const IPv6Layer& other);
|
|
|
|
/**
|
|
* Get a pointer to the IPv6 header. Notice this points directly to the data, so every change will change the actual packet data
|
|
* @return A pointer to the @ref ip6_hdr
|
|
*/
|
|
ip6_hdr* getIPv6Header() const { return (ip6_hdr*)m_Data; }
|
|
|
|
/**
|
|
* Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv6Address(),
|
|
* but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses
|
|
* @return An IPAddress containing the source address
|
|
*/
|
|
IPAddress getSrcIPAddress() const { return getSrcIPv6Address(); }
|
|
|
|
/**
|
|
* Get the source IP address in the form of IPv6Address
|
|
* @return An IPv6Address containing the source address
|
|
*/
|
|
IPv6Address getSrcIPv6Address() const { return getIPv6Header()->ipSrc; }
|
|
|
|
/**
|
|
* Set the source IP address
|
|
* @param[in] ipAddr The IP address to set
|
|
*/
|
|
void setSrcIPv6Address(const IPv6Address& ipAddr) { ipAddr.copyTo(getIPv6Header()->ipSrc); }
|
|
|
|
|
|
/**
|
|
* Set the dest IP address
|
|
* @param[in] ipAddr The IP address to set
|
|
*/
|
|
void setDstIPv6Address(const IPv6Address& ipAddr) { ipAddr.copyTo(getIPv6Header()->ipDst); }
|
|
|
|
/**
|
|
* Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv6Address(),
|
|
* but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses
|
|
* @return An IPAddress containing the destination address
|
|
*/
|
|
IPAddress getDstIPAddress() const { return getDstIPv6Address(); }
|
|
|
|
/**
|
|
* Get the destination IP address in the form of IPv6Address
|
|
* @return An IPv6Address containing the destination address
|
|
*/
|
|
IPv6Address getDstIPv6Address() const { return getIPv6Header()->ipDst; }
|
|
|
|
/**
|
|
* @return Number of IPv6 extensions in this layer
|
|
*/
|
|
size_t getExtensionCount() const;
|
|
|
|
/**
|
|
* A templated getter for an IPv6 extension of a type TIPv6Extension. TIPv6Extension has to be one of the supported IPv6 extensions,
|
|
* meaning a class that inherits IPv6Extension. If the requested extension type isn't found NULL is returned
|
|
* @return A pointer to the extension instance or NULL if the requested extension type isn't found
|
|
*/
|
|
template<class TIPv6Extension>
|
|
TIPv6Extension* getExtensionOfType() const;
|
|
|
|
/**
|
|
* Add a new extension of type TIPv6Extension to the layer. This is a templated method and TIPv6Extension has to be one of
|
|
* the supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the extension is added successfully a pointer
|
|
* to the newly added extension object is returned, otherwise NULL is returned
|
|
* @param[in] extensionHeader The extension object to add. Notice the object passed here is read-only, meaning its data is copied
|
|
* but the object itself isn't modified
|
|
* @return If the extension is added successfully a pointer to the newly added extension object is returned. Otherwise NULL is
|
|
* returned
|
|
*/
|
|
template<class TIPv6Extension>
|
|
TIPv6Extension* addExtension(const TIPv6Extension& extensionHeader);
|
|
|
|
/**
|
|
* Remove all IPv6 extensions in this layer
|
|
*/
|
|
void removeAllExtensions();
|
|
|
|
/**
|
|
* @return True if this packet is an IPv6 fragment, meaning if it has an IPv6FragmentationHeader extension
|
|
*/
|
|
bool isFragment() const;
|
|
|
|
/**
|
|
* The static method makes validation of input data
|
|
* @param[in] data The pointer to the beginning of byte stream of IP packet
|
|
* @param[in] dataLen The length of byte stream
|
|
* @return True if the data is valid and can represent the IPv6 packet
|
|
*/
|
|
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
|
|
|
|
|
// implement abstract methods
|
|
|
|
/**
|
|
* Currently identifies the following next layers:
|
|
* - UdpLayer
|
|
* - TcpLayer
|
|
* - IPv4Layer (IP-in-IP)
|
|
* - IPv6Layer (IP-in-IP)
|
|
* - GreLayer
|
|
* - AuthenticationHeaderLayer (IPSec)
|
|
* - ESPLayer (IPSec)
|
|
*
|
|
* Otherwise sets PayloadLayer
|
|
*/
|
|
void parseNextLayer();
|
|
|
|
/**
|
|
* @return Size of @ref ip6_hdr
|
|
*/
|
|
size_t getHeaderLen() const { return sizeof(ip6_hdr) + m_ExtensionsLen; }
|
|
|
|
/**
|
|
* Calculate the following fields:
|
|
* - ip6_hdr#payloadLength = size of payload (all data minus header size)
|
|
* - ip6_hdr#ipVersion = 6
|
|
* - ip6_hdr#nextHeader = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP
|
|
*/
|
|
void computeCalculateFields();
|
|
|
|
std::string toString() const;
|
|
|
|
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
|
|
|
private:
|
|
void initLayer();
|
|
void parseExtensions();
|
|
void deleteExtensions();
|
|
|
|
IPv6Extension* m_FirstExtension;
|
|
IPv6Extension* m_LastExtension;
|
|
size_t m_ExtensionsLen;
|
|
};
|
|
|
|
|
|
template<class TIPv6Extension>
|
|
TIPv6Extension* IPv6Layer::getExtensionOfType() const
|
|
{
|
|
IPv6Extension* curExt = m_FirstExtension;
|
|
while (curExt != NULL && dynamic_cast<TIPv6Extension*>(curExt) == NULL)
|
|
curExt = curExt->getNextHeader();
|
|
|
|
return (TIPv6Extension*)curExt;
|
|
}
|
|
|
|
template<class TIPv6Extension>
|
|
TIPv6Extension* IPv6Layer::addExtension(const TIPv6Extension& extensionHeader)
|
|
{
|
|
int offsetToAddHeader = (int)getHeaderLen();
|
|
if (!extendLayer(offsetToAddHeader, extensionHeader.getExtensionLen()))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
TIPv6Extension* newHeader = new TIPv6Extension(this, (size_t)offsetToAddHeader);
|
|
(*newHeader) = extensionHeader;
|
|
|
|
if (m_FirstExtension != NULL)
|
|
{
|
|
newHeader->getBaseHeader()->nextHeader = m_LastExtension->getBaseHeader()->nextHeader;
|
|
m_LastExtension->getBaseHeader()->nextHeader = newHeader->getExtensionType();
|
|
m_LastExtension->setNextHeader(newHeader);
|
|
m_LastExtension = newHeader;
|
|
}
|
|
else
|
|
{
|
|
m_FirstExtension = newHeader;
|
|
m_LastExtension = newHeader;
|
|
newHeader->getBaseHeader()->nextHeader = getIPv6Header()->nextHeader;
|
|
getIPv6Header()->nextHeader = newHeader->getExtensionType();
|
|
}
|
|
|
|
m_ExtensionsLen += newHeader->getExtensionLen();
|
|
|
|
return newHeader;
|
|
}
|
|
|
|
// implementation of inline methods
|
|
|
|
bool IPv6Layer::isDataValid(const uint8_t* data, size_t dataLen)
|
|
{
|
|
return dataLen >= sizeof(ip6_hdr);
|
|
}
|
|
|
|
} // namespace pcpp
|
|
|
|
#endif /* PACKETPP_IPV6_LAYER */
|