- add Pcap++ Windows build
This commit is contained in:
140
pcappp/include/pcapplusplus/ArpLayer.h
Normal file
140
pcappp/include/pcapplusplus/ArpLayer.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef PACKETPP_ARP_LAYER
|
||||
#define PACKETPP_ARP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "IpAddress.h"
|
||||
#include "MacAddress.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct arphdr
|
||||
* Represents an ARP protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct arphdr
|
||||
{
|
||||
/** Hardware type (HTYPE) */
|
||||
uint16_t hardwareType;
|
||||
/** Protocol type (PTYPE). The permitted PTYPE values share a numbering space with those for EtherType */
|
||||
uint16_t protocolType;
|
||||
/** Hardware address length (HLEN). For IPv4, this has the value 0x0800 */
|
||||
uint8_t hardwareSize;
|
||||
/** Protocol length (PLEN). Length (in octets) of addresses used in the upper layer protocol. (The upper layer protocol specified in PTYPE.) IPv4 address size is 4 */
|
||||
uint8_t protocolSize;
|
||||
/** Specifies the operation that the sender is performing: 1 (::ARP_REQUEST) for request, 2 (::ARP_REPLY) for reply */
|
||||
uint16_t opcode;
|
||||
/** Sender hardware address (SHA) */
|
||||
uint8_t senderMacAddr[6];
|
||||
/** Sender protocol address (SPA) */
|
||||
uint32_t senderIpAddr;
|
||||
/** Target hardware address (THA) */
|
||||
uint8_t targetMacAddr[6];
|
||||
/** Target protocol address (TPA) */
|
||||
uint32_t targetIpAddr;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* An enum for ARP message type
|
||||
*/
|
||||
enum ArpOpcode
|
||||
{
|
||||
ARP_REQUEST = 0x0001, ///< ARP request
|
||||
ARP_REPLY = 0x0002 ///< ARP reply (response)
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ArpLayer
|
||||
* Represents an ARP protocol layer. Currently only IPv4 ARP messages are supported
|
||||
*/
|
||||
class ArpLayer : public Layer
|
||||
{
|
||||
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 arphdr)
|
||||
* @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
|
||||
*/
|
||||
ArpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ARP; m_DataLen = sizeof(arphdr); }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new ARP header
|
||||
* @param[in] opCode ARP message type (ARP request or ARP reply)
|
||||
* @param[in] senderMacAddr The sender MAC address (will be put in arphdr#senderMacAddr)
|
||||
* @param[in] targetMacAddr The target MAC address (will be put in arphdr#targetMacAddr)
|
||||
* @param[in] senderIpAddr The sender IP address (will be put in arphdr#senderIpAddr)
|
||||
* @param[in] targetIpAddr The target IP address (will be put in arphdr#targetIpAddr)
|
||||
*/
|
||||
ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr);
|
||||
|
||||
~ArpLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the ARP header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref arphdr
|
||||
*/
|
||||
inline arphdr* getArpHeader() const { return (arphdr*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get the sender hardware address (SHA) in the form of MacAddress
|
||||
* @return A MacAddress containing the sender hardware address (SHA)
|
||||
*/
|
||||
inline MacAddress getSenderMacAddress() const { return MacAddress(getArpHeader()->senderMacAddr); }
|
||||
|
||||
/**
|
||||
* Get the target hardware address (THA) in the form of MacAddress
|
||||
* @return A MacAddress containing the target hardware address (THA)
|
||||
*/
|
||||
inline MacAddress getTargetMacAddress() const { return MacAddress(getArpHeader()->targetMacAddr); }
|
||||
|
||||
/**
|
||||
* Get the sender protocol address (SPA) in the form of IPv4Address
|
||||
* @return An IPv4Address containing the sender protocol address (SPA)
|
||||
*/
|
||||
inline IPv4Address getSenderIpAddr() const { return getArpHeader()->senderIpAddr; }
|
||||
|
||||
/**
|
||||
* Get the target protocol address (TPA) in the form of IPv4Address
|
||||
* @return An IPv4Address containing the target protocol address (TPA)
|
||||
*/
|
||||
inline IPv4Address getTargetIpAddr() const { return getArpHeader()->targetIpAddr; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (ArpLayer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return The size of @ref arphdr
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(arphdr); }
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - @ref arphdr#hardwareType = Ethernet (1)
|
||||
* - @ref arphdr#hardwareSize = 6
|
||||
* - @ref arphdr#protocolType = ETHERTYPE_IP (assume IPv4 over ARP)
|
||||
* - @ref arphdr#protocolSize = 4 (assume IPv4 over ARP)
|
||||
* - if it's an ARP request: @ref arphdr#targetMacAddr = MacAddress("00:00:00:00:00:00")
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
#endif /* PACKETPP_ARP_LAYER */
|
||||
670
pcappp/include/pcapplusplus/BgpLayer.h
Normal file
670
pcappp/include/pcapplusplus/BgpLayer.h
Normal file
@@ -0,0 +1,670 @@
|
||||
#ifndef PACKETPP_BGP_LAYER
|
||||
#define PACKETPP_BGP_LAYER
|
||||
|
||||
#include <vector>
|
||||
#include "Layer.h"
|
||||
#include "IpAddress.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains classes for parsing, creating and editing Border Gateway Protocol (BGP) version 4 packets.
|
||||
* It contains an abstract class named BgpLayer which has common functionality and 5 inherited classes that
|
||||
* represent the different BGP message types: OPEN, UPDATE, NOTIFICATION, KEEPALIVE and ROUTE-REFRESH.
|
||||
* Each of these classes contains unique functionality for parsing. creating and editing of these message.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class BgpLayer
|
||||
* Represents Border Gateway Protocol (BGP) v4 protocol layer. This is an abstract class that cannot be instantiated,
|
||||
* and contains functionality which is common to all BGP message types.
|
||||
*/
|
||||
class BgpLayer : public Layer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum representing BGP message types
|
||||
*/
|
||||
enum BgpMessageType
|
||||
{
|
||||
/** BGP OPEN message */
|
||||
Open = 1,
|
||||
/** BGP UPDATE message */
|
||||
Update = 2,
|
||||
/** BGP NOTIFICATION message */
|
||||
Notification = 3,
|
||||
/** BGP KEEPALIVE message */
|
||||
Keepalive = 4,
|
||||
/** BGP ROUTE-REFRESH message */
|
||||
RouteRefresh = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct bgp_common_header
|
||||
* Represents the common fields of a BGP 4 message
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct bgp_common_header
|
||||
{
|
||||
/** 16-octet marker */
|
||||
uint8_t marker[16];
|
||||
/** Total length of the message, including the header */
|
||||
uint16_t length;
|
||||
/** BGP message type */
|
||||
uint8_t messageType;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @return BGP message type
|
||||
*/
|
||||
virtual BgpMessageType getBgpMessageType() const = 0;
|
||||
|
||||
/**
|
||||
* @return BGP message type as string. Return value can be one of the following:
|
||||
* "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", "Unknown"
|
||||
*/
|
||||
std::string getMessageTypeAsString() const;
|
||||
|
||||
/**
|
||||
* A static method that checks whether a source or dest port match those associated with the BGP protocol
|
||||
* @param[in] portSrc Source port number to check
|
||||
* @param[in] portDst Dest port number to check
|
||||
* @return True if the source or dest port match those associated with the BGP protocol
|
||||
*/
|
||||
static bool isBgpPort(uint16_t portSrc, uint16_t portDst) { return portSrc == 179 || portDst == 179; }
|
||||
|
||||
/**
|
||||
* A method that creates a BGP layer from packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
* @return A newly allocated BGP layer of one of the following types (according to the message type):
|
||||
* BgpOpenMessageLayer, BgpUpdateMessageLayer, BgpNotificationMessageLayer, BgpKeepaliveMessageLayer,
|
||||
* BgpRouteRefreshMessageLayer
|
||||
*/
|
||||
static BgpLayer* parseBgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size of the BGP message
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
/**
|
||||
* Multiple BGP messages can reside in a single packet, and the only layer that can come after a BGP message
|
||||
* is another BGP message. This method checks for remaining data and parses it as another BGP layer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
/**
|
||||
* Calculates the basic BGP fields:
|
||||
* - Set marker to all ones
|
||||
* - Set message type value
|
||||
* - Set message length
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
protected:
|
||||
|
||||
// protected c'tors, this class cannot be instantiated by users
|
||||
BgpLayer() {}
|
||||
BgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = BGP; }
|
||||
|
||||
bgp_common_header* getBasicHeader() const { return (bgp_common_header*)m_Data; }
|
||||
|
||||
void setBgpFields(size_t messageLen = 0);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class BgpOpenMessageLayer
|
||||
* Represents a BGP v4 OPEN message
|
||||
*/
|
||||
class BgpOpenMessageLayer : public BgpLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct bgp_open_message
|
||||
* BGP OPEN message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct bgp_open_message : bgp_common_header
|
||||
{
|
||||
/** BGP version number */
|
||||
uint8_t version;
|
||||
/** Autonomous System number of the sender */
|
||||
uint16_t myAutonomousSystem;
|
||||
/** The number of seconds the sender proposes for the value of the Hold Timer */
|
||||
uint16_t holdTime;
|
||||
/** BGP Identifier of the sender */
|
||||
uint32_t bgpId;
|
||||
/** The total length of the Optional Parameters field */
|
||||
uint8_t optionalParameterLength;
|
||||
} bgp_open_message;
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @struct optional_parameter
|
||||
* A structure that represents BGP OPEN message optional parameters
|
||||
*/
|
||||
struct optional_parameter
|
||||
{
|
||||
/** Parameter type */
|
||||
uint8_t type;
|
||||
/** Parameter length */
|
||||
uint8_t length;
|
||||
/** Parameter data */
|
||||
uint8_t value[32];
|
||||
|
||||
/**
|
||||
* A default c'tor that zeroes all data
|
||||
*/
|
||||
optional_parameter() {}
|
||||
|
||||
/**
|
||||
* A c'tor that initializes the values of the struct
|
||||
* @param[in] typeVal Parameter type value
|
||||
* @param[in] valueAsHexString Parameter data as hex string. The length field will be set accordingly.
|
||||
* If this parameter is not a valid hex string the data will remain zeroed and length will be also zero
|
||||
*/
|
||||
optional_parameter(uint8_t typeVal, std::string valueAsHexString);
|
||||
};
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
BgpOpenMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP OPEN message
|
||||
* @param[in] myAutonomousSystem The Autonomous System number of the sender
|
||||
* @param[in] holdTime The number of seconds the sender proposes for the value of the Hold Timer
|
||||
* @param[in] bgpId The BGP Identifier of the sender
|
||||
* @param[in] optionalParams A vector of optional parameters. This parameter is optional and if not provided no parameters will be
|
||||
* set on the message
|
||||
*/
|
||||
BgpOpenMessageLayer(uint16_t myAutonomousSystem, uint16_t holdTime, const IPv4Address& bgpId,
|
||||
const std::vector<optional_parameter>& optionalParams = std::vector<optional_parameter>());
|
||||
|
||||
/**
|
||||
* Get a pointer to the open message data. Notice this points directly to the data, so any change will modify the actual packet data
|
||||
* @return A pointer to a bgp_open_message structure containing the data
|
||||
*/
|
||||
bgp_open_message* getOpenMsgHeader() const { return (bgp_open_message*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The BGP identifier as IPv4Address object
|
||||
*/
|
||||
IPv4Address getBgpId() const { return IPv4Address(getOpenMsgHeader()->bgpId); }
|
||||
|
||||
/**
|
||||
* Set the BGP identifier
|
||||
* @param[in] newBgpId BGP identifier to set. If value is not a valid IPv4 address it won't be set
|
||||
*/
|
||||
void setBgpId(const IPv4Address& newBgpId);
|
||||
|
||||
/**
|
||||
* Get a vector of the optional parameters in the message
|
||||
* @param[out] optionalParameters The vector where the optional parameters will be written to. This method doesn't remove any
|
||||
* existing data on this vector before pushing data to it
|
||||
*/
|
||||
void getOptionalParameters(std::vector<optional_parameter>& optionalParameters);
|
||||
|
||||
/**
|
||||
* @return The length in [bytes] of the optional parameters data in the message
|
||||
*/
|
||||
size_t getOptionalParametersLength();
|
||||
|
||||
/**
|
||||
* Set optional parameters in the message. This method will override all existing optional parameters currently in the message.
|
||||
* If the input is an empty vector all optional parameters will be cleared. This method automatically sets the
|
||||
* bgp_common_header#length and the bgp_open_message#optionalParameterLength fields on the message
|
||||
* @param[in] optionalParameters A vector of new optional parameters to set in the message
|
||||
* @return True if all optional parameters were set successfully or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool setOptionalParameters(const std::vector<optional_parameter>& optionalParameters);
|
||||
|
||||
/**
|
||||
* Clear all optional parameters currently in the message. This is equivalent to calling setOptionalParameters() with an empty
|
||||
* vector as a parameter
|
||||
* @return True if all optional parameters were successfully cleared or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool clearOptionalParameters();
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
BgpMessageType getBgpMessageType() const { return BgpLayer::Open; }
|
||||
|
||||
private:
|
||||
|
||||
size_t optionalParamsToByteArray(const std::vector<optional_parameter>& optionalParams, uint8_t* resultByteArr, size_t maxByteArrSize);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class BgpUpdateMessageLayer
|
||||
* Represents a BGP v4 UPDATE message
|
||||
*/
|
||||
class BgpUpdateMessageLayer : public BgpLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct prefix_and_ip
|
||||
* A structure that contains IPv4 address and IP address mask (prefix) information.
|
||||
* It's used to represent BGP Withdrawn Routes and Network Layer Reachability Information (NLRI)
|
||||
*/
|
||||
struct prefix_and_ip
|
||||
{
|
||||
/** IPv4 address mask, must contain one of the values: 8, 16, 24, 32 */
|
||||
uint8_t prefix;
|
||||
/** IPv4 address */
|
||||
IPv4Address ipAddr;
|
||||
|
||||
/**
|
||||
* A default c'tor that zeroes all data
|
||||
*/
|
||||
prefix_and_ip(): prefix(0), ipAddr(IPv4Address::Zero) {}
|
||||
|
||||
/**
|
||||
* A c'tor that initializes the values of the struct
|
||||
* @param[in] prefixVal IPv4 address mask value
|
||||
* @param[in] ipAddrVal IPv4 address
|
||||
*/
|
||||
prefix_and_ip(uint8_t prefixVal, const std::string& ipAddrVal): prefix(prefixVal), ipAddr(ipAddrVal) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct path_attribute
|
||||
* A structure that represents BGP OPEN message Path Attributes information
|
||||
*/
|
||||
struct path_attribute
|
||||
{
|
||||
/** Path attribute flags */
|
||||
uint8_t flags;
|
||||
/** Path attribute type */
|
||||
uint8_t type;
|
||||
/** Path attribute length */
|
||||
uint8_t length;
|
||||
/** Path attribute data. Max supported data length is 32 bytes */
|
||||
uint8_t data[32];
|
||||
|
||||
/**
|
||||
* A default c'tor that zeroes all data
|
||||
*/
|
||||
path_attribute() {}
|
||||
|
||||
/**
|
||||
* A c'tor that initializes the values of the struct
|
||||
* @param[in] flagsVal Path attribute flags value
|
||||
* @param[in] typeVal Path attribute type value
|
||||
* @param[in] dataAsHexString Path attribute data as hex string. The path_attribute#length field will be set accordingly.
|
||||
* If this parameter is not a valid hex string the data will remain zeroed and length will be also set to zero
|
||||
*/
|
||||
path_attribute(uint8_t flagsVal, uint8_t typeVal, std::string dataAsHexString);
|
||||
};
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
BgpUpdateMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP UPDATE message
|
||||
* @param[in] withdrawnRoutes A vector of withdrawn routes data. If left empty (which is the default value) no withdrawn route information will be written to the message
|
||||
* @param[in] pathAttributes A vector of path attributes data. If left empty (which is the default value) no path attribute information will be written to the message
|
||||
* @param[in] nlri A vector of network layer reachability data. If left empty (which is the default value) no reachability information will be written to the message
|
||||
*/
|
||||
BgpUpdateMessageLayer(
|
||||
const std::vector<prefix_and_ip>& withdrawnRoutes = std::vector<prefix_and_ip>(),
|
||||
const std::vector<path_attribute>& pathAttributes = std::vector<path_attribute>(),
|
||||
const std::vector<prefix_and_ip>& nlri = std::vector<prefix_and_ip>());
|
||||
|
||||
/**
|
||||
* Get a pointer to the basic BGP message data. Notice this points directly to the data, so any change will modify the actual packet data
|
||||
* @return A pointer to a bgp_common_header structure containing the data
|
||||
*/
|
||||
bgp_common_header* getBasicMsgHeader() const { return (bgp_common_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The size in [bytes] of the Withdrawn Routes data
|
||||
*/
|
||||
size_t getWithdrawnRoutesLength() const;
|
||||
|
||||
/**
|
||||
* Get a vector of the Withdrawn Routes currently in the message
|
||||
* @param[out] withdrawnRoutes A reference to a vector the Withdrawn Routes data will be written to
|
||||
*/
|
||||
void getWithdrawnRoutes(std::vector<prefix_and_ip>& withdrawnRoutes);
|
||||
|
||||
/**
|
||||
* Set Withdrawn Routes in this message. This method will override any existing Withdrawn Routes in the message.
|
||||
* If the input is an empty vector all Withdrawn Routes will be removed. This method automatically sets the
|
||||
* bgp_common_header#length and the Withdrawn Routes length fields in the message
|
||||
* @param[in] withdrawnRoutes New Withdrawn Routes to set in the message
|
||||
* @return True if all Withdrawn Routes were set successfully or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool setWithdrawnRoutes(const std::vector<prefix_and_ip>& withdrawnRoutes);
|
||||
|
||||
/**
|
||||
* Clear all Withdrawn Routes data currently in the message. This is equivalent to calling setWithdrawnRoutes() with an empty
|
||||
* vector as a parameter
|
||||
* @return True if all Withdrawn Routes were successfully cleared or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool clearWithdrawnRoutes();
|
||||
|
||||
/**
|
||||
* @return The size in [bytes] of the Path Attributes data
|
||||
*/
|
||||
size_t getPathAttributesLength() const;
|
||||
|
||||
/**
|
||||
* Get a vector of the Path Attributes currently in the message
|
||||
* @param[out] pathAttributes A reference to a vector the Path Attributes data will be written to
|
||||
*/
|
||||
void getPathAttributes(std::vector<path_attribute>& pathAttributes);
|
||||
|
||||
/**
|
||||
* Set Path Attributes in this message. This method will override any existing Path Attributes in the message.
|
||||
* If the input is an empty vector all Path Attributes will be removed. This method automatically sets the
|
||||
* bgp_common_header#length and the Path Attributes length fields in the message
|
||||
* @param[in] pathAttributes New Path Attributes to set in the message
|
||||
* @return True if all Path Attributes were set successfully or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool setPathAttributes(const std::vector<path_attribute>& pathAttributes);
|
||||
|
||||
/**
|
||||
* Clear all Path Attributes data currently in the message. This is equivalent to calling setPathAttributes() with an empty
|
||||
* vector as a parameter
|
||||
* @return True if all Path Attributes were successfully cleared or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool clearPathAttributes();
|
||||
|
||||
/**
|
||||
* @return The size in [bytes] of the Network Layer Reachability Info
|
||||
*/
|
||||
size_t getNetworkLayerReachabilityInfoLength() const;
|
||||
|
||||
/**
|
||||
* Get a vector of the Network Layer Reachability Info currently in the message
|
||||
* @param[out] nlri A reference to a vector the NLRI data will be written to
|
||||
*/
|
||||
void getNetworkLayerReachabilityInfo(std::vector<prefix_and_ip>& nlri);
|
||||
|
||||
/**
|
||||
* Set NLRI data in this message. This method will override any existing NLRI data in the message.
|
||||
* If the input is an empty vector all NLRI data will be removed. This method automatically sets the
|
||||
* bgp_common_header#length field in the message
|
||||
* @param[in] nlri New NLRI data to set in the message
|
||||
* @return True if all NLRI data was set successfully or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool setNetworkLayerReachabilityInfo(const std::vector<prefix_and_ip>& nlri);
|
||||
|
||||
/**
|
||||
* Clear all NLRI data currently in the message. This is equivalent to calling setNetworkLayerReachabilityInfo() with an empty
|
||||
* vector as a parameter
|
||||
* @return True if all NLRI were successfully cleared or false otherwise. In case of an error an appropriate message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool clearNetworkLayerReachabilityInfo();
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
BgpMessageType getBgpMessageType() const { return BgpLayer::Update; }
|
||||
|
||||
private:
|
||||
|
||||
void parsePrefixAndIPData(uint8_t* dataPtr, size_t dataLen, std::vector<prefix_and_ip>& result);
|
||||
|
||||
size_t prefixAndIPDataToByteArray(const std::vector<prefix_and_ip>& prefixAndIpData, uint8_t* resultByteArr, size_t maxByteArrSize);
|
||||
|
||||
size_t pathAttributesToByteArray(const std::vector<path_attribute>& pathAttributes, uint8_t* resultByteArr, size_t maxByteArrSize);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class BgpNotificationMessageLayer
|
||||
* Represents a BGP v4 NOTIFICATION message
|
||||
*/
|
||||
class BgpNotificationMessageLayer : public BgpLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct bgp_notification_message
|
||||
* BGP NOTIFICATION message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct bgp_notification_message : bgp_common_header
|
||||
{
|
||||
/** BGP notification error code */
|
||||
uint8_t errorCode;
|
||||
/** BGP notification error sub-code */
|
||||
uint8_t errorSubCode;
|
||||
} bgp_notification_message;
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
BgpNotificationMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP NOTIFICATION message
|
||||
* @param[in] errorCode BGP notification error code
|
||||
* @param[in] errorSubCode BGP notification error sub code
|
||||
*/
|
||||
BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode);
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP Notification message
|
||||
* @param[in] errorCode BGP notification error code
|
||||
* @param[in] errorSubCode BGP notification error sub code
|
||||
* @param[in] notificationData A byte array that contains the notification data
|
||||
* @param[in] notificationDataLen The size of the byte array that contains the notification data
|
||||
*/
|
||||
BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, size_t notificationDataLen);
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP Notification message
|
||||
* @param[in] errorCode BGP notification error code
|
||||
* @param[in] errorSubCode BGP notification error sub code
|
||||
* @param[in] notificationData A hex string that contains the notification data. This string will be converted to a byte array that will be
|
||||
* added to the message. If the input isn't a valid hex string notification data will remain empty and an error will be printed to log
|
||||
*/
|
||||
BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const std::string& notificationData);
|
||||
|
||||
/**
|
||||
* Get a pointer to the notification message data. Notice this points directly to the data, so any change will modify the actual packet data
|
||||
* @return A pointer to a bgp_notification_message structure containing the data
|
||||
*/
|
||||
bgp_notification_message* getNotificationMsgHeader() const { return (bgp_notification_message*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The size in [bytes] of the notification data. Notification data is a variable-length field used to diagnose the reason for
|
||||
* the BGP NOTIFICATION
|
||||
*/
|
||||
size_t getNotificationDataLen() const;
|
||||
|
||||
/**
|
||||
* @return A pointer to the notification data. Notification data is a variable-length field used to diagnose the reason for
|
||||
* the BGP NOTIFICATION
|
||||
*/
|
||||
uint8_t* getNotificationData() const;
|
||||
|
||||
/**
|
||||
* @return A hex string which represents the notification data. Notification data is a variable-length field used to diagnose the reason for
|
||||
* the BGP NOTIFICATION
|
||||
*/
|
||||
std::string getNotificationDataAsHexString() const;
|
||||
|
||||
/**
|
||||
* Set the notification data. This method will extend or shorten the existing layer to include the new notification data.
|
||||
* If newNotificationData is NULL or newNotificationDataLen is zero then notification data will be set to none.
|
||||
* @param[in] newNotificationData A byte array containing the new notification data
|
||||
* @param[in] newNotificationDataLen The size of the byte array
|
||||
* @return True if notification data was set successfully or false if any error occurred. In case of an error an appropriate
|
||||
* error message will be printed to log
|
||||
*/
|
||||
bool setNotificationData(const uint8_t* newNotificationData, size_t newNotificationDataLen);
|
||||
|
||||
/**
|
||||
* Set the notification data. This method will extend or shorten the existing layer to include the new notification data.
|
||||
* If newNotificationDataAsHexString is an empty string then notification data will be set to none.
|
||||
* @param[in] newNotificationDataAsHexString A hex string representing the new notification data. If the string is not a valid hex string
|
||||
* no data will be changed and an error will be returned
|
||||
* @return True if notification data was set successfully or false if any error occurred or if the string is not a valid hex string.
|
||||
* In case of an error an appropriate error message will be printed to log
|
||||
*/
|
||||
bool setNotificationData(const std::string& newNotificationDataAsHexString);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
BgpMessageType getBgpMessageType() const { return BgpLayer::Notification; }
|
||||
|
||||
private:
|
||||
|
||||
void initMessageData(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, size_t notificationDataLen);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class BgpKeepaliveMessageLayer
|
||||
* Represents a BGP v4 KEEPALIVE message
|
||||
*/
|
||||
class BgpKeepaliveMessageLayer : public BgpLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @typedef bgp_keepalive_message
|
||||
* BGP KEEPALIVE message structure
|
||||
*/
|
||||
typedef bgp_common_header bgp_keepalive_message;
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
BgpKeepaliveMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP KEEPALIVE message
|
||||
*/
|
||||
BgpKeepaliveMessageLayer();
|
||||
|
||||
/**
|
||||
* Get a pointer to the KeepAlive message data. Notice this points directly to the data, so any change will modify the actual packet data
|
||||
* @return A pointer to a bgp_keepalive_message structure containing the data
|
||||
*/
|
||||
bgp_keepalive_message* getKeepaliveHeader() const { return (bgp_keepalive_message*)getBasicHeader(); }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
BgpMessageType getBgpMessageType() const { return BgpLayer::Keepalive; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class BgpRouteRefreshMessageLayer
|
||||
* Represents a BGP v4 ROUTE-REFRESH message
|
||||
*/
|
||||
class BgpRouteRefreshMessageLayer : public BgpLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct bgp_route_refresh_message
|
||||
* BGP ROUTE-REFRESH message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct bgp_route_refresh_message : bgp_common_header
|
||||
{
|
||||
/** Address Family Identifier */
|
||||
uint16_t afi;
|
||||
/** Reserved field */
|
||||
uint8_t reserved;
|
||||
/** Subsequent Address Family Identifier */
|
||||
uint8_t safi;
|
||||
} bgp_route_refresh_message;
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
BgpRouteRefreshMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
/**
|
||||
* A c'tor that creates a new BGP ROUTE-REFRESH message
|
||||
* @param[in] afi The Address Family Identifier (AFI) value to set in the message
|
||||
* @param[in] safi The Subsequent Address Family Identifier (SAFI) value to set in the message
|
||||
*/
|
||||
BgpRouteRefreshMessageLayer(uint16_t afi, uint8_t safi);
|
||||
|
||||
/**
|
||||
* Get a pointer to the ROUTE-REFRESH message data. Notice this points directly to the data, so any change will modify the actual packet data
|
||||
* @return A pointer to a bgp_route_refresh_message structure containing the data
|
||||
*/
|
||||
bgp_route_refresh_message* getRouteRefreshHeader() const { return (bgp_route_refresh_message*)getBasicHeader(); }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
BgpMessageType getBgpMessageType() const { return BgpLayer::RouteRefresh; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //PACKETPP_BGP_LAYER
|
||||
99
pcappp/include/pcapplusplus/Device.h
Normal file
99
pcappp/include/pcapplusplus/Device.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef PCAPPP_DEVICE
|
||||
#define PCAPPP_DEVICE
|
||||
|
||||
/// @file
|
||||
|
||||
#include "PointerVector.h"
|
||||
#include "RawPacket.h"
|
||||
#include "PcapFilter.h"
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/** A vector of pointers to RawPacket */
|
||||
typedef PointerVector<RawPacket> RawPacketVector;
|
||||
|
||||
/**
|
||||
* @class IDevice
|
||||
* An abstract interface representing all packet processing devices. It stands as the root class for all devices.
|
||||
* This is an abstract class that cannot be instantiated
|
||||
*/
|
||||
class IDevice
|
||||
{
|
||||
protected:
|
||||
bool m_DeviceOpened;
|
||||
|
||||
// c'tor should not be public
|
||||
IDevice() : m_DeviceOpened(false) {}
|
||||
|
||||
public:
|
||||
|
||||
virtual ~IDevice() {}
|
||||
|
||||
/**
|
||||
* Open the device
|
||||
* @return True if device was opened successfully, false otherwise
|
||||
*/
|
||||
virtual bool open() = 0;
|
||||
|
||||
/**
|
||||
* Close the device
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* @return True if the file is opened, false otherwise
|
||||
*/
|
||||
inline bool isOpened() { return m_DeviceOpened; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IFilterableDevice
|
||||
* An abstract interface representing all devices that have BPF (Berkeley Packet Filter) filtering capabilities,
|
||||
* meaning devices that can filter packets based on the BPF filtering syntax.
|
||||
* This is an abstract class that cannot be instantiated
|
||||
*/
|
||||
class IFilterableDevice
|
||||
{
|
||||
protected:
|
||||
|
||||
// c'tor should not be public
|
||||
IFilterableDevice() {}
|
||||
|
||||
public:
|
||||
|
||||
virtual ~IFilterableDevice() {}
|
||||
|
||||
/**
|
||||
* Set a filter for the device. When implemented by the device, only packets that match the filter will be received
|
||||
* @param[in] filter The filter to be set in PcapPlusPlus' GeneralFilter format
|
||||
* @return True if filter set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setFilter(GeneralFilter& filter)
|
||||
{
|
||||
std::string filterAsString;
|
||||
filter.parseToString(filterAsString);
|
||||
return setFilter(filterAsString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a filter for the device. When implemented by the device, only packets that match the filter will be received
|
||||
* @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
|
||||
* @return True if filter set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setFilter(std::string filterAsString) = 0;
|
||||
|
||||
/**
|
||||
* Clear the filter currently set on the device
|
||||
* @return True if filter was removed successfully or if no filter was set, false otherwise
|
||||
*/
|
||||
virtual bool clearFilter() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PCAPPP_DEVICE
|
||||
821
pcappp/include/pcapplusplus/DhcpLayer.h
Normal file
821
pcappp/include/pcapplusplus/DhcpLayer.h
Normal file
@@ -0,0 +1,821 @@
|
||||
#ifndef PACKETPP_DHCP_LAYER
|
||||
#define PACKETPP_DHCP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
#include "IpAddress.h"
|
||||
#include "MacAddress.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifndef PCPP_DEPRECATED
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define PCPP_DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define PCPP_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
#pragma message("WARNING: DEPRECATED feature is not implemented for this compiler")
|
||||
#define PCPP_DEPRECATED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct dhcp_header
|
||||
* Represents a DHCP protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct dhcp_header
|
||||
{
|
||||
/** BootP opcode */
|
||||
uint8_t opCode;
|
||||
/** Hardware type, set to 1 (Ethernet) by default */
|
||||
uint8_t hardwareType;
|
||||
/** Hardware address length, set to 6 (MAC address length) by default */
|
||||
uint8_t hardwareAddressLength;
|
||||
/** Hop count */
|
||||
uint8_t hops;
|
||||
/** DHCP/BootP transaction ID */
|
||||
uint32_t transactionID;
|
||||
/** The elapsed time, in seconds since the client sent its first BOOTREQUEST message */
|
||||
uint16_t secondsElapsed;
|
||||
/** BootP flags */
|
||||
uint16_t flags;
|
||||
/** Client IPv4 address */
|
||||
uint32_t clientIpAddress;
|
||||
/** Your IPv4 address */
|
||||
uint32_t yourIpAddress;
|
||||
/** Server IPv4 address */
|
||||
uint32_t serverIpAddress;
|
||||
/** Gateway IPv4 address */
|
||||
uint32_t gatewayIpAddress;
|
||||
/** Client hardware address, by default contains the MAC address (only 6 first bytes are used) */
|
||||
uint8_t clientHardwareAddress[16];
|
||||
/** BootP server name */
|
||||
uint8_t serverName[64];
|
||||
/** BootP boot file name */
|
||||
uint8_t bootFilename[128];
|
||||
/** DHCP magic number (set to the default value of 0x63538263) */
|
||||
uint32_t magicNumber;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* BootP opcodes
|
||||
*/
|
||||
enum BootpOpCodes
|
||||
{
|
||||
/** BootP request */
|
||||
DHCP_BOOTREQUEST = 1,
|
||||
/** BootP reply */
|
||||
DHCP_BOOTREPLY = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* DHCP message types
|
||||
*/
|
||||
enum DhcpMessageType
|
||||
{
|
||||
/** Unknown message type */
|
||||
DHCP_UNKNOWN_MSG_TYPE = 0,
|
||||
/** Discover message type */
|
||||
DHCP_DISCOVER = 1,
|
||||
/** Offer message type */
|
||||
DHCP_OFFER = 2,
|
||||
/** Request message type */
|
||||
DHCP_REQUEST = 3,
|
||||
/** Decline message type */
|
||||
DHCP_DECLINE = 4,
|
||||
/** Acknowledge message type */
|
||||
DHCP_ACK = 5,
|
||||
/** Non-acknowledge message type */
|
||||
DHCP_NAK = 6,
|
||||
/** Release message type */
|
||||
DHCP_RELEASE = 7,
|
||||
/** Inform message type */
|
||||
DHCP_INFORM = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* DHCP option types.
|
||||
*/
|
||||
enum DhcpOptionTypes
|
||||
{
|
||||
/** Unknown option type */
|
||||
DHCPOPT_UNKNOWN = -1,
|
||||
/** Pad */
|
||||
DHCPOPT_PAD = 0,
|
||||
/** Subnet Mask Value */
|
||||
DHCPOPT_SUBNET_MASK = 1,
|
||||
/** Time Offset in Seconds from UTC */
|
||||
DHCPOPT_TIME_OFFSET = 2,
|
||||
/** N/4 Router addresses */
|
||||
DHCPOPT_ROUTERS = 3,
|
||||
/** N/4 Timeserver addresses */
|
||||
DHCPOPT_TIME_SERVERS = 4,
|
||||
/** N/4 IEN-116 Server addresses */
|
||||
DHCPOPT_NAME_SERVERS = 5,
|
||||
/** N/4 DNS Server addresses */
|
||||
DHCPOPT_DOMAIN_NAME_SERVERS = 6,
|
||||
/** N/4 Logging Server addresses */
|
||||
DHCPOPT_LOG_SERVERS = 7,
|
||||
/** N/4 Quotes Server addresses */
|
||||
DHCPOPT_QUOTES_SERVERS = 8,
|
||||
/** N/4 Quotes Server addresses */
|
||||
DHCPOPT_LPR_SERVERS = 9,
|
||||
/** N/4 Quotes Server addresses */
|
||||
DHCPOPT_IMPRESS_SERVERS = 10,
|
||||
/** N/4 RLP Server addresses */
|
||||
DHCPOPT_RESOURCE_LOCATION_SERVERS = 11,
|
||||
/** Hostname string */
|
||||
DHCPOPT_HOST_NAME = 12,
|
||||
/** Size of boot file in 512 byte chunks */
|
||||
DHCPOPT_BOOT_SIZE = 13,
|
||||
/** Client to dump and name the file to dump it to */
|
||||
DHCPOPT_MERIT_DUMP = 14,
|
||||
/** The DNS domain name of the client */
|
||||
DHCPOPT_DOMAIN_NAME = 15,
|
||||
/** Swap Server address */
|
||||
DHCPOPT_SWAP_SERVER = 16,
|
||||
/** Path name for root disk */
|
||||
DHCPOPT_ROOT_PATH = 17,
|
||||
/** Path name for more BOOTP info */
|
||||
DHCPOPT_EXTENSIONS_PATH = 18,
|
||||
/** Enable/Disable IP Forwarding */
|
||||
DHCPOPT_IP_FORWARDING = 19,
|
||||
/** Enable/Disable Source Routing */
|
||||
DHCPOPT_NON_LOCAL_SOURCE_ROUTING = 20,
|
||||
/** Routing Policy Filters */
|
||||
DHCPOPT_POLICY_FILTER = 21,
|
||||
/** Max Datagram Reassembly Size */
|
||||
DHCPOPT_MAX_DGRAM_REASSEMBLY = 22,
|
||||
/** Default IP Time to Live */
|
||||
DEFAULT_IP_TTL = 23,
|
||||
/** Path MTU Aging Timeout */
|
||||
DHCPOPT_PATH_MTU_AGING_TIMEOUT = 24,
|
||||
/** Path MTU Plateau Table */
|
||||
PATH_MTU_PLATEAU_TABLE = 25,
|
||||
/** Interface MTU Size */
|
||||
DHCPOPT_INTERFACE_MTU = 26,
|
||||
/** All Subnets are Local */
|
||||
DHCPOPT_ALL_SUBNETS_LOCAL = 27,
|
||||
/** Broadcast Address */
|
||||
DHCPOPT_BROADCAST_ADDRESS = 28,
|
||||
/** Perform Mask Discovery */
|
||||
DHCPOPT_PERFORM_MASK_DISCOVERY = 29,
|
||||
/** Provide Mask to Others */
|
||||
DHCPOPT_MASK_SUPPLIER = 30,
|
||||
/** Perform Router Discovery */
|
||||
DHCPOPT_ROUTER_DISCOVERY = 31,
|
||||
/** Router Solicitation Address */
|
||||
DHCPOPT_ROUTER_SOLICITATION_ADDRESS = 32,
|
||||
/** Static Routing Table */
|
||||
DHCPOPT_STATIC_ROUTES = 33,
|
||||
/** Trailer Encapsulation */
|
||||
DHCPOPT_TRAILER_ENCAPSULATION = 34,
|
||||
/** ARP Cache Timeout */
|
||||
DHCPOPT_ARP_CACHE_TIMEOUT = 35,
|
||||
/** IEEE802.3 Encapsulation */
|
||||
DHCPOPT_IEEE802_3_ENCAPSULATION = 36,
|
||||
/** Default TCP Time to Live */
|
||||
DHCPOPT_DEFAULT_TCP_TTL = 37,
|
||||
/** TCP Keepalive Interval */
|
||||
DHCPOPT_TCP_KEEPALIVE_INTERVAL = 38,
|
||||
/** TCP Keepalive Garbage */
|
||||
DHCPOPT_TCP_KEEPALIVE_GARBAGE = 39,
|
||||
/** NIS Domain Name */
|
||||
DHCPOPT_NIS_DOMAIN = 40,
|
||||
/** NIS Server Addresses */
|
||||
DHCPOPT_NIS_SERVERS = 41,
|
||||
/** NTP Server Addresses */
|
||||
DHCPOPT_NTP_SERVERS = 42,
|
||||
/** Vendor Specific Information */
|
||||
DHCPOPT_VENDOR_ENCAPSULATED_OPTIONS = 43,
|
||||
/** NETBIOS Name Servers */
|
||||
DHCPOPT_NETBIOS_NAME_SERVERS = 44,
|
||||
/** NETBIOS Datagram Distribution */
|
||||
DHCPOPT_NETBIOS_DD_SERVER = 45,
|
||||
/** NETBIOS Node Type */
|
||||
DHCPOPT_NETBIOS_NODE_TYPE = 46,
|
||||
/** NETBIOS Scope */
|
||||
DHCPOPT_NETBIOS_SCOPE = 47,
|
||||
/** X Window Font Server */
|
||||
DHCPOPT_FONT_SERVERS = 48,
|
||||
/** X Window Display Manager */
|
||||
DHCPOPT_X_DISPLAY_MANAGER = 49,
|
||||
/** Requested IP Address */
|
||||
DHCPOPT_DHCP_REQUESTED_ADDRESS = 50,
|
||||
/** IP Address Lease Time */
|
||||
DHCPOPT_DHCP_LEASE_TIME = 51,
|
||||
/** Overload "sname" or "file" */
|
||||
DHCPOPT_DHCP_OPTION_OVERLOAD = 52,
|
||||
/** DHCP Message Type */
|
||||
DHCPOPT_DHCP_MESSAGE_TYPE = 53,
|
||||
/** DHCP Server Identification */
|
||||
DHCPOPT_DHCP_SERVER_IDENTIFIER = 54,
|
||||
/** Parameter Request List */
|
||||
DHCPOPT_DHCP_PARAMETER_REQUEST_LIST = 55,
|
||||
/** DHCP Error Message */
|
||||
DHCPOPT_DHCP_MESSAGE = 56,
|
||||
/** DHCP Maximum Message Size */
|
||||
DHCPOPT_DHCP_MAX_MESSAGE_SIZE = 57,
|
||||
/** DHCP Renewal (T1) Time */
|
||||
DHCPOPT_DHCP_RENEWAL_TIME = 58,
|
||||
/** DHCP Rebinding (T2) Time */
|
||||
DHCPOPT_DHCP_REBINDING_TIME = 59,
|
||||
/** Class Identifier */
|
||||
DHCPOPT_VENDOR_CLASS_IDENTIFIER = 60,
|
||||
/** Class Identifier */
|
||||
DHCPOPT_DHCP_CLIENT_IDENTIFIER = 61,
|
||||
/** NetWare/IP Domain Name */
|
||||
DHCPOPT_NWIP_DOMAIN_NAME = 62,
|
||||
/** NetWare/IP sub Options */
|
||||
DHCPOPT_NWIP_SUBOPTIONS = 63,
|
||||
/** NIS+ v3 Client Domain Name */
|
||||
DHCPOPT_NIS_DOMAIN_NAME = 64,
|
||||
/** NIS+ v3 Server Addresses */
|
||||
DHCPOPT_NIS_SERVER_ADDRESS = 65,
|
||||
/** TFTP Server Name */
|
||||
DHCPOPT_TFTP_SERVER_NAME = 66,
|
||||
/** Boot File Name */
|
||||
DHCPOPT_BOOTFILE_NAME = 67,
|
||||
/** Home Agent Addresses */
|
||||
DHCPOPT_HOME_AGENT_ADDRESS = 68,
|
||||
/** Simple Mail Server (SMTP) Addresses */
|
||||
DHCPOPT_SMTP_SERVER = 69,
|
||||
/** Post Office (POP3) Server Addresses */
|
||||
DHCPOPT_POP3_SERVER = 70,
|
||||
/** Network News (NNTP) Server Addresses */
|
||||
DHCPOPT_NNTP_SERVER = 71,
|
||||
/** WWW Server Addresses */
|
||||
DHCPOPT_WWW_SERVER = 72,
|
||||
/** Finger Server Addresses */
|
||||
DHCPOPT_FINGER_SERVER = 73,
|
||||
/** Chat (IRC) Server Addresses */
|
||||
DHCPOPT_IRC_SERVER = 74,
|
||||
/** StreetTalk Server Addresses */
|
||||
DHCPOPT_STREETTALK_SERVER = 75,
|
||||
/** ST Directory Assist. Addresses */
|
||||
DHCPOPT_STDA_SERVER = 76,
|
||||
/** User Class Information */
|
||||
DHCPOPT_USER_CLASS = 77,
|
||||
/** Directory Agent Information */
|
||||
DHCPOPT_DIRECTORY_AGENT = 78,
|
||||
/** Service Location Agent Scope */
|
||||
DHCPOPT_SERVICE_SCOPE = 79,
|
||||
/** Rapid Commit */
|
||||
DHCPOPT_RAPID_COMMIT = 80,
|
||||
/** Fully Qualified Domain Name */
|
||||
DHCPOPT_FQDN = 81,
|
||||
/** Relay Agent Information */
|
||||
DHCPOPT_DHCP_AGENT_OPTIONS = 82,
|
||||
/** Internet Storage Name Service */
|
||||
DHCPOPT_ISNS = 83,
|
||||
/** Novell Directory Services */
|
||||
DHCPOPT_NDS_SERVERS = 85,
|
||||
/** Novell Directory Services */
|
||||
DHCPOPT_NDS_TREE_NAME = 86,
|
||||
/** Novell Directory Services */
|
||||
DHCPOPT_NDS_CONTEXT = 87,
|
||||
/** BCMCS Controller Domain Name list */
|
||||
DHCPOPT_BCMCS_CONTROLLER_DOMAIN_NAME_LIST = 88,
|
||||
/** BCMCS Controller IPv4 address option */
|
||||
DHCPOPT_BCMCS_CONTROLLER_IPV4_ADDRESS = 89,
|
||||
/** Authentication */
|
||||
DHCPOPT_AUTHENTICATION = 90,
|
||||
/** Client Last Transaction Time */
|
||||
DHCPOPT_CLIENT_LAST_TXN_TIME = 91,
|
||||
/** Associated IP */
|
||||
DHCPOPT_ASSOCIATED_IP = 92,
|
||||
/** Client System Architecture */
|
||||
DHCPOPT_CLIENT_SYSTEM = 93,
|
||||
/** Client Network Device Interface */
|
||||
DHCPOPT_CLIENT_NDI = 94,
|
||||
/** Lightweight Directory Access Protocol [ */
|
||||
DHCPOPT_LDAP = 95,
|
||||
/** UUID/GUID-based Client Identifier */
|
||||
DHCPOPT_UUID_GUID = 97,
|
||||
/** Open Group's User Authentication */
|
||||
DHCPOPT_USER_AUTH = 98,
|
||||
/** GEOCONF_CIVIC */
|
||||
DHCPOPT_GEOCONF_CIVIC = 99,
|
||||
/** IEEE 1003.1 TZ String */
|
||||
DHCPOPT_PCODE = 100,
|
||||
/** Reference to the TZ Database */
|
||||
DHCPOPT_TCODE = 101,
|
||||
/** NetInfo Parent Server Address */
|
||||
DHCPOPT_NETINFO_ADDRESS = 112,
|
||||
/** NetInfo Parent Server Tag */
|
||||
DHCPOPT_NETINFO_TAG = 113,
|
||||
/** URL */
|
||||
DHCPOPT_URL = 114,
|
||||
/** DHCP Auto-Configuration */
|
||||
DHCPOPT_AUTO_CONFIG = 116,
|
||||
/** Name Service Search */
|
||||
DHCPOPT_NAME_SERVICE_SEARCH = 117,
|
||||
/** Subnet Selection Option */
|
||||
DHCPOPT_SUBNET_SELECTION = 118,
|
||||
/** DNS Domain Search List */
|
||||
DHCPOPT_DOMAIN_SEARCH = 119,
|
||||
/** SIP Servers DHCP Option */
|
||||
DHCPOPT_SIP_SERVERS = 120,
|
||||
/** Classless Static Route Option */
|
||||
DHCPOPT_CLASSLESS_STATIC_ROUTE = 121,
|
||||
/** CableLabs Client Configuration */
|
||||
DHCPOPT_CCC = 122,
|
||||
/** GeoConf Option */
|
||||
DHCPOPT_GEOCONF = 123,
|
||||
/** Vendor-Identifying Vendor Class */
|
||||
DHCPOPT_V_I_VENDOR_CLASS = 124,
|
||||
/** Vendor-Identifying Vendor-Specific Information */
|
||||
DHCPOPT_V_I_VENDOR_OPTS = 125,
|
||||
/** OPTION_PANA_AGENT */
|
||||
DHCPOPT_OPTION_PANA_AGENT = 136,
|
||||
/** OPTION_V4_LOST */
|
||||
DHCPOPT_OPTION_V4_LOST = 137,
|
||||
/** CAPWAP Access Controller addresses */
|
||||
DHCPOPT_OPTION_CAPWAP_AC_V4 = 138,
|
||||
/** A Series Of Suboptions */
|
||||
DHCPOPT_OPTION_IPV4_ADDRESS_MOS = 139,
|
||||
/** A Series Of Suboptions */
|
||||
DHCPOPT_OPTION_IPV4_FQDN_MOS = 140,
|
||||
/** List of domain names to search for SIP User Agent Configuration */
|
||||
DHCPOPT_SIP_UA_CONFIG = 141,
|
||||
/** ANDSF IPv4 Address Option for DHCPv4 */
|
||||
DHCPOPT_OPTION_IPV4_ADDRESS_ANDSF = 142,
|
||||
/** Geospatial Location with Uncertainty [RF */
|
||||
DHCPOPT_GEOLOC = 144,
|
||||
/** Forcerenew Nonce Capable */
|
||||
DHCPOPT_FORCERENEW_NONCE_CAPABLE = 145,
|
||||
/** Information for selecting RDNSS */
|
||||
DHCPOPT_RDNSS_SELECTION = 146,
|
||||
/** Status code and optional N byte text message describing status */
|
||||
DHCPOPT_STATUS_CODE = 151,
|
||||
/** Absolute time (seconds since Jan 1, 1970) message was sent */
|
||||
DHCPOPT_BASE_TIME = 152,
|
||||
/** Number of seconds in the past when client entered current state */
|
||||
DHCPOPT_START_TIME_OF_STATE = 153,
|
||||
/** Absolute time (seconds since Jan 1, 1970) for beginning of query */
|
||||
DHCPOPT_QUERY_START_TIME = 154,
|
||||
/** Absolute time (seconds since Jan 1, 1970) for end of query */
|
||||
DHCPOPT_QUERY_END_TIME = 155,
|
||||
/** State of IP address */
|
||||
DHCPOPT_DHCP_STATE = 156,
|
||||
/** Indicates information came from local or remote server */
|
||||
DHCPOPT_DATA_SOURCE = 157,
|
||||
/** Includes one or multiple lists of PCP server IP addresses; each list is treated as a separate PCP server */
|
||||
DHCPOPT_OPTION_V4_PCP_SERVER = 158,
|
||||
/** This option is used to configure a set of ports bound to a shared IPv4 address */
|
||||
DHCPOPT_OPTION_V4_PORTPARAMS = 159,
|
||||
/** DHCP Captive-Portal */
|
||||
DHCPOPT_CAPTIVE_PORTAL = 160,
|
||||
/** Manufacturer Usage Descriptions */
|
||||
DHCPOPT_OPTION_MUD_URL_V4 = 161,
|
||||
/** Etherboot */
|
||||
DHCPOPT_ETHERBOOT = 175,
|
||||
/** IP Telephone */
|
||||
DHCPOPT_IP_TELEPHONE = 176,
|
||||
/** Magic string = F1:00:74:7E */
|
||||
DHCPOPT_PXELINUX_MAGIC = 208,
|
||||
/** Configuration file */
|
||||
DHCPOPT_CONFIGURATION_FILE = 209,
|
||||
/** Path Prefix Option */
|
||||
DHCPOPT_PATH_PREFIX = 210,
|
||||
/** Reboot Time */
|
||||
DHCPOPT_REBOOT_TIME = 211,
|
||||
/** OPTION_6RD with N/4 6rd BR addresses */
|
||||
DHCPOPT_OPTION_6RD = 212,
|
||||
/** Access Network Domain Name */
|
||||
DHCPOPT_OPTION_V4_ACCESS_DOMAIN = 213,
|
||||
/** Subnet Allocation Option */
|
||||
DHCPOPT_SUBNET_ALLOCATION = 220,
|
||||
/** Virtual Subnet Selection (VSS) Option */
|
||||
DHCPOPT_VIRTUAL_SUBNET_SELECTION = 221,
|
||||
/** End (last option) */
|
||||
DHCPOPT_END = 255
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class DhcpOption
|
||||
* A wrapper class for DHCP options. This class does not create or modify DHCP option records, but rather
|
||||
* serves as a wrapper and provides useful methods for setting and retrieving data to/from them
|
||||
*/
|
||||
class DhcpOption : public TLVRecord<uint8_t, uint8_t>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the option raw data (byte array)
|
||||
* @param[in] optionRawData A pointer to the option raw data
|
||||
*/
|
||||
DhcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
virtual ~DhcpOption() { }
|
||||
|
||||
/**
|
||||
* Retrieve DHCP option data as IPv4 address. Relevant only if option value is indeed an IPv4 address
|
||||
* @return DHCP option data as IPv4 address
|
||||
*/
|
||||
IPv4Address getValueAsIpAddr() const
|
||||
{
|
||||
return getValueAs<uint32_t>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DHCP option data as IPv4 address. This method copies the 4 bytes of the IP address to the option value
|
||||
* @param[in] addr The IPv4 address to set
|
||||
* @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set to 0). For example:
|
||||
* if option data is 20 bytes long and you want to set the IP address in the 4 last bytes then use this method like this:
|
||||
* setValueIpAddr(your_addr, 16)
|
||||
*/
|
||||
void setValueIpAddr(const IPv4Address& addr, int valueOffset = 0)
|
||||
{
|
||||
setValue<uint32_t>(addr.toInt(), valueOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve DHCP option data as string. Relevant only if option value is indeed a string
|
||||
* @param[in] valueOffset An optional parameter that specifies where to start copy the DHCP option data. For example:
|
||||
* when retrieving Client FQDN option, you may ignore the flags and RCODE fields using this method like this:
|
||||
* getValueAsString(3). The default is 0 - start copying from the beginning of option data
|
||||
* @return DHCP option data as string
|
||||
*/
|
||||
std::string getValueAsString(int valueOffset = 0) const
|
||||
{
|
||||
if (m_Data->recordLen - valueOffset < 1)
|
||||
return "";
|
||||
|
||||
return std::string((const char*)m_Data->recordValue + valueOffset, (int)m_Data->recordLen - valueOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DHCP option data as string. This method copies the string to the option value. If the string is longer than option length
|
||||
* the string is trimmed so it will fit the option length
|
||||
* @param[in] stringValue The string to set
|
||||
* @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set to 0). For example:
|
||||
* if option data is 20 bytes long and you want to set a 6 char-long string in the 6 last bytes then use this method like this:
|
||||
* setValueString("string", 14)
|
||||
*/
|
||||
void setValueString(const std::string& stringValue, int valueOffset = 0)
|
||||
{
|
||||
// calculate the maximum length of the destination buffer
|
||||
size_t len = (size_t)m_Data->recordLen - (size_t)valueOffset;
|
||||
|
||||
// use the length of input string if a buffer is large enough for whole string
|
||||
if (stringValue.length() < len)
|
||||
len = stringValue.length();
|
||||
|
||||
memcpy(m_Data->recordValue + valueOffset, stringValue.data(), len);
|
||||
}
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
if (m_Data->recordType == (uint8_t)DHCPOPT_END || m_Data->recordType == (uint8_t)DHCPOPT_PAD)
|
||||
return sizeof(uint8_t);
|
||||
|
||||
return sizeof(uint8_t) * 2 + (size_t)m_Data->recordLen;
|
||||
}
|
||||
|
||||
size_t getDataSize() const
|
||||
{
|
||||
if (m_Data->recordType == (uint8_t)DHCPOPT_END || m_Data->recordType == (uint8_t)DHCPOPT_PAD)
|
||||
return 0;
|
||||
|
||||
return m_Data->recordLen;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class DhcpOptionBuilder
|
||||
* A class for building DHCP options. This builder receives the option parameters in its c'tor,
|
||||
* builds the DHCP option raw buffer and provides a build() method to get a DhcpOption object out of it
|
||||
*/
|
||||
class DhcpOptionBuilder : public TLVRecordBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCP options which their value is a byte array. The DhcpOption object can later
|
||||
* be retrieved by calling build()
|
||||
* @param[in] optionType DHCP option type
|
||||
* @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way
|
||||
* @param[in] optionValueLen DHCP option value length in bytes
|
||||
*/
|
||||
DhcpOptionBuilder(DhcpOptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCP options which have a 1-byte value. The DhcpOption object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType DHCP option type
|
||||
* @param[in] optionValue A 1-byte option value
|
||||
*/
|
||||
DhcpOptionBuilder(DhcpOptionTypes optionType, uint8_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCP options which have a 2-byte value. The DhcpOption object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType DHCP option type
|
||||
* @param[in] optionValue A 2-byte option value
|
||||
*/
|
||||
DhcpOptionBuilder(DhcpOptionTypes optionType, uint16_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCP options which have a 4-byte value. The DhcpOption object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType DHCP option type
|
||||
* @param[in] optionValue A 4-byte option value
|
||||
*/
|
||||
DhcpOptionBuilder(DhcpOptionTypes optionType, uint32_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCP options which have an IPv4Address value. The DhcpOption object can later be
|
||||
* retrieved by calling build()
|
||||
* @param[in] optionType DHCP option type
|
||||
* @param[in] optionValue The IPv4 address option value
|
||||
*/
|
||||
DhcpOptionBuilder(DhcpOptionTypes optionType, const IPv4Address& optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCP options which have a string value. The DhcpOption object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType DHCP option type
|
||||
* @param[in] optionValue The string option value
|
||||
*/
|
||||
DhcpOptionBuilder(DhcpOptionTypes optionType, const std::string& optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) { }
|
||||
|
||||
/**
|
||||
* A copy c'tor which copies all the data from another instance of DhcpOptionBuilder
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
DhcpOptionBuilder(const DhcpOptionBuilder& other) :
|
||||
TLVRecordBuilder(other) { }
|
||||
|
||||
/**
|
||||
* Assignment operator that copies all data from another instance of DhcpOptionBuilder
|
||||
* @param[in] other The instance to assign from
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
DhcpOptionBuilder& operator=(const DhcpOptionBuilder& other)
|
||||
{
|
||||
TLVRecordBuilder::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the DhcpOption object out of the parameters defined in the c'tor
|
||||
* @return The DhcpOption object
|
||||
*/
|
||||
DhcpOption build() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class DhcpLayer
|
||||
* Represents a DHCP (Dynamic Host Configuration Protocol) protocol layer
|
||||
*/
|
||||
class DhcpLayer : public Layer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
DhcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from scratch. Adds a ::DHCPOPT_DHCP_MESSAGE_TYPE and a ::DHCPOPT_END
|
||||
* options
|
||||
* @param[in] msgType A DHCP message type to be set
|
||||
* @param[in] clientMacAddr A client MAC address to set in dhcp_header#clientHardwareAddress field
|
||||
*/
|
||||
DhcpLayer(DhcpMessageType msgType, const MacAddress& clientMacAddr);
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from scratch with clean data
|
||||
*/
|
||||
DhcpLayer();
|
||||
|
||||
/**
|
||||
* A destructor for this layer
|
||||
*/
|
||||
virtual ~DhcpLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the DHCP header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref dhcp_header
|
||||
*/
|
||||
dhcp_header* getDhcpHeader() const { return (dhcp_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The BootP opcode of this message
|
||||
*/
|
||||
BootpOpCodes getOpCode() const { return (BootpOpCodes)getDhcpHeader()->opCode; }
|
||||
|
||||
/**
|
||||
* @return The client IPv4 address (as extracted from dhcp_header#clientIpAddress converted to IPv4Address object)
|
||||
*/
|
||||
IPv4Address getClientIpAddress() const { return getDhcpHeader()->clientIpAddress; }
|
||||
|
||||
/**
|
||||
* Set the client IPv4 address in dhcp_header#clientIpAddress
|
||||
* @param[in] addr The IPv4 address to set
|
||||
*/
|
||||
void setClientIpAddress(const IPv4Address& addr) { getDhcpHeader()->clientIpAddress = addr.toInt(); }
|
||||
|
||||
/**
|
||||
* @return The server IPv4 address (as extracted from dhcp_header#serverIpAddress converted to IPv4Address object)
|
||||
*/
|
||||
IPv4Address getServerIpAddress() const { return getDhcpHeader()->serverIpAddress; }
|
||||
|
||||
/**
|
||||
* Set the server IPv4 address in dhcp_header#serverIpAddress
|
||||
* @param[in] addr The IPv4 address to set
|
||||
*/
|
||||
void setServerIpAddress(const IPv4Address& addr) { getDhcpHeader()->serverIpAddress = addr.toInt(); }
|
||||
|
||||
/**
|
||||
* @return Your IPv4 address (as extracted from dhcp_header#yourIpAddress converted to IPv4Address object)
|
||||
*/
|
||||
IPv4Address getYourIpAddress() const { return getDhcpHeader()->yourIpAddress; }
|
||||
|
||||
/**
|
||||
* Set your IPv4 address in dhcp_header#yourIpAddress
|
||||
* @param[in] addr The IPv4 address to set
|
||||
*/
|
||||
void setYourIpAddress(const IPv4Address& addr) { getDhcpHeader()->yourIpAddress = addr.toInt(); }
|
||||
|
||||
/**
|
||||
* @return Gateway IPv4 address (as extracted from dhcp_header#gatewayIpAddress converted to IPv4Address object)
|
||||
*/
|
||||
IPv4Address getGatewayIpAddress() const { return getDhcpHeader()->gatewayIpAddress; }
|
||||
|
||||
/**
|
||||
* Set the gateway IPv4 address in dhcp_header#gatewayIpAddress
|
||||
* @param[in] addr The IPv4 address to set
|
||||
*/
|
||||
void setGatewayIpAddress(const IPv4Address& addr) { getDhcpHeader()->gatewayIpAddress = addr.toInt(); }
|
||||
|
||||
/**
|
||||
* @return The client MAC address as extracted from dhcp_header#clientHardwareAddress, assuming dhcp_header#hardwareType is 1 (Ethernet)
|
||||
* and dhcp_header#hardwareAddressLength is 6 (MAC address length). Otherwise returns MacAddress#Zero
|
||||
*/
|
||||
MacAddress getClientHardwareAddress() const;
|
||||
|
||||
/**
|
||||
* Set a MAC address into the first 6 bytes of dhcp_header#clientHardwareAddress. This method also sets dhcp_header#hardwareType
|
||||
* to 1 (Ethernet) and dhcp_header#hardwareAddressLength to 6 (MAC address length)
|
||||
* @param[in] addr The MAC address to set
|
||||
*/
|
||||
void setClientHardwareAddress(const MacAddress& addr);
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated due to typo. Please use getMessageType()
|
||||
*/
|
||||
PCPP_DEPRECATED DhcpMessageType getMesageType() const { return getMessageType(); };
|
||||
|
||||
/**
|
||||
* @return DHCP message type as extracted from ::DHCPOPT_DHCP_MESSAGE_TYPE option. If this option doesn't exist the value of
|
||||
* ::DHCP_UNKNOWN_MSG_TYPE is returned
|
||||
*/
|
||||
DhcpMessageType getMessageType() const;
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated due to typo. Please use setMessageType()
|
||||
*/
|
||||
bool setMesageType(DhcpMessageType msgType) { return setMessageType(msgType); };
|
||||
|
||||
/**
|
||||
* Set DHCP message type. This method searches for existing ::DHCPOPT_DHCP_MESSAGE_TYPE option. If found, it sets the requested
|
||||
* message type as its value. If not, it creates a ::DHCPOPT_DHCP_MESSAGE_TYPE option and sets the requested message type as its
|
||||
* value
|
||||
* @param[in] msgType Message type to set
|
||||
* @return True if message type was set successfully or false if msgType is ::DHCP_UNKNOWN_MSG_TYPE or if failed to add
|
||||
* ::DHCPOPT_DHCP_MESSAGE_TYPE option
|
||||
*/
|
||||
bool setMessageType(DhcpMessageType msgType);
|
||||
|
||||
/**
|
||||
* @return The first DHCP option in the packet. If there are no DHCP options the returned value will contain
|
||||
* a logical NULL (DhcpOption#isNull() == true)
|
||||
*/
|
||||
DhcpOption getFirstOptionData() const;
|
||||
|
||||
/**
|
||||
* Get the DHCP option that comes after a given option. If the given option was the last one, the
|
||||
* returned value will contain a logical NULL (DhcpOption#isNull() == true)
|
||||
* @param[in] dhcpOption A given DHCP option
|
||||
* @return A DhcpOption object containing the option data that comes next, or logical NULL if the given DHCP
|
||||
* option: (1) was the last one; (2) contains a logical NULL or (3) doesn't belong to this packet
|
||||
*/
|
||||
DhcpOption getNextOptionData(DhcpOption dhcpOption) const;
|
||||
|
||||
/**
|
||||
* Get a DHCP option by type
|
||||
* @param[in] option DHCP option type
|
||||
* @return A DhcpOption object containing the first DHCP option data that matches this type, or logical NULL
|
||||
* (DhcpOption#isNull() == true) if no such option found
|
||||
*/
|
||||
DhcpOption getOptionData(DhcpOptionTypes option) const;
|
||||
|
||||
/**
|
||||
* @return The number of DHCP options in this layer
|
||||
*/
|
||||
size_t getOptionsCount() const;
|
||||
|
||||
/**
|
||||
* Add a new DHCP option at the end of the layer
|
||||
* @param[in] optionBuilder A DhcpOptionBuilder object that contains the requested DHCP option data to add
|
||||
* @return A DhcpOption object containing the newly added DHCP option data or logical NULL
|
||||
* (DhcpOption#isNull() == true) if addition failed
|
||||
*/
|
||||
DhcpOption addOption(const DhcpOptionBuilder& optionBuilder);
|
||||
|
||||
/**
|
||||
* Add a new DHCP option after an existing one
|
||||
* @param[in] optionBuilder A DhcpOptionBuilder object that contains the requested DHCP option data to add
|
||||
* @param[in] prevOption The DHCP option type which the newly added option will come after
|
||||
* @return A DhcpOption object containing the newly added DHCP option data or logical NULL
|
||||
* (DhcpOption#isNull() == true) if addition failed
|
||||
*/
|
||||
DhcpOption addOptionAfter(const DhcpOptionBuilder& optionBuilder, DhcpOptionTypes prevOption);
|
||||
|
||||
/**
|
||||
* Remove an existing DHCP option from the layer
|
||||
* @param[in] optionType The DHCP option type to remove
|
||||
* @return True if DHCP option was successfully removed or false if type wasn't found or if removal failed
|
||||
*/
|
||||
bool removeOption(DhcpOptionTypes optionType);
|
||||
|
||||
/**
|
||||
* Remove all DHCP options in this layer
|
||||
* @return True if all DHCP options were successfully removed or false if removal failed for some reason
|
||||
*/
|
||||
bool removeAllOptions();
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (DhcpLayer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return The size of @ref dhcp_header + size of options
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - @ref dhcp_header#magicNumber = DHCP magic number (0x63538263)
|
||||
* - @ref dhcp_header#opCode = ::DHCP_BOOTREQUEST for message types: ::DHCP_DISCOVER, ::DHCP_REQUEST, ::DHCP_DECLINE, ::DHCP_RELEASE,
|
||||
* ::DHCP_INFORM, ::DHCP_UNKNOWN_MSG_TYPE
|
||||
* ::DHCP_BOOTREPLY for message types: ::DHCP_OFFER, ::DHCP_ACK, ::DHCP_NAK
|
||||
* - @ref dhcp_header#hardwareType = 1 (Ethernet)
|
||||
* - @ref dhcp_header#hardwareAddressLength = 6 (MAC address length)
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
private:
|
||||
|
||||
uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(dhcp_header); }
|
||||
|
||||
TLVRecordReader<DhcpOption> m_OptionReader;
|
||||
|
||||
void initDhcpLayer(size_t numOfBytesToAllocate);
|
||||
|
||||
DhcpOption addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* PACKETPP_DHCP_LAYER */
|
||||
454
pcappp/include/pcapplusplus/DhcpV6Layer.h
Normal file
454
pcappp/include/pcapplusplus/DhcpV6Layer.h
Normal file
@@ -0,0 +1,454 @@
|
||||
#ifndef PACKETPP_DHCPV6_LAYER
|
||||
#define PACKETPP_DHCPV6_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* DHCPv6 message types
|
||||
*/
|
||||
enum DhcpV6MessageType
|
||||
{
|
||||
/** Unknown message type */
|
||||
DHCPV6_UNKNOWN_MSG_TYPE = 0,
|
||||
/** Solicit message type (Client to Server) */
|
||||
DHCPV6_SOLICIT = 1,
|
||||
/** Advertise message type (Server to Client) */
|
||||
DHCPV6_ADVERTISE = 2,
|
||||
/** Request message type (Client to Server) */
|
||||
DHCPV6_REQUEST = 3,
|
||||
/** Confirm message type (Client to Server) */
|
||||
DHCPV6_CONFIRM = 4,
|
||||
/** Renew message type (Client to Server) */
|
||||
DHCPV6_RENEW = 5,
|
||||
/** Rebind message type (Client to Server) */
|
||||
DHCPV6_REBIND = 6,
|
||||
/** Reply message type (Server to Client) */
|
||||
DHCPV6_REPLY = 7,
|
||||
/** Release message type (Client to Server) */
|
||||
DHCPV6_RELEASE = 8,
|
||||
/** Decline message type (Client to Server) */
|
||||
DHCPV6_DECLINE = 9,
|
||||
/** Reconfigure message type (Server to Client) */
|
||||
DHCPV6_RECONFIGURE = 10,
|
||||
/** Information-Request message type (Client to Server) */
|
||||
DHCPV6_INFORMATION_REQUEST = 11,
|
||||
/** Relay-Forward message type (Relay agent to Server) */
|
||||
DHCPV6_RELAY_FORWARD = 12,
|
||||
/** Relay-Reply message type (Server to Relay agent) */
|
||||
DHCPV6_RELAY_REPLY = 13
|
||||
};
|
||||
|
||||
/**
|
||||
* DHCPv6 option types.
|
||||
* Resources for more information:
|
||||
* - https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781118073810.app2
|
||||
* - https://datatracker.ietf.org/doc/html/rfc5970
|
||||
* - https://datatracker.ietf.org/doc/html/rfc6607
|
||||
* - https://datatracker.ietf.org/doc/html/rfc8520
|
||||
*/
|
||||
enum DhcpV6OptionType
|
||||
{
|
||||
/** Unknown option type */
|
||||
DHCPV6_OPT_UNKNOWN = 0,
|
||||
/** Client Identifier (DUID of client) */
|
||||
DHCPV6_OPT_CLIENTID = 1,
|
||||
/** Server Identifier (DUID of server) */
|
||||
DHCPV6_OPT_SERVERID = 2,
|
||||
/** Identity Association for Non-temporary addresses */
|
||||
DHCPV6_OPT_IA_NA = 3,
|
||||
/** Identity Association for Temporary addresses */
|
||||
DHCPV6_OPT_IA_TA = 4,
|
||||
/** IA Address option */
|
||||
DHCPV6_OPT_IAADDR = 5,
|
||||
/** Option Request Option */
|
||||
DHCPV6_OPT_ORO = 6,
|
||||
/** Preference setting */
|
||||
DHCPV6_OPT_PREFERENCE = 7,
|
||||
/** The amount of time since the client began the current DHCP transaction */
|
||||
DHCPV6_OPT_ELAPSED_TIME = 8,
|
||||
/** The DHCP message being relayed by a relay agent */
|
||||
DHCPV6_OPT_RELAY_MSG = 9,
|
||||
/** Authentication information */
|
||||
DHCPV6_OPT_AUTH = 11,
|
||||
/** Server unicast */
|
||||
DHCPV6_OPT_UNICAST = 12,
|
||||
/** Status code */
|
||||
DHCPV6_OPT_STATUS_CODE = 13,
|
||||
/** Rapid commit */
|
||||
DHCPV6_OPT_RAPID_COMMIT = 14,
|
||||
/** User class */
|
||||
DHCPV6_OPT_USER_CLASS = 15,
|
||||
/** Vendor class */
|
||||
DHCPV6_OPT_VENDOR_CLASS = 16,
|
||||
/** Vendor specific information */
|
||||
DHCPV6_OPT_VENDOR_OPTS = 17,
|
||||
/** Interface ID */
|
||||
DHCPV6_OPT_INTERFACE_ID = 18,
|
||||
/** Reconfigure Message */
|
||||
DHCPV6_OPT_RECONF_MSG = 19,
|
||||
/** Reconfigure Accept */
|
||||
DHCPV6_OPT_RECONF_ACCEPT = 20,
|
||||
/** SIP Servers Domain Name */
|
||||
DHCPV6_OPT_SIP_SERVERS_D = 21,
|
||||
/** SIP Servers IPv6 Address List */
|
||||
DHCPV6_OPT_SIP_SERVERS_A = 22,
|
||||
/** DNS Recursive Name Server */
|
||||
DHCPV6_OPT_DNS_SERVERS = 23,
|
||||
/** Domain Search List */
|
||||
DHCPV6_OPT_DOMAIN_LIST = 24,
|
||||
/** Identity Association for Prefix Delegation */
|
||||
DHCPV6_OPT_IA_PD = 25,
|
||||
/** IA_PD Prefix */
|
||||
DHCPV6_OPT_IAPREFIX = 26,
|
||||
/** Network Information Service (NIS) Servers */
|
||||
DHCPV6_OPT_NIS_SERVERS = 27,
|
||||
/** Network Information Service v2 (NIS+) Servers */
|
||||
DHCPV6_OPT_NISP_SERVERS = 28,
|
||||
/** Network Information Service (NIS) domain name */
|
||||
DHCPV6_OPT_NIS_DOMAIN_NAME = 29,
|
||||
/** Network Information Service v2 (NIS+) domain name */
|
||||
DHCPV6_OPT_NISP_DOMAIN_NAME = 30,
|
||||
/** Simple Network Time Protocol (SNTP) servers */
|
||||
DHCPV6_OPT_SNTP_SERVERS = 31,
|
||||
/** Information Refresh */
|
||||
DHCPV6_OPT_INFORMATION_REFRESH_TIME = 32,
|
||||
/** Broadcast and Multicast Service (BCMCS) Domain Name List */
|
||||
DHCPV6_OPT_BCMCS_SERVER_D = 33,
|
||||
/** Broadcast and Multicast Service (BCMCS) IPv6 Address List */
|
||||
DHCPV6_OPT_BCMCS_SERVER_A = 34,
|
||||
/** Geographical location in civic (e.g., postal) format */
|
||||
DHCPV6_OPT_GEOCONF_CIVIC = 36,
|
||||
/** Relay Agent Remote ID */
|
||||
DHCPV6_OPT_REMOTE_ID = 37,
|
||||
/** Relay Agent Subscriber ID */
|
||||
DHCPV6_OPT_SUBSCRIBER_ID = 38,
|
||||
/** FQDN */
|
||||
DHCPV6_OPT_CLIENT_FQDN = 39,
|
||||
/** One or more IPv6 addresses associated with PANA (Protocol for carrying Authentication for Network Access) Authentication Agents */
|
||||
DHCPV6_OPT_PANA_AGENT = 40,
|
||||
/** Time zone to be used by the client in IEEE 1003.1 format */
|
||||
DHCPV6_OPT_NEW_POSIX_TIMEZONE = 41,
|
||||
/** Time zone (TZ) database entry referred to by entry name */
|
||||
DHCPV6_OPT_NEW_TZDB_TIMEZONE = 42,
|
||||
/** Relay Agent Echo Request */
|
||||
DHCPV6_OPT_ERO = 43,
|
||||
/** Query option */
|
||||
DHCPV6_OPT_LQ_QUERY = 44,
|
||||
/** Client Data */
|
||||
DHCPV6_OPT_CLIENT_DATA = 45,
|
||||
/** Client Last Transaction Time */
|
||||
DHCPV6_OPT_CLT_TIME = 46,
|
||||
/** Relay data */
|
||||
DHCPV6_OPT_LQ_RELAY_DATA = 47,
|
||||
/** Client link */
|
||||
DHCPV6_OPT_LQ_CLIENT_LINK = 48,
|
||||
/** Mobile IPv6 Home Network Information */
|
||||
DHCPV6_OPT_MIP6_HNINF = 49,
|
||||
/** Mobile IPv6 Relay Agent */
|
||||
DHCPV6_OPT_MIP6_RELAY = 50,
|
||||
/** Location to Service Translation (LoST) server domain name */
|
||||
DHCPV6_OPT_V6_LOST = 51,
|
||||
/** Access Points (CAPWAP) Access Controller IPv6 addresses */
|
||||
DHCPV6_OPT_CAPWAP_AC_V6 = 52,
|
||||
/** DHCPv6 Bulk LeaseQuery */
|
||||
DHCPV6_OPT_RELAY_ID = 53,
|
||||
/** List of IPv6 addresses for servers providing particular types of IEEE 802.21 Mobility Service (MoS) */
|
||||
DHCPV6_OPT_IPH6_ADDRESS_MOS = 54,
|
||||
/** List of FQDNs for servers providing particular types of IEEE 802.21 Mobility Service (MoS) */
|
||||
DHCPV6_OPT_IPV6_FQDN_MOS = 55,
|
||||
/** Network Time Protocol (NTP) or Simple NTP (SNTP) Server Location */
|
||||
DHCPV6_OPT_NTP_SERVER = 56,
|
||||
/** Boot File Uniform Resource Locator (URL) */
|
||||
DHCPV6_OPT_BOOTFILE_URL = 59,
|
||||
/** Boot File Parameters */
|
||||
DHCPV6_OPT_BOOTFILE_PARAM = 60,
|
||||
/** Client System Architecture Type */
|
||||
DHCPV6_OPT_CLIENT_ARCH_TYPE = 61,
|
||||
/** Client Network Interface Identifier */
|
||||
DHCPV6_OPT_NII = 62,
|
||||
/** ERP Local Domain Name */
|
||||
DHCPV6_OPT_ERP_LOCAL_DOMAIN_NAME = 65,
|
||||
/** Relay supplied options */
|
||||
DHCPV6_OPT_RELAY_SUPPLIED_OPTIONS = 66,
|
||||
/** Virtual Subnet Selection */
|
||||
DHCPV6_OPT_VSS = 68,
|
||||
/** Client link layer */
|
||||
DHCPV6_OPT_CLIENT_LINKLAYER_ADDR = 79,
|
||||
/** Manufacturer Usage Description */
|
||||
DHCPV6_OPT_MUD_URL = 112
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DhcpV6Option
|
||||
* A wrapper class for DHCPv6 options. This class does not create or modify DHCP option records, but rather
|
||||
* serves as a wrapper and provides useful methods for setting and retrieving data to/from them
|
||||
*/
|
||||
class DhcpV6Option : public TLVRecord<uint16_t, uint16_t>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the option raw data (byte array)
|
||||
* @param[in] optionRawData A pointer to the option raw data
|
||||
*/
|
||||
DhcpV6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
virtual ~DhcpV6Option() { }
|
||||
|
||||
/**
|
||||
* @return The option type converted to ::DhcpV6OptionType enum
|
||||
*/
|
||||
DhcpV6OptionType getType() const;
|
||||
|
||||
/**
|
||||
* @return The raw option value (byte array) as a hex string
|
||||
*/
|
||||
std::string getValueAsHexString() const;
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const;
|
||||
size_t getDataSize() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DhcpV6OptionBuilder
|
||||
* A class for building DHCPv6 options. This builder receives the option parameters in its c'tor,
|
||||
* builds the DHCPv6 option raw buffer and provides a build() method to get a DhcpV6Option object out of it
|
||||
*/
|
||||
class DhcpV6OptionBuilder : public TLVRecordBuilder
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A c'tor for building DHCPv6 options from a string representing the hex stream of the raw byte value.
|
||||
* The DhcpV6Option object can later be retrieved by calling build()
|
||||
* @param[in] optionType DHCPv6 option type
|
||||
* @param[in] optionValueAsHexStream The value as a hex stream string
|
||||
*/
|
||||
DhcpV6OptionBuilder(DhcpV6OptionType optionType, const std::string& optionValueAsHexStream) :
|
||||
TLVRecordBuilder(static_cast<uint16_t>(optionType), optionValueAsHexStream, true) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building DHCPv6 options from a byte array representing their value. The DhcpV6Option object can be later
|
||||
* retrieved by calling build()
|
||||
* @param[in] optionType DHCPv6 option type
|
||||
* @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way.
|
||||
* @param[in] optionValueLen Option value length in bytes
|
||||
*/
|
||||
DhcpV6OptionBuilder(DhcpV6OptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) :
|
||||
TLVRecordBuilder(static_cast<uint16_t>(optionType), optionValue, optionValueLen) {}
|
||||
|
||||
/**
|
||||
* Build the DhcpV6Option object out of the parameters defined in the c'tor
|
||||
* @return The DhcpV6Option object
|
||||
*/
|
||||
DhcpV6Option build() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct dhcpv6_header
|
||||
* Represents the basic DHCPv6 protocol header
|
||||
*/
|
||||
struct dhcpv6_header
|
||||
{
|
||||
/** DHCPv6 message type */
|
||||
uint8_t messageType;
|
||||
/** DHCPv6 transaction ID (first byte) */
|
||||
uint8_t transactionId1;
|
||||
/** DHCPv6 transaction ID (second byte) */
|
||||
uint8_t transactionId2;
|
||||
/** DHCPv6 transaction ID (last byte) */
|
||||
uint8_t transactionId3;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DhcpV6Layer
|
||||
* Represents a DHCPv6 (Dynamic Host Configuration Protocol version 6) protocol layer
|
||||
*/
|
||||
class DhcpV6Layer : public Layer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
DhcpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from scratch
|
||||
* @param[in] messageType A DHCPv6 message type to be set
|
||||
* @param[in] transactionId The transaction ID to be set. Notice the transaction ID is 3-byte long so the value shouldn't exceed 0xFFFFFF
|
||||
*/
|
||||
DhcpV6Layer(DhcpV6MessageType messageType, uint32_t transactionId);
|
||||
|
||||
/**
|
||||
* @return The message type of this DHCPv6 message
|
||||
*/
|
||||
DhcpV6MessageType getMessageType() const;
|
||||
|
||||
/**
|
||||
* @return The string value of the message type of this DHCPv6 message
|
||||
*/
|
||||
std::string getMessageTypeAsString() const;
|
||||
|
||||
/**
|
||||
* Set the message type for this layer
|
||||
* @param[in] messageType The message type to set
|
||||
* @return No return value
|
||||
*/
|
||||
void setMessageType(DhcpV6MessageType messageType);
|
||||
|
||||
/**
|
||||
* @return The transaction ID of this DHCPv6 message
|
||||
*/
|
||||
uint32_t getTransactionID() const;
|
||||
|
||||
/**
|
||||
* Set the transaction ID for this DHCPv6 message
|
||||
* @param[in] transactionId The transaction ID value to set
|
||||
* @return No return value
|
||||
*/
|
||||
void setTransactionID(uint32_t transactionId) const;
|
||||
|
||||
/**
|
||||
* @return The first DHCPv6 option in the packet. If there are no DHCPv6 options the returned value will contain
|
||||
* a logical NULL (DhcpV6Option#isNull() == true)
|
||||
*/
|
||||
DhcpV6Option getFirstOptionData() const;
|
||||
|
||||
/**
|
||||
* Get the DHCPv6 option that comes after a given option. If the given option was the last one, the
|
||||
* returned value will contain a logical NULL (DhcpV6Option#isNull() == true)
|
||||
* @param[in] dhcpv6Option A given DHCPv6 option
|
||||
* @return A DhcpV6Option object containing the option data that comes next, or logical NULL if the given DHCPv6
|
||||
* option: (1) was the last one; (2) contains a logical NULL or (3) doesn't belong to this packet
|
||||
*/
|
||||
DhcpV6Option getNextOptionData(DhcpV6Option dhcpv6Option) const;
|
||||
|
||||
/**
|
||||
* Get a DHCPv6 option by type
|
||||
* @param[in] option DHCPv6 option type
|
||||
* @return A DhcpV6OptionType object containing the first DHCP option data that matches this type, or logical NULL
|
||||
* (DhcpV6Option#isNull() == true) if no such option found
|
||||
*/
|
||||
DhcpV6Option getOptionData(DhcpV6OptionType option) const;
|
||||
|
||||
/**
|
||||
* @return The number of DHCPv6 options in this layer
|
||||
*/
|
||||
size_t getOptionCount() const;
|
||||
|
||||
/**
|
||||
* Add a new DHCPv6 option at the end of the layer
|
||||
* @param[in] optionBuilder A DhcpV6OptionBuilder object that contains the requested DHCPv6 option data to add
|
||||
* @return A DhcpV6Option object containing the newly added DHCP option data or logical NULL
|
||||
* (DhcpV6Option#isNull() == true) if addition failed
|
||||
*/
|
||||
DhcpV6Option addOption(const DhcpV6OptionBuilder& optionBuilder);
|
||||
|
||||
/**
|
||||
* Add a new DHCPv6 option after an existing one
|
||||
* @param[in] optionBuilder A DhcpV6OptionBuilder object that contains the requested DHCPv6 option data to add
|
||||
* @param[in] optionType The DHCPv6 option type which the newly added option will come after
|
||||
* @return A DhcpV6Option object containing the newly added DHCPv6 option data or logical NULL
|
||||
* (DhcpV6Option#isNull() == true) if addition failed
|
||||
*/
|
||||
DhcpV6Option addOptionAfter(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType);
|
||||
|
||||
/**
|
||||
* Add a new DHCPv6 option before an existing one
|
||||
* @param[in] optionBuilder A DhcpV6OptionBuilder object that contains the requested DHCPv6 option data to add
|
||||
* @param[in] optionType The DHCPv6 option type which the newly added option will come before
|
||||
* @return A DhcpV6Option object containing the newly added DHCPv6 option data or logical NULL
|
||||
* (DhcpV6Option#isNull() == true) if addition failed
|
||||
*/
|
||||
DhcpV6Option addOptionBefore(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType);
|
||||
|
||||
/**
|
||||
* Remove an existing DHCPv6 option from the layer
|
||||
* @param[in] optionType The DHCPv6 option type to remove
|
||||
* @return True if DHCPv6 option was successfully removed or false if type wasn't found or if removal failed
|
||||
*/
|
||||
bool removeOption(DhcpV6OptionType optionType);
|
||||
|
||||
/**
|
||||
* Remove all DHCPv6 options in this layer
|
||||
* @return True if all DHCPv6 options were successfully removed or false if removal failed for some reason
|
||||
*/
|
||||
bool removeAllOptions();
|
||||
|
||||
/**
|
||||
* A static method that checks whether a port is considered as a DHCPv6 port
|
||||
* @param[in] port The port number to check
|
||||
* @return True if this is a DHCPv6 port number, false otherwise
|
||||
*/
|
||||
static inline bool isDhcpV6Port(uint16_t port);
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of an DHCPv6 layer
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @return True if the data is valid and can represent an DHCPv6 layer
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (DhcpV6Layer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return The size of @ref dhcpv6_header + size of options
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
private:
|
||||
uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(dhcpv6_header); }
|
||||
dhcpv6_header* getDhcpHeader() const { return (dhcpv6_header*)m_Data; }
|
||||
DhcpV6Option addOptionAt(const DhcpV6OptionBuilder& optionBuilder, int offset);
|
||||
|
||||
TLVRecordReader<DhcpV6Option> m_OptionReader;
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool DhcpV6Layer::isDhcpV6Port(uint16_t port)
|
||||
{
|
||||
return (port == 546) || (port == 547);
|
||||
|
||||
}
|
||||
|
||||
bool DhcpV6Layer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
return dataLen >= sizeof(dhcpv6_header);
|
||||
}
|
||||
|
||||
}
|
||||
# endif // PACKETPP_DHCPV6_LAYER
|
||||
565
pcappp/include/pcapplusplus/DnsLayer.h
Normal file
565
pcappp/include/pcapplusplus/DnsLayer.h
Normal file
@@ -0,0 +1,565 @@
|
||||
#ifndef PACKETPP_DNS_LAYER
|
||||
#define PACKETPP_DNS_LAYER
|
||||
|
||||
#include "DnsLayerEnums.h"
|
||||
#include "DnsResource.h"
|
||||
#include "DnsResourceData.h"
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct dnshdr
|
||||
* Represents the fixed part of the DNS header, meaning the part that doesn't include the DNS data (queries, answers, authorities
|
||||
* and additional records)
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct dnshdr
|
||||
{
|
||||
/** DNS query identification */
|
||||
uint16_t transactionID;
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
uint16_t
|
||||
/** Recursion desired flag */
|
||||
recursionDesired:1,
|
||||
/** Truncated flag */
|
||||
truncation:1,
|
||||
/** Authoritative answer flag */
|
||||
authoritativeAnswer:1,
|
||||
/** Operation Code */
|
||||
opcode:4,
|
||||
/** Query/Response flag */
|
||||
queryOrResponse:1,
|
||||
/** Return Code */
|
||||
responseCode:4,
|
||||
/** Checking disabled flag */
|
||||
checkingDisabled:1,
|
||||
/** Authenticated data flag */
|
||||
authenticData:1,
|
||||
/** Zero flag (Reserved) */
|
||||
zero:1,
|
||||
/** Recursion available flag */
|
||||
recursionAvailable:1;
|
||||
#elif (BYTE_ORDER == BIG_ENDIAN)
|
||||
uint16_t
|
||||
/** Query/Response flag */
|
||||
queryOrResponse:1,
|
||||
/** Operation Code */
|
||||
opcode:4,
|
||||
/** Authoritative answer flag */
|
||||
authoritativeAnswer:1,
|
||||
/** Truncated flag */
|
||||
truncation:1,
|
||||
/** Recursion desired flag */
|
||||
recursionDesired:1,
|
||||
/** Recursion available flag */
|
||||
recursionAvailable:1,
|
||||
/** Zero flag (Reserved) */
|
||||
zero:1,
|
||||
/** Authenticated data flag */
|
||||
authenticData:1,
|
||||
/** Checking disabled flag */
|
||||
checkingDisabled:1,
|
||||
/** Return Code */
|
||||
responseCode:4;
|
||||
#endif
|
||||
/** Number of DNS query records in packet */
|
||||
uint16_t numberOfQuestions;
|
||||
/** Number of DNS answer records in packet */
|
||||
uint16_t numberOfAnswers;
|
||||
/** Number of authority records in packet */
|
||||
uint16_t numberOfAuthority;
|
||||
/** Number of additional records in packet */
|
||||
uint16_t numberOfAdditional;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
// forward declarations
|
||||
class DnsQuery;
|
||||
class IDnsResource;
|
||||
class DnsResource;
|
||||
class IDnsResourceData;
|
||||
|
||||
|
||||
/**
|
||||
* @class DnsLayer
|
||||
* Represents the DNS protocol layer
|
||||
*/
|
||||
class DnsLayer : public Layer
|
||||
{
|
||||
friend class IDnsResource;
|
||||
friend class DnsQuery;
|
||||
friend class DnsResource;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no records
|
||||
*/
|
||||
DnsLayer();
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer
|
||||
* @param[in] other The DNS layer to copy from
|
||||
*/
|
||||
DnsLayer(const DnsLayer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator for this layer
|
||||
* @param[in] other The DNS layer to assign
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
DnsLayer& operator=(const DnsLayer& other);
|
||||
|
||||
virtual ~DnsLayer();
|
||||
|
||||
/**
|
||||
* Get a pointer to the DNS header (as opposed to the DNS data which is the queries, answers, etc. Data can be retrieved through the
|
||||
* other methods of this layer. Notice the return value points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref dnshdr
|
||||
*/
|
||||
dnshdr* getDnsHeader() const;
|
||||
|
||||
/**
|
||||
* Searches for a DNS query by its name field. Notice this method returns only a query which its name equals to the requested name. If
|
||||
* several queries match the requested name, the first one will be returned. If no queries match the requested name, NULL will be returned
|
||||
* @param[in] name The name of the query to search
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return The first matching DNS query or NULL if no queries were found
|
||||
*/
|
||||
DnsQuery* getQuery(const std::string& name, bool exactMatch) const;
|
||||
|
||||
/**
|
||||
* @return The first DNS query in the packet or NULL if packet doesn't contain any queries
|
||||
*/
|
||||
DnsQuery* getFirstQuery() const;
|
||||
|
||||
/**
|
||||
* Get the DNS query following a certain query
|
||||
* @param[in] query A pointer to a DNS query that exist in the packet
|
||||
* @return The DNS query following 'query'. If 'query' is NULL or 'query' is the last query in the packet NULL will be returned
|
||||
*/
|
||||
DnsQuery* getNextQuery(DnsQuery* query) const;
|
||||
|
||||
/**
|
||||
* @return The number of DNS queries in the packet
|
||||
*/
|
||||
size_t getQueryCount() const;
|
||||
|
||||
/**
|
||||
* Add a new DNS query to the layer
|
||||
* @param[in] name The value that shall be set in the name field of the query
|
||||
* @param[in] dnsType The value that shall be set in the DNS type field of the query
|
||||
* @param[in] dnsClass The value that shall be set in the DNS class field of the query
|
||||
* @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error log message will be
|
||||
* printed in this case)
|
||||
*/
|
||||
DnsQuery* addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass);
|
||||
|
||||
/**
|
||||
* Add a new DNS query similar to an already existing DNS query. All query fields will be copied from the existing query
|
||||
* @param[in] copyQuery The record to create the new record from. copyQuery won't be changed in any way
|
||||
* @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error log message will be
|
||||
* printed in this case)
|
||||
*/
|
||||
DnsQuery* addQuery(DnsQuery* const copyQuery);
|
||||
|
||||
/**
|
||||
* Remove an existing query by name. If several queries matches the name, the first match will be removed
|
||||
* @param[in] queryNameToRemove The name of the query to remove
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return True if query was found and successfully removed or false if query was not found or couldn't be removed
|
||||
*/
|
||||
bool removeQuery(const std::string& queryNameToRemove, bool exactMatch);
|
||||
|
||||
/**
|
||||
* Remove an existing query
|
||||
* @param[in] queryToRemove A pointer to the query to remove
|
||||
* @return True if query was found and successfully removed or false if query was not found or couldn't be removed
|
||||
*/
|
||||
bool removeQuery(DnsQuery* queryToRemove);
|
||||
|
||||
/**
|
||||
* Searches for a DNS answer by its name field. Notice this method returns only an answer which its name equals to the requested name. If
|
||||
* several answers match the requested name, the first one will be returned. If no answers match the requested name, NULL will be returned
|
||||
* @param[in] name The name of the answer to search
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return The first matching DNS answer or NULL if no answers were found
|
||||
*/
|
||||
DnsResource* getAnswer(const std::string& name, bool exactMatch) const;
|
||||
|
||||
/**
|
||||
* @return The first DNS answer in the packet or NULL if packet doesn't contain any answers
|
||||
*/
|
||||
DnsResource* getFirstAnswer() const;
|
||||
|
||||
/**
|
||||
* Get the DNS answer following a certain answer
|
||||
* @param[in] answer A pointer to a DNS answer that exist in the packet
|
||||
* @return The DNS answer following 'answer'. If 'answer' is NULL or 'answer' is the last answer in the packet NULL will be returned
|
||||
*/
|
||||
DnsResource* getNextAnswer(DnsResource* answer) const;
|
||||
|
||||
/**
|
||||
* @return The number of DNS answers in the packet
|
||||
*/
|
||||
size_t getAnswerCount() const;
|
||||
|
||||
/**
|
||||
* Add a new DNS answer to the layer
|
||||
* @param[in] name The value that shall be set in the name field of the answer
|
||||
* @param[in] dnsType The value that shall be set in the DNS type field of the answer
|
||||
* @param[in] dnsClass The value that shall be set in the DNS class field of the answer
|
||||
* @param[in] ttl The value that shall be set in the 'time-to-leave' field of the answer
|
||||
* @param[in] data The answer data to be set. The type of the data should match the type of the DNS record
|
||||
* (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData()
|
||||
* for more info on this
|
||||
* @return A pointer to the newly created DNS answer or NULL if answer could not be created (an appropriate error log message will be
|
||||
* printed in this case)
|
||||
*/
|
||||
DnsResource* addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data);
|
||||
|
||||
/**
|
||||
* Add a new DNS answer similar to an already existing DNS answer. All answer fields will be copied from the existing answer
|
||||
* @param[in] copyAnswer The record to create the new record from. copyAnswer won't be changed in any way
|
||||
* @return A pointer to the newly created DNS answer or NULL if query could not be created (an appropriate error log message will be
|
||||
* printed in this case)
|
||||
*/
|
||||
DnsResource* addAnswer(DnsResource* const copyAnswer);
|
||||
|
||||
/**
|
||||
* Remove an existing answer by name. If several answers matches the name, the first match will be removed
|
||||
* @param[in] answerNameToRemove The name of the answer to remove
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return True if answer was found and successfully removed or false if answer was not found or couldn't be removed
|
||||
*/
|
||||
bool removeAnswer(const std::string& answerNameToRemove, bool exactMatch);
|
||||
|
||||
/**
|
||||
* Remove an existing answer
|
||||
* @param[in] answerToRemove A pointer to the answer to remove
|
||||
* @return True if answer was found and successfully removed or false if answer was not found or couldn't be removed
|
||||
*/
|
||||
bool removeAnswer(DnsResource* answerToRemove);
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a DNS authority by its name field. Notice this method returns only an authority which its name equals to the requested name. If
|
||||
* several authorities match the requested name, the first one will be returned. If no authorities match the requested name, NULL will be returned
|
||||
* @param[in] name The name of the authority to search
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return The first matching DNS authority or NULL if no authorities were found
|
||||
*/
|
||||
DnsResource* getAuthority(const std::string& name, bool exactMatch) const;
|
||||
|
||||
/**
|
||||
* @return The first DNS authority in the packet or NULL if packet doesn't contain any authorities
|
||||
*/
|
||||
DnsResource* getFirstAuthority() const;
|
||||
|
||||
/**
|
||||
* Get the DNS authority following a certain authority
|
||||
* @param[in] authority A pointer to a DNS authority that exist in the packet
|
||||
* @return The DNS authority following 'authority'. If 'authority' is NULL or 'authority' is the last authority in the packet NULL will be returned
|
||||
*/
|
||||
DnsResource* getNextAuthority(DnsResource* authority) const;
|
||||
|
||||
/**
|
||||
* @return The number of DNS authorities in the packet
|
||||
*/
|
||||
size_t getAuthorityCount() const;
|
||||
|
||||
/**
|
||||
* Add a new DNS authority to the layer
|
||||
* @param[in] name The value that shall be set in the name field of the authority
|
||||
* @param[in] dnsType The value that shall be set in the DNS type field of the authority
|
||||
* @param[in] dnsClass The value that shall be set in the DNS class field of the authority
|
||||
* @param[in] ttl The value that shall be set in the 'time-to-leave' field of the authority
|
||||
* @param[in] data The authority data to be set. The type of the data should match the type of the DNS record
|
||||
* (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData()
|
||||
* for more info on this
|
||||
* @return A pointer to the newly created DNS authority or NULL if authority could not be created (an appropriate error log message will be
|
||||
* printed in this case)
|
||||
*/
|
||||
DnsResource* addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data);
|
||||
|
||||
/**
|
||||
* Add a new DNS authority similar to an already existing DNS authority. All authority fields will be copied from the existing authority
|
||||
* @param[in] copyAuthority The record to create the new record from. copyAuthority won't be changed in any way
|
||||
* @return A pointer to the newly created DNS authority or NULL if query could not be created (an appropriate error log message will be
|
||||
* printed in this case)
|
||||
*/
|
||||
DnsResource* addAuthority(DnsResource* const copyAuthority);
|
||||
|
||||
/**
|
||||
* Remove an existing authority by name. If several authorities matches the name, the first match will be removed
|
||||
* @param[in] authorityNameToRemove The name of the authority to remove
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return True if authority was found and successfully removed or false if authority was not found or couldn't be removed
|
||||
*/
|
||||
bool removeAuthority(const std::string& authorityNameToRemove, bool exactMatch);
|
||||
|
||||
/**
|
||||
* Remove an existing authority
|
||||
* @param[in] authorityToRemove A pointer to the authority to remove
|
||||
* @return True if authority was found and successfully removed or false if authority was not found or couldn't be removed
|
||||
*/
|
||||
bool removeAuthority(DnsResource* authorityToRemove);
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a DNS additional record by its name field. Notice this method returns only an additional record which its name equals to
|
||||
* the requested name. If several additional records match the requested name, the first one will be returned. If no additional records
|
||||
* match the requested name, NULL will be returned
|
||||
* @param[in] name The name of the additional record to search
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return The first matching DNS additional record or NULL if no additional records were found
|
||||
*/
|
||||
DnsResource* getAdditionalRecord(const std::string& name, bool exactMatch) const;
|
||||
|
||||
/**
|
||||
* @return The first DNS additional record in the packet or NULL if packet doesn't contain any additional records
|
||||
*/
|
||||
DnsResource* getFirstAdditionalRecord() const;
|
||||
|
||||
/**
|
||||
* Get the DNS additional record following a certain additional record
|
||||
* @param[in] additionalRecord A pointer to a DNS additional record that exist in the packet
|
||||
* @return The DNS additional record following 'additionalRecord'. If 'additionalRecord' is NULL or 'additionalRecord' is the
|
||||
* last additional record in the packet NULL will be returned
|
||||
*/
|
||||
DnsResource* getNextAdditionalRecord(DnsResource* additionalRecord) const;
|
||||
|
||||
/**
|
||||
* @return The number of DNS additional records in the packet
|
||||
*/
|
||||
size_t getAdditionalRecordCount() const;
|
||||
|
||||
/**
|
||||
* Add a new DNS additional record to the layer
|
||||
* @param[in] name The value that shall be set in the name field of the additional record
|
||||
* @param[in] dnsType The value that shall be set in the DNS type field of the additional record
|
||||
* @param[in] dnsClass The value that shall be set in the DNS class field of the additional record
|
||||
* @param[in] ttl The value that shall be set in the 'time-to-leave' field of the additional record
|
||||
* @param[in] data The additional record data to be set. The type of the data should match the type of the DNS record
|
||||
* (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData()
|
||||
* for more info on this
|
||||
* @return A pointer to the newly created DNS additional record or NULL if additional record could not be created (an appropriate error
|
||||
* log message will be printed in this case)
|
||||
*/
|
||||
DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data);
|
||||
|
||||
/**
|
||||
* Add a new DNS additional record to the layer that doesn't have DNS class and TTL. Instead these bytes may contains some arbitrary
|
||||
* data. In the future I may add support for these kinds of additional data records. For now, these bytes are set as raw
|
||||
* @param[in] name The value that shall be set in the name field of the additional record
|
||||
* @param[in] dnsType The value that shall be set in the DNS type field of the additional record
|
||||
* @param[in] customData1 Two bytes of the arbitrary data that will be set in the offset usually used for the DNS class
|
||||
* @param[in] customData2 Four bytes of the arbitrary data that will be set in the offset usually used for the TTL
|
||||
* @param[in] data The additional record data to be set. The type of the data should match the type of the DNS record.
|
||||
* (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData()
|
||||
* for more info on this
|
||||
* @return A pointer to the newly created DNS additional record or NULL if additional record could not be created (an appropriate error
|
||||
* log message will be printed in this case)
|
||||
*/
|
||||
DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, uint32_t customData2, IDnsResourceData* data);
|
||||
|
||||
/**
|
||||
* Add a new DNS additional record similar to an already existing DNS additional record. All additional record fields will be copied from the
|
||||
* existing additional record
|
||||
* @param[in] copyAdditionalRecord The record to create the new record from. copyAdditionalRecord won't be changed in any way
|
||||
* @return A pointer to the newly created DNS additional record or NULL if query could not be created (an appropriate error log message will
|
||||
* be printed in this case)
|
||||
*/
|
||||
DnsResource* addAdditionalRecord(DnsResource* const copyAdditionalRecord);
|
||||
|
||||
/**
|
||||
* Remove an existing additional record by name. If several additional records matches the name, the first match will be removed
|
||||
* @param[in] additionalRecordNameToRemove The name of the additional record to remove
|
||||
* @param[in] exactMatch Indicate whether to match the whole name or just a part of it
|
||||
* @return True if additional record was found and successfully removed or false if additional record was not found or couldn't be removed
|
||||
*/
|
||||
bool removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch);
|
||||
|
||||
/**
|
||||
* Remove an existing additional record
|
||||
* @param[in] additionalRecordToRemove A pointer to the additional record to remove
|
||||
* @return True if additional record was found and successfully removed or false if additional record was not found or couldn't be removed
|
||||
*/
|
||||
bool removeAdditionalRecord(DnsResource* additionalRecordToRemove);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (DnsLayer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return The size of the DNS data in the packet including he DNS header and size of all queries, answers, authorities and additional
|
||||
* records
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; } //No layer above DNS
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as DNS
|
||||
* @param[in] port The port number to be checked
|
||||
* @return True if the port is associated with the DNS protocol
|
||||
*/
|
||||
static inline bool isDnsPort(uint16_t port);
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of a DNS packet
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @param[in] dnsOverTcp Should be set to "true" if this is DNS is over TCP, otherwise set to "false"
|
||||
* (which is also the default value)
|
||||
* @return True if the data is valid and can represent a DNS packet
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen, bool dnsOverTcp = false);
|
||||
|
||||
protected:
|
||||
DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, size_t offsetAdjustment);
|
||||
DnsLayer(size_t offsetAdjustment);
|
||||
|
||||
private:
|
||||
IDnsResource* m_ResourceList;
|
||||
DnsQuery* m_FirstQuery;
|
||||
DnsResource* m_FirstAnswer;
|
||||
DnsResource* m_FirstAuthority;
|
||||
DnsResource* m_FirstAdditional;
|
||||
uint16_t m_OffsetAdjustment;
|
||||
|
||||
size_t getBasicHeaderSize();
|
||||
void init(size_t offsetAdjustment, bool callParseResource);
|
||||
void initNewLayer(size_t offsetAdjustment);
|
||||
|
||||
IDnsResource* getFirstResource(DnsResourceType resType) const;
|
||||
void setFirstResource(DnsResourceType resType, IDnsResource* resource);
|
||||
|
||||
using Layer::extendLayer;
|
||||
bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource* resource);
|
||||
|
||||
using Layer::shortenLayer;
|
||||
bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource);
|
||||
|
||||
IDnsResource* getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, bool exactMatch) const;
|
||||
|
||||
void parseResources();
|
||||
|
||||
DnsResource* addResource(DnsResourceType resType, const std::string& name, DnsType dnsType, DnsClass dnsClass,
|
||||
uint32_t ttl, IDnsResourceData* data);
|
||||
|
||||
bool removeResource(IDnsResource* resourceToRemove);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class DnsOverTcpLayer
|
||||
* Represents the DNS over TCP layer.
|
||||
* DNS over TCP is described here: https://tools.ietf.org/html/rfc7766 .
|
||||
* It is very similar to DNS over UDP, except for one field: TCP message length which is added in the beginning of the message
|
||||
* before the other DNS data properties. The rest of the data is similar.
|
||||
*
|
||||
* Note: DNS over TCP can spread over more than one packet, but this implementation doesn't support this use-case and assumes
|
||||
* the whole message fits in a single packet.
|
||||
*/
|
||||
class DnsOverTcpLayer : public DnsLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
DnsOverTcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: DnsLayer(data, dataLen, prevLayer, packet, sizeof(uint16_t)) {}
|
||||
|
||||
/**
|
||||
* A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no records
|
||||
*/
|
||||
DnsOverTcpLayer() : DnsLayer(sizeof(uint16_t)) {}
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer
|
||||
* @param[in] other The DNS over TCP layer to copy from
|
||||
*/
|
||||
DnsOverTcpLayer(const DnsOverTcpLayer& other) : DnsLayer(other) {}
|
||||
|
||||
/**
|
||||
* @return The value of the TCP message length as described in https://tools.ietf.org/html/rfc7766#section-8
|
||||
*/
|
||||
uint16_t getTcpMessageLength();
|
||||
|
||||
/**
|
||||
* Set the TCP message length value as described in https://tools.ietf.org/html/rfc7766#section-8
|
||||
* @param[in] value The value to set
|
||||
*/
|
||||
void setTcpMessageLength(uint16_t value);
|
||||
|
||||
|
||||
// overridden methods
|
||||
|
||||
/**
|
||||
* Calculate the TCP message length field
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool DnsLayer::isDnsPort(uint16_t port)
|
||||
{
|
||||
switch (port)
|
||||
{
|
||||
case 53:
|
||||
case 5353:
|
||||
case 5355:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DnsLayer::isDataValid(const uint8_t* data, size_t dataLen, bool dnsOverTcp)
|
||||
{
|
||||
size_t minSize = sizeof(dnshdr) + (dnsOverTcp ? sizeof(uint16_t) : 0);
|
||||
return dataLen >= minSize;
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_DNS_LAYER */
|
||||
159
pcappp/include/pcapplusplus/DnsLayerEnums.h
Normal file
159
pcappp/include/pcapplusplus/DnsLayerEnums.h
Normal file
@@ -0,0 +1,159 @@
|
||||
#ifndef PACKETPP_DNS_LAYER_ENUMS
|
||||
#define PACKETPP_DNS_LAYER_ENUMS
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* An enum for all possible DNS record types
|
||||
*/
|
||||
enum DnsType
|
||||
{
|
||||
/** IPv4 address record */
|
||||
DNS_TYPE_A = 1,
|
||||
/** Name Server record */
|
||||
DNS_TYPE_NS,
|
||||
/** Obsolete, replaced by MX */
|
||||
DNS_TYPE_MD,
|
||||
/** Obsolete, replaced by MX */
|
||||
DNS_TYPE_MF,
|
||||
/** Canonical name record */
|
||||
DNS_TYPE_CNAME,
|
||||
/** Start of Authority record */
|
||||
DNS_TYPE_SOA,
|
||||
/** mailbox domain name record */
|
||||
DNS_TYPE_MB,
|
||||
/** mail group member record */
|
||||
DNS_TYPE_MG,
|
||||
/** mail rename domain name record */
|
||||
DNS_TYPE_MR,
|
||||
/** NULL record */
|
||||
DNS_TYPE_NULL_R,
|
||||
/** well known service description record */
|
||||
DNS_TYPE_WKS,
|
||||
/** Pointer record */
|
||||
DNS_TYPE_PTR,
|
||||
/** Host information record */
|
||||
DNS_TYPE_HINFO,
|
||||
/** mailbox or mail list information record */
|
||||
DNS_TYPE_MINFO,
|
||||
/** Mail exchanger record */
|
||||
DNS_TYPE_MX,
|
||||
/** Text record */
|
||||
DNS_TYPE_TXT,
|
||||
/** Responsible person record */
|
||||
DNS_TYPE_RP,
|
||||
/** AFS database record */
|
||||
DNS_TYPE_AFSDB,
|
||||
/** DNS X25 resource record */
|
||||
DNS_TYPE_X25,
|
||||
/** Integrated Services Digital Network record */
|
||||
DNS_TYPE_ISDN,
|
||||
/** Route Through record */
|
||||
DNS_TYPE_RT,
|
||||
/** network service access point address record */
|
||||
DNS_TYPE_NSAP,
|
||||
/** network service access point address pointer record */
|
||||
DNS_TYPE_NSAP_PTR,
|
||||
/** Signature record */
|
||||
DNS_TYPE_SIG,
|
||||
/** Key record */
|
||||
DNS_TYPE_KEY,
|
||||
/** Mail Mapping Information record */
|
||||
DNS_TYPE_PX,
|
||||
/** DNS Geographical Position record */
|
||||
DNS_TYPE_GPOS,
|
||||
/** IPv6 address record */
|
||||
DNS_TYPE_AAAA,
|
||||
/** Location record */
|
||||
DNS_TYPE_LOC,
|
||||
/** Obsolete record */
|
||||
DNS_TYPE_NXT,
|
||||
/** DNS Endpoint Identifier record */
|
||||
DNS_TYPE_EID,
|
||||
/** DNS Nimrod Locator record */
|
||||
DNS_TYPE_NIMLOC,
|
||||
/** Service locator record */
|
||||
DNS_TYPE_SRV,
|
||||
/** Asynchronous Transfer Mode address record */
|
||||
DNS_TYPE_ATMA,
|
||||
/** Naming Authority Pointer record */
|
||||
DNS_TYPE_NAPTR,
|
||||
/** Key eXchanger record */
|
||||
DNS_TYPE_KX,
|
||||
/** Certificate record */
|
||||
DNS_TYPE_CERT,
|
||||
/** Obsolete, replaced by AAAA type */
|
||||
DNS_TYPE_A6,
|
||||
/** Delegation Name record */
|
||||
DNS_TYPE_DNAM,
|
||||
/** Kitchen sink record */
|
||||
DNS_TYPE_SINK,
|
||||
/** Option record */
|
||||
DNS_TYPE_OPT,
|
||||
/** Address Prefix List record */
|
||||
DNS_TYPE_APL,
|
||||
/** Delegation signer record */
|
||||
DNS_TYPE_DS,
|
||||
/** SSH Public Key Fingerprint record */
|
||||
DNS_TYPE_SSHFP,
|
||||
/** IPsec Key record */
|
||||
DNS_TYPE_IPSECKEY,
|
||||
/** DNSSEC signature record */
|
||||
DNS_TYPE_RRSIG,
|
||||
/** Next-Secure record */
|
||||
DNS_TYPE_NSEC,
|
||||
/** DNS Key record */
|
||||
DNS_TYPE_DNSKEY,
|
||||
/** DHCP identifier record */
|
||||
DNS_TYPE_DHCID,
|
||||
/** NSEC record version 3 */
|
||||
DNS_TYPE_NSEC3,
|
||||
/** NSEC3 parameters */
|
||||
DNS_TYPE_NSEC3PARAM,
|
||||
/** All cached records */
|
||||
DNS_TYPE_ALL = 255
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An enum for all possible DNS classes
|
||||
*/
|
||||
enum DnsClass
|
||||
{
|
||||
/** Internet class */
|
||||
DNS_CLASS_IN = 1,
|
||||
/** Internet class with QU flag set to True */
|
||||
DNS_CLASS_IN_QU = 32769,
|
||||
/** Chaos class */
|
||||
DNS_CLASS_CH = 3,
|
||||
/** Hesiod class */
|
||||
DNS_CLASS_HS = 4,
|
||||
/** ANY class */
|
||||
DNS_CLASS_ANY = 255
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An enum for representing the 4 types of possible DNS records
|
||||
*/
|
||||
enum DnsResourceType
|
||||
{
|
||||
/** DNS query record */
|
||||
DnsQueryType = 0,
|
||||
/** DNS answer record */
|
||||
DnsAnswerType = 1,
|
||||
/** DNS authority record */
|
||||
DnsAuthorityType = 2,
|
||||
/** DNS additional record */
|
||||
DnsAdditionalType = 3
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_DNS_LAYER_ENUMS
|
||||
237
pcappp/include/pcapplusplus/DnsResource.h
Normal file
237
pcappp/include/pcapplusplus/DnsResource.h
Normal file
@@ -0,0 +1,237 @@
|
||||
#ifndef PACKETPP_DNS_RESOURCE
|
||||
#define PACKETPP_DNS_RESOURCE
|
||||
|
||||
#include "DnsLayer.h"
|
||||
#include "DnsLayerEnums.h"
|
||||
#include "DnsResourceData.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
// forward declarations
|
||||
class DnsLayer;
|
||||
class IDnsResourceData;
|
||||
class DnsResourceDataPtr;
|
||||
|
||||
|
||||
/**
|
||||
* @class IDnsResource
|
||||
* An abstract class for representing all types of DNS records. This class gives access to all available record data such as DNS type, class,
|
||||
* name, type of record, etc. The DnsLayer holds an instance of (inherited type of) this class for each DNS record in the DNS packet
|
||||
*/
|
||||
class IDnsResource
|
||||
{
|
||||
protected:
|
||||
friend class DnsLayer;
|
||||
friend class IDnsResourceData;
|
||||
|
||||
protected:
|
||||
DnsLayer* m_DnsLayer;
|
||||
size_t m_OffsetInLayer;
|
||||
IDnsResource* m_NextResource;
|
||||
std::string m_DecodedName;
|
||||
size_t m_NameLength;
|
||||
uint8_t* m_ExternalRawData;
|
||||
|
||||
IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer);
|
||||
|
||||
IDnsResource(uint8_t* emptyRawData);
|
||||
|
||||
size_t decodeName(const char* encodedName, char* result, int iteration = 1);
|
||||
void encodeName(const std::string& decodedName, char* result, size_t& resultLen);
|
||||
|
||||
IDnsResource* getNextResource() const { return m_NextResource; }
|
||||
void setNexResource(IDnsResource* next) { m_NextResource = next; }
|
||||
|
||||
uint8_t* getRawData() const;
|
||||
|
||||
void setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer);
|
||||
|
||||
public:
|
||||
|
||||
virtual ~IDnsResource() {}
|
||||
|
||||
/**
|
||||
* @return The DNS type of this record
|
||||
*/
|
||||
DnsType getDnsType() const;
|
||||
|
||||
/**
|
||||
* Set DNS type for this record
|
||||
* @param[in] newType The type to set
|
||||
*/
|
||||
void setDnsType(DnsType newType);
|
||||
|
||||
/**
|
||||
* @return The DNS class of this record
|
||||
*/
|
||||
DnsClass getDnsClass() const;
|
||||
|
||||
/**
|
||||
* Set DNS class for this record
|
||||
* @param[in] newClass The class to set
|
||||
*/
|
||||
void setDnsClass(DnsClass newClass);
|
||||
|
||||
/**
|
||||
* @return The name of this record
|
||||
*/
|
||||
const std::string& getName() const { return m_DecodedName; }
|
||||
|
||||
/**
|
||||
* @return The record name's offset in the packet
|
||||
*/
|
||||
size_t getNameOffset() const { return m_OffsetInLayer; }
|
||||
|
||||
/**
|
||||
* Set the name of this record. The input name can be a standard hostname (e.g 'google.com'), or it may contain
|
||||
* a pointer to another string in the packet (as explained here: http://www.zytrax.com/books/dns/ch15/#name).
|
||||
* The pointer is used to reduce the DNS packet size and avoid unnecessary duplications. In case you
|
||||
* want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where '#{offset}'
|
||||
* is a the offset from the start of the layer. For example: if the string 'yahoo.com' already appears in offset
|
||||
* 12 in the packet and you want to set the name of the current record to 'my.subdomain.yahoo.com' you may use
|
||||
* the following string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12.<BR>
|
||||
* Please notice the new name can be shorter or longer of the old name, so this method can cause the packet to be
|
||||
* shorten or extended
|
||||
* @param[in] newName The name to set
|
||||
* @return True if name was set successfully or false if input string is malformed or if an error occurred
|
||||
*/
|
||||
bool setName(const std::string& newName);
|
||||
|
||||
|
||||
// abstract methods
|
||||
|
||||
/**
|
||||
* @return The total size in bytes of this record
|
||||
*/
|
||||
virtual size_t getSize() const = 0;
|
||||
|
||||
/**
|
||||
* @return The type of this record (query, answer, authority, additional)
|
||||
*/
|
||||
virtual DnsResourceType getType() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class DnsQuery
|
||||
* Representing a DNS query record
|
||||
*/
|
||||
class DnsQuery : public IDnsResource
|
||||
{
|
||||
friend class DnsLayer;
|
||||
|
||||
private:
|
||||
DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) {}
|
||||
|
||||
DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) {}
|
||||
|
||||
public:
|
||||
virtual ~DnsQuery() {}
|
||||
|
||||
// implementation of abstract methods
|
||||
virtual size_t getSize() const { return m_NameLength + 2 * sizeof(uint16_t); }
|
||||
virtual DnsResourceType getType() const { return DnsQueryType; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class DnsResource
|
||||
* Representing DNS record other than DNS query
|
||||
*/
|
||||
class DnsResource : public IDnsResource
|
||||
{
|
||||
friend class DnsLayer;
|
||||
|
||||
private:
|
||||
DnsResourceType m_ResourceType;
|
||||
|
||||
DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) : IDnsResource(dnsLayer, offsetInLayer) { m_ResourceType = resourceType; }
|
||||
|
||||
DnsResource(uint8_t* emptyRawData, DnsResourceType resType) : IDnsResource(emptyRawData), m_ResourceType(resType) {}
|
||||
|
||||
public:
|
||||
virtual ~DnsResource() {}
|
||||
|
||||
/**
|
||||
* @return The time-to-leave value for this record
|
||||
*/
|
||||
uint32_t getTTL() const;
|
||||
|
||||
/**
|
||||
* Set time-to-leave value for this record
|
||||
* @param[in] newTTL The new TTL value to set
|
||||
*/
|
||||
void setTTL(uint32_t newTTL);
|
||||
|
||||
/**
|
||||
* @return The data length value for this record (taken from the "data length" field of the record)
|
||||
*/
|
||||
size_t getDataLength() const;
|
||||
|
||||
/**
|
||||
* @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed that the
|
||||
* smart pointer will always point to an object and never to NULL. The specific object type depends on the DNS type of this record:<BR>
|
||||
* - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains the IPv4 address<BR>
|
||||
* - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that contains the IPv6 address<BR>
|
||||
* - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the return value is
|
||||
* a smart pointer to StringDnsResourceData object that contains the name<BR>
|
||||
* - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains the MX data (preference and
|
||||
* mail exchange name)<BR>
|
||||
* - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte array of the data
|
||||
*/
|
||||
DnsResourceDataPtr getData() const;
|
||||
|
||||
/**
|
||||
* @return The offset of data in the DNS layer
|
||||
*/
|
||||
size_t getDataOffset() const;
|
||||
|
||||
/**
|
||||
* Set resource data. The given IDnsResourceData input object is validated against the DNS type of the resource. For example: if DNS type is A
|
||||
* and data isn't of type IPv4DnsResourceData (which contains the IPv4 address) a log error will be printed and the method will return false.
|
||||
* This method currently supports the following DNS types:<BR>
|
||||
* - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 address
|
||||
* - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 address
|
||||
* - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a pointer to StringDnsResourceData
|
||||
* object that contains a host name, e.g: 'www.google.com'
|
||||
* - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the MX data
|
||||
* - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string (valid hex string means a string
|
||||
* which has an even number of characters representing a valid hex data. e.g: '0d0a45569a9b')
|
||||
* @param[in] data The pointer to the data object, as described above
|
||||
* @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the packet (appropriate error log is
|
||||
* printed in all cases)
|
||||
*/
|
||||
bool setData(IDnsResourceData* data);
|
||||
|
||||
/**
|
||||
* Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the
|
||||
* user to receive these bytes
|
||||
* @return The value stored in this place
|
||||
*/
|
||||
uint16_t getCustomDnsClass() const;
|
||||
|
||||
/**
|
||||
* Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the
|
||||
* user to set these bytes
|
||||
* @param[in] customValue The value to set
|
||||
*/
|
||||
void setCustomDnsClass(uint16_t customValue);
|
||||
|
||||
// implementation of abstract methods
|
||||
virtual size_t getSize() const { return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); }
|
||||
virtual DnsResourceType getType() const { return m_ResourceType; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_DNS_RESOURCE
|
||||
399
pcappp/include/pcapplusplus/DnsResourceData.h
Normal file
399
pcappp/include/pcapplusplus/DnsResourceData.h
Normal file
@@ -0,0 +1,399 @@
|
||||
#ifndef PACKETPP_DNS_RESOURCE_DATA
|
||||
#define PACKETPP_DNS_RESOURCE_DATA
|
||||
|
||||
#include "DnsResource.h"
|
||||
#include "IpAddress.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
//Visual studio has always been stupid about returning something useful for __cplusplus
|
||||
//Only recently was this fixed - and even then it requires a specific hack to the command line during build
|
||||
//Its easier/more consistent to test _MSC_VER in VS
|
||||
//https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017
|
||||
|
||||
#if __cplusplus > 199711L || _MSC_VER >= 1800 //Maybe this can be 1600 for VS2010
|
||||
#define PCPP_SMART_PTR(T) std::unique_ptr<T>
|
||||
#else
|
||||
#define PCPP_SMART_PTR(T) std::auto_ptr<T>
|
||||
#endif
|
||||
|
||||
// forward declarations
|
||||
class IDnsResource;
|
||||
|
||||
/**
|
||||
* @class IDnsResourceData
|
||||
* A wrapper class for storing DNS RR (resource record) data. This is the base class which introduces several abstract
|
||||
* methods for derived classes to implement for setting and retrieving the stored data. Each derived class will store
|
||||
* different type of DNS RR data and implement these methods accordingly (for example: IPv4/IPv6 addresses, MX data,
|
||||
* hostnames, raw byte data etc.)
|
||||
*/
|
||||
class IDnsResourceData
|
||||
{
|
||||
protected:
|
||||
|
||||
// unimplemented private copy c'tor
|
||||
IDnsResourceData(const IDnsResourceData& other);
|
||||
IDnsResourceData() { }
|
||||
|
||||
size_t decodeName(const char* encodedName, char* result, IDnsResource* dnsResource) const;
|
||||
void encodeName(const std::string& decodedName, char* result, size_t& resultLen, IDnsResource* dnsResource) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* A virtual d'tor, does nothing
|
||||
*/
|
||||
virtual ~IDnsResourceData() { }
|
||||
|
||||
/**
|
||||
* A templated method which takes a class that derives from IDnsResourceData as the template argument and
|
||||
* checks whether this instance is of this type
|
||||
* @return True if this instance is of the requested type, false otherwise
|
||||
*/
|
||||
template <class IDnsResourceDataType>
|
||||
bool isTypeOf() const { return dynamic_cast<const IDnsResourceDataType*>(this) != NULL; }
|
||||
|
||||
/**
|
||||
* A templated method which take a class that derives from IDnsResourceData as the template argument and tries to
|
||||
* cast the current instance as that type
|
||||
* @return A pointer to the current instance casted as the requested type or NULL if this instance isn't of this type
|
||||
*/
|
||||
template <class IDnsResourceDataType>
|
||||
IDnsResourceDataType* castAs() { return dynamic_cast<IDnsResourceDataType*>(this); }
|
||||
|
||||
/**
|
||||
* @return A string that represents the current DNS RR data
|
||||
*/
|
||||
virtual std::string toString() const = 0;
|
||||
|
||||
/**
|
||||
* Convert the DNS RR data into a byte array
|
||||
* @param[out] arr A pointer to a pre-allocated byte array where the result will be written to
|
||||
* @param[out] arrLength A reference to a 2-byte number where the result array length will be written to
|
||||
* @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored
|
||||
* @return True if the DNS RR data was successfully converted into a byte array and written to the given array or
|
||||
* false if stored DNS RR data is invalid or if it could not be written to the given array
|
||||
*/
|
||||
virtual bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class DnsResourceDataPtr
|
||||
* A smart pointer class that holds pointers of type IDnsResourceData. This object is used in DnsResource#getData()
|
||||
*/
|
||||
class DnsResourceDataPtr : public PCPP_SMART_PTR(IDnsResourceData)
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor to this class
|
||||
* @param[in] ptr A pointer to IDnsResourceData
|
||||
*/
|
||||
DnsResourceDataPtr(IDnsResourceData* ptr) : PCPP_SMART_PTR(IDnsResourceData)(ptr) {}
|
||||
|
||||
//Visual studio has always been stupid about returning something useful for __cplusplus
|
||||
//Only recently was this fixed - and even then it requires a specific hack to the command line during build
|
||||
//Its easier/more consistent to test _MSC_VER in VS
|
||||
//https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017
|
||||
|
||||
#if __cplusplus <= 199711L && _MSC_VER < 1800 //Maybe this can be 1600 for VS2010
|
||||
DnsResourceDataPtr(const DnsResourceDataPtr& other) : PCPP_SMART_PTR(IDnsResourceData)((DnsResourceDataPtr&)other) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A templated method which takes a class that derives from IDnsResourceData as the template argument and
|
||||
* checks whether the pointer stored in this object is of this type
|
||||
* @return True if the stored pointer is of the requested type, false otherwise
|
||||
*/
|
||||
template <class IDnsResourceDataType>
|
||||
bool isTypeOf() const { return get()->isTypeOf<IDnsResourceDataType>(); }
|
||||
|
||||
/**
|
||||
* A templated method which take a class that derives from IDnsResourceData as the template argument and tries to
|
||||
* cast the pointer stored in this object as that type
|
||||
* @return A pointer to the stored pointer casted as the requested type or NULL if it isn't of this type
|
||||
*/
|
||||
template <class IDnsResourceDataType>
|
||||
IDnsResourceDataType* castAs() { return get()->castAs<IDnsResourceDataType>();}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class StringDnsResourceData
|
||||
* A class that represents DNS RR string data, mainly used in DNS RRs that store hostnames (like CNAME, DNAME, NS, etc.)
|
||||
*/
|
||||
class StringDnsResourceData : public IDnsResourceData
|
||||
{
|
||||
private:
|
||||
std::string m_Data;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] data The string data to store in this object. If this string represents a hostname it's possible
|
||||
* to include a pointer to another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name).
|
||||
* These pointers are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include pointers
|
||||
* in a hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is the offset from the
|
||||
* start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset 12 in the packet and you want
|
||||
* to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'.
|
||||
* This will result in writing 'my.subdomain' and a pointer to offset 12
|
||||
*/
|
||||
StringDnsResourceData(const std::string& data) { m_Data = data; }
|
||||
|
||||
StringDnsResourceData(const uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource);
|
||||
|
||||
~StringDnsResourceData() {}
|
||||
|
||||
/**
|
||||
* Equality operator overload for this class that compares the strings stored in each object
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if the string data is the same in both objects, false otherwise
|
||||
*/
|
||||
bool operator==(const StringDnsResourceData& other) const { return m_Data == other.m_Data; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const { return m_Data; }
|
||||
bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4DnsResourceData
|
||||
* A class that represents DNS RR IPv4 data, mainly used in DNS RRs of type ::DNS_TYPE_A
|
||||
*/
|
||||
class IPv4DnsResourceData : public IDnsResourceData
|
||||
{
|
||||
private:
|
||||
IPv4Address m_Data;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] dataPtr A byte array of size 4 that contains an IPv4 address (each byte represents 1 octet)
|
||||
* @param[in] dataLen The byte array size, expected to be 4
|
||||
*/
|
||||
IPv4DnsResourceData(const uint8_t* dataPtr, size_t dataLen);
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] addr The IPv4 address to store in this object
|
||||
*/
|
||||
IPv4DnsResourceData(const IPv4Address& addr) : m_Data(addr) {}
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] addrAsString A string representation of an IPv4 address to store in this object
|
||||
*/
|
||||
IPv4DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) {}
|
||||
|
||||
/**
|
||||
* Equality operator overload for this class that compares the IPv4 addresses stored in each object
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if IPv4 addresses are the same in both objects, false otherwise
|
||||
*/
|
||||
bool operator==(const IPv4DnsResourceData& other) const { return m_Data == other.m_Data; }
|
||||
|
||||
/**
|
||||
* @return The IPv4 address stored in this object
|
||||
*/
|
||||
IPv4Address getIpAddress() const { return m_Data; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const { return m_Data.toString(); }
|
||||
bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6DnsResourceData
|
||||
* A class that represents DNS RR IPv6 data, mainly used in DNS RRs of type ::DNS_TYPE_AAAA
|
||||
*/
|
||||
class IPv6DnsResourceData : public IDnsResourceData
|
||||
{
|
||||
private:
|
||||
IPv6Address m_Data;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] dataPtr A byte array of size 16 that contains an IPv6 address (each byte represents 1 octet)
|
||||
* @param[in] dataLen The byte array size, expected to be 16
|
||||
*/
|
||||
IPv6DnsResourceData(const uint8_t* dataPtr, size_t dataLen);
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] addr The IPv6 address to store in this object
|
||||
*/
|
||||
IPv6DnsResourceData(const IPv6Address& addr) : m_Data(addr) {}
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] addrAsString A string representation of an IPv6 address to store in this object
|
||||
*/
|
||||
IPv6DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) {}
|
||||
|
||||
/**
|
||||
* Equality operator overload for this class that compares the IPv6 addresses stored in each object
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if IPv6 addresses are the same in both objects, false otherwise
|
||||
*/
|
||||
bool operator==(const IPv6DnsResourceData& other) const { return m_Data == other.m_Data; }
|
||||
|
||||
/**
|
||||
* @return The IPv6 address stored in this object
|
||||
*/
|
||||
IPv6Address getIpAddress() const { return m_Data; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const { return m_Data.toString(); }
|
||||
bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class MxDnsResourceData
|
||||
* A class that represents DNS RR mail exchange (MX) data, used in DNS RRs of type ::DNS_TYPE_MX
|
||||
*/
|
||||
class MxDnsResourceData : public IDnsResourceData
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A struct that represents mail exchange (MX) data
|
||||
*/
|
||||
struct MxData
|
||||
{
|
||||
/** Preference value */
|
||||
uint16_t preference;
|
||||
/** Mail exchange hostname */
|
||||
std::string mailExchange;
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] dataPtr A byte array that contains the raw MX data (as written in the DNS packet)
|
||||
* @param[in] dataLen The byte array size
|
||||
* @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored
|
||||
*/
|
||||
MxDnsResourceData(uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource);
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] preference The MX preference value to store in this object
|
||||
* @param[in] mailExchange The MX hostname value to store in this object. It's possible to include a pointer to
|
||||
* another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). These pointers
|
||||
* are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include pointers
|
||||
* in the hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is the offset
|
||||
* from the start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset 12 in the
|
||||
* packet and you want to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following string:
|
||||
* 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12
|
||||
*/
|
||||
MxDnsResourceData(const uint16_t& preference, const std::string& mailExchange);
|
||||
|
||||
~MxDnsResourceData() {}
|
||||
|
||||
/**
|
||||
* Equality operator overload for this class that compares the MX data stored in each object
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if MX data is the same in both objects, meaning both preference and MX hostname are the same,
|
||||
* false otherwise
|
||||
*/
|
||||
bool operator==(const MxDnsResourceData& other) const;
|
||||
|
||||
/**
|
||||
* @return The MX data stored in this object
|
||||
*/
|
||||
MxData getMxData() const { return m_Data; }
|
||||
|
||||
/**
|
||||
* Set the MX data stored in this object
|
||||
* @param[in] preference The MX preference value to store in this object
|
||||
* @param[in] mailExchange The MX hostname value to store in this object
|
||||
*/
|
||||
void setMxData(uint16_t preference, std::string mailExchange);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* A string representation of the MX data stored in this object. The string format is as follows:
|
||||
* 'pref: {preference_value}; mx: {mail_exchange_hostname_value}'
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const;
|
||||
|
||||
private:
|
||||
MxData m_Data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class GenericDnsResourceData
|
||||
* A class that represents generic DNS RR data which cannot be represented in any of the other classes. It stores the
|
||||
* DNS RR data as byte array
|
||||
*/
|
||||
class GenericDnsResourceData : public IDnsResourceData
|
||||
{
|
||||
private:
|
||||
uint8_t* m_Data;
|
||||
size_t m_DataLen;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] dataPtr A byte array that contains the raw data (as it written in the DNS packet). The data will be
|
||||
* copied from this byte array to the object
|
||||
* @param[in] dataLen The byte array size
|
||||
*/
|
||||
GenericDnsResourceData(uint8_t* dataPtr, size_t dataLen);
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] dataAsHexString A hex string that represents the DNS RR data
|
||||
*/
|
||||
GenericDnsResourceData(const std::string& dataAsHexString);
|
||||
|
||||
/**
|
||||
* A copy c'tor for this class
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
GenericDnsResourceData(const GenericDnsResourceData& other);
|
||||
|
||||
~GenericDnsResourceData() { if (m_Data != NULL) delete [] m_Data; }
|
||||
|
||||
GenericDnsResourceData& operator=(const GenericDnsResourceData& other);
|
||||
|
||||
/**
|
||||
* Equality operator overload for this class that compares the raw data stored in each object
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if data is the same in both objects, meaning byte streams are equal, false otherwise
|
||||
*/
|
||||
bool operator==(const GenericDnsResourceData& other) const;
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_DNS_RESOURCE_DATA
|
||||
809
pcappp/include/pcapplusplus/DpdkDevice.h
Normal file
809
pcappp/include/pcapplusplus/DpdkDevice.h
Normal file
@@ -0,0 +1,809 @@
|
||||
#ifndef PCAPPP_DPDK_DEVICE
|
||||
#define PCAPPP_DPDK_DEVICE
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include "MacAddress.h"
|
||||
#include "SystemUtils.h"
|
||||
#include "Device.h"
|
||||
#include "MBufRawPacket.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file and DpdkDeviceList.h provide PcapPlusPlus C++ wrapper for DPDK (stands for data-plan development kit). What is
|
||||
* DPDK? as quoting from http://dpdk.org: "DPDK is a set of libraries and drivers for fast packet processing... These libraries can be used to:
|
||||
* receive and send packets within the minimum number of CPU cycles (usually less than 80 cycles)... develop fast packet capture algorithms
|
||||
* (tcpdump-like)... run third-party fast path stacks... Some packet processing functions have been benchmarked up to hundreds million
|
||||
* frames per second, using 64-byte packets with a PCIe NIC"<BR>
|
||||
* As DPDK API is written in C, PcapPlusPlus wraps the main functionality in a C++ easy-to-use classes which should have minimum affect
|
||||
* on performance and packet processing rate. In addition it brings DPDK to the PcapPlusPlus framework and API so you can use DPDK
|
||||
* together with other PcapPlusPlus features such as packet parsing and editing, etc.<BR>
|
||||
* So how DPDK basically works? in order to boost packet processing performance on a commodity server DPDK is bypassing the Linux kernel.
|
||||
* All the packet processing activity happens in the user space so basically packets are delivered from NIC hardware queues directly
|
||||
* to user-space shared memory without going through the kernel. In addition DPDK uses polling instead of handling interrupts for each
|
||||
* arrived packet (as interrupts create some delays). Other methods to boost packets processing implemented by DPDK are using Hugepages to
|
||||
* decrease the size of TLB that results in a much faster virtual to physical page conversion, thread affinity to bind threads to a
|
||||
* specific core, lock-free user-space multi-core synchronization using rings data structures and NUMA awareness to avoid expensive data
|
||||
* transfers between sockets.<BR>
|
||||
* Not every NIC supports kernel-bypass capabilities so DPDK cannot work with any NIC. The list of supported NICs are in DPDK's web-site
|
||||
* http://dpdk.org/doc/nics . For each such NIC the DPDK framework provides a module that called poll-mode-driver (PMD in short) that
|
||||
* enables this NIC to the working with DPDK. PcapPlusPlus wasn't tested with most PMDs but all of them should theoretically work as
|
||||
* PcapPlusPlus doesn't change the PMD behavior<BR>
|
||||
* DPDK has another basic data-structure called mbuf. An mbuf is DPDK wrapper struct for network packets. When working with packets
|
||||
* in DPDK you actually work with mbufs. The mbuf contains the packet data (obviously) but also some metadata on the packet such
|
||||
* as the DPDK port it was captured on, packet ref-count (which allows it to be referenced by several objects), etc. One important
|
||||
* concept is that DPDK doesn't allocate mbufs on-the-fly but uses mbuf pools. These pools is allocated on application startup and
|
||||
* used throughout the application. The goal of this, of course, is increasing packet processing performance as allocating memory has
|
||||
* its cost. So pool size is important and varies between applications. For example: an application that stores packets in memory
|
||||
* has to have a large pool of mbufs so mbufs doesn't run-out. PcapPlusPlus enables to choose the pool size at startup<BR>
|
||||
* <BR>
|
||||
* PcapPlusPlus main wrapper classes for DPDK are:
|
||||
* - DpdkDevice - a class that wraps a DPDK port and provides all capabilities of receiving and sending packets to this port
|
||||
* - DpdkDeviceList - a singleton class that initializes the DPDK infrastructure and creates DpdkDevice instances to all available ports.
|
||||
* In addition it allows starting and stopping of worker threads
|
||||
* - MBufRawPacket - a child class to RawPacket which customizes it for working with mbuf
|
||||
* - In addition PcapPlusPlus provides a shell script to initialize DPDK prerequisites: setup-dpdk.sh. This is an easy-to-use script
|
||||
* that sets up huge-pages, loads DPDK kernel module and sets up the NICs that will be used by DPDK. This script must run before an
|
||||
* application that uses DPDK runs. If you forgot to run it the application will fail with an appropriate error that will remind
|
||||
*
|
||||
* DPDK initialization using PcapPlusPlus:
|
||||
* - Before application runs: run the setup-dpdk.sh script
|
||||
* - On application startup call DpdkDeviceList#initDpdk() static method to initialize DPDK infrastructure and DpdkDevice instances
|
||||
* - Open the relevant DpdkDevice(s)
|
||||
* - Send & receive packets...
|
||||
*/
|
||||
|
||||
struct rte_mbuf;
|
||||
struct rte_mempool;
|
||||
struct rte_eth_conf;
|
||||
struct rte_eth_dev_tx_buffer;
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
#define DPDK_MAX_RX_QUEUES 16
|
||||
#define DPDK_MAX_TX_QUEUES 16
|
||||
|
||||
class DpdkDeviceList;
|
||||
class DpdkDevice;
|
||||
|
||||
/**
|
||||
* An enum describing all PMD (poll mode driver) types supported by DPDK. For more info about these PMDs please visit the DPDK web-site
|
||||
*/
|
||||
enum DpdkPMDType
|
||||
{
|
||||
/** Unknown PMD type */
|
||||
PMD_UNKNOWN,
|
||||
/** Link Bonding for 1GbE and 10GbE ports to allow the aggregation of multiple (slave) NICs into a single logical interface*/
|
||||
PMD_BOND,
|
||||
/** Intel E1000 PMD */
|
||||
PMD_E1000EM,
|
||||
/** Intel 1GbE PMD */
|
||||
PMD_IGB,
|
||||
/** Intel 1GbE virtual function PMD */
|
||||
PMD_IGBVF,
|
||||
/** Cisco enic (UCS Virtual Interface Card) PMD */
|
||||
PMD_ENIC,
|
||||
/** Intel fm10k PMD */
|
||||
PMD_FM10K,
|
||||
/** Intel 40GbE PMD */
|
||||
PMD_I40E,
|
||||
/** Intel 40GbE virtual function PMD */
|
||||
PMD_I40EVF,
|
||||
/** Intel 10GbE PMD */
|
||||
PMD_IXGBE,
|
||||
/** Intel 10GbE virtual function PMD */
|
||||
PMD_IXGBEVF,
|
||||
/** Mellanox ConnectX-3, ConnectX-3 Pro PMD */
|
||||
PMD_MLX4,
|
||||
/** Null PMD */
|
||||
PMD_NULL,
|
||||
/** pcap file PMD */
|
||||
PMD_PCAP,
|
||||
/** ring-based (memory) PMD */
|
||||
PMD_RING,
|
||||
/** VirtIO PMD */
|
||||
PMD_VIRTIO,
|
||||
/** VMWare VMXNET3 PMD */
|
||||
PMD_VMXNET3,
|
||||
/** Xen Project PMD */
|
||||
PMD_XENVIRT,
|
||||
/** AF_PACKET PMD */
|
||||
PMD_AF_PACKET
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef OnDpdkPacketsArriveCallback
|
||||
* A callback that is called when a burst of packets are captured by DpdkDevice
|
||||
* @param[in] packets A pointer to an array of MBufRawPacket
|
||||
* @param[in] numOfPackets The length of the array
|
||||
* @param[in] threadId The thread/core ID who captured the packets
|
||||
* @param[in] device A pointer to the DpdkDevice who captured the packets
|
||||
* @param[in] userCookie The user cookie assigned by the user in DpdkDevice#startCaptureSingleThread() or DpdkDevice#startCaptureMultiThreads
|
||||
*/
|
||||
typedef void (*OnDpdkPacketsArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, DpdkDevice* device, void* userCookie);
|
||||
|
||||
/**
|
||||
* @class DpdkDevice
|
||||
* Encapsulates a DPDK port and enables receiving and sending packets using DPDK as well as getting interface info & status, packet
|
||||
* statistics, etc. This class has no public c'tor as it's constructed by DpdkDeviceList during initialization.<BR>
|
||||
*
|
||||
* __RX/TX queues__: modern NICs provide hardware load-balancing for packets. This means that each packet received by the NIC is hashed
|
||||
* by one or more parameter (IP address, port, etc.) and goes into one of several RX queues provided by the NIC. This enables
|
||||
* applications to work in a multi-core environment where each core can read packets from different RX queue(s). Same goes for TX
|
||||
* queues: it's possible to write packets to different TX queues and the NIC is taking care of sending them to the network.
|
||||
* Different NICs provide different number of RX and TX queues. DPDK supports this capability and enables the user to open the
|
||||
* DPDK port (DpdkDevice) with a single or multiple RX and TX queues. When receiving packets the user can decide from which RX queue
|
||||
* to read from, and when transmitting packets the user can decide to which TX queue to send them to. RX/TX queues are configured
|
||||
* when opening the DpdkDevice (see openMultiQueues())<BR>
|
||||
*
|
||||
* __Capturing packets__: there are two ways to capture packets using DpdkDevice:
|
||||
* - using worker threads (see DpdkDeviceList#startDpdkWorkerThreads() ). When using this method the worker should use the
|
||||
* DpdkDevice#receivePackets() methods to get packets from the DpdkDevice
|
||||
* - by setting a callback which is invoked each time a burst of packets arrives. For more details see
|
||||
* DpdkDevice#startCaptureSingleThread()
|
||||
*
|
||||
* __Sending packets:__ DpdkDevice has various methods for sending packets. They enable sending raw packets, parsed packets, etc.
|
||||
* for all opened TX queues. Also, DPDK provides an option to buffer TX packets and send them only when reaching a certain threshold (you
|
||||
* can read more about it here: http://dpdk.org/doc/api/rte__ethdev_8h.html#a0e941a74ae1b1b886764bc282458d946). DpdkDevice supports that
|
||||
* option as well. See DpdkDevice#sendPackets()<BR>
|
||||
*
|
||||
* __Get interface info__: DpdkDevice provides all kind of information on the interface/device such as MAC address, MTU, link status,
|
||||
* PCI address, PMD (poll-mode-driver) used for this port, etc. In addition it provides RX/TX statistics when receiving or sending
|
||||
* packets<BR>
|
||||
*
|
||||
* __Known limitations:__
|
||||
* - BPF filters are currently not supported by this device (as opposed to other PcapPlusPlus device types. This means that the
|
||||
* device cannot filter packets before they get to the user
|
||||
* - It's not possible to set or change NIC load-balancing method. DPDK provides this capability but it's still not
|
||||
* supported by DpdkDevice
|
||||
*/
|
||||
class DpdkDevice : public IDevice
|
||||
{
|
||||
friend class DpdkDeviceList;
|
||||
friend class MBufRawPacket;
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum describing all RSS (Receive Side Scaling) hash functions supported in DPDK. Notice not all
|
||||
* PMDs support all types of hash functions
|
||||
*/
|
||||
enum DpdkRssHashFunction
|
||||
{
|
||||
/** IPv4 based flow */
|
||||
RSS_IPV4 = 0x1,
|
||||
/** Fragmented IPv4 based flow */
|
||||
RSS_FRAG_IPV4 = 0x2,
|
||||
/** Non-fragmented IPv4 + TCP flow */
|
||||
RSS_NONFRAG_IPV4_TCP = 0x4,
|
||||
/** Non-fragmented IPv4 + UDP flow */
|
||||
RSS_NONFRAG_IPV4_UDP = 0x8,
|
||||
/** Non-fragmented IPv4 + SCTP flow */
|
||||
RSS_NONFRAG_IPV4_SCTP = 0x10,
|
||||
/** Non-fragmented IPv4 + non TCP/UDP/SCTP flow */
|
||||
RSS_NONFRAG_IPV4_OTHER = 0x20,
|
||||
/** IPv6 based flow */
|
||||
RSS_IPV6 = 0x40,
|
||||
/** Fragmented IPv6 based flow */
|
||||
RSS_FRAG_IPV6 = 0x80,
|
||||
/** Non-fragmented IPv6 + TCP flow */
|
||||
RSS_NONFRAG_IPV6_TCP = 0x100,
|
||||
/** Non-fragmented IPv6 + UDP flow */
|
||||
RSS_NONFRAG_IPV6_UDP = 0x200,
|
||||
/** Non-fragmented IPv6 + SCTP flow */
|
||||
RSS_NONFRAG_IPV6_SCTP = 0x400,
|
||||
/** Non-fragmented IPv6 + non TCP/UDP/SCTP flow */
|
||||
RSS_NONFRAG_IPV6_OTHER = 0x800,
|
||||
/** L2 payload based flow */
|
||||
RSS_L2_PAYLOAD = 0x1000,
|
||||
/** IPv6 Ex based flow */
|
||||
RSS_IPV6_EX = 0x2000,
|
||||
/** IPv6 + TCP Ex based flow */
|
||||
RSS_IPV6_TCP_EX = 0x4000,
|
||||
/** IPv6 + UDP Ex based flow */
|
||||
RSS_IPV6_UDP_EX = 0x8000,
|
||||
/** Consider device port number as a flow differentiator */
|
||||
RSS_PORT = 0x10000,
|
||||
/** VXLAN protocol based flow */
|
||||
RSS_VXLAN = 0x20000,
|
||||
/** GENEVE protocol based flow */
|
||||
RSS_GENEVE = 0x40000,
|
||||
/** NVGRE protocol based flow */
|
||||
RSS_NVGRE = 0x80000
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct DpdkDeviceConfiguration
|
||||
* A struct that contains user configurable parameters for opening a DpdkDevice. All of these parameters have default values so
|
||||
* the user doesn't have to use these parameters or understand exactly what is their effect
|
||||
*/
|
||||
struct DpdkDeviceConfiguration
|
||||
{
|
||||
/**
|
||||
* When configuring a DPDK RX queue, DPDK creates descriptors it will use for receiving packets from the network to this RX queue.
|
||||
* This parameter enables to configure the number of descriptors that will be created for each RX queue
|
||||
*/
|
||||
uint16_t receiveDescriptorsNumber;
|
||||
|
||||
/**
|
||||
* When configuring a DPDK TX queue, DPDK creates descriptors it will use for transmitting packets to the network through this TX queue.
|
||||
* This parameter enables to configure the number of descriptors that will be created for each TX queue
|
||||
*/
|
||||
uint16_t transmitDescriptorsNumber;
|
||||
|
||||
/**
|
||||
* Set the TX buffer flush timeout in millisecond (only relevant if sending packets using DPDK TX buffer mechanism).
|
||||
* A value of zero means no timeout
|
||||
*/
|
||||
uint16_t flushTxBufferTimeout;
|
||||
|
||||
/**
|
||||
* When configuring a DPDK device, DPDK supports to activate the Receive Side Scaling (RSS) feature to distribute traffic between the RX queues
|
||||
* This parameter points to an array holding the RSS key to use for hashing specific header fields of received packets.
|
||||
* The length of this array should be indicated by rssKeyLength below.
|
||||
* Supplying a NULL value causes a default random hash key to be used by the device driver
|
||||
*/
|
||||
uint8_t* rssKey;
|
||||
|
||||
/**
|
||||
* This parameter indicates the length in bytes of the array pointed by rssKey.
|
||||
* This length will be checked in i40e only. Others assume 40 bytes to be used.
|
||||
*/
|
||||
uint8_t rssKeyLength;
|
||||
|
||||
/**
|
||||
* This parameter enables to configure the types of packets to which the RSS hashing must be applied. The value
|
||||
* is a mask composed of hash functions described in DpdkRssHashFunction enum. Supplying a value equal to zero
|
||||
* disables the RSS feature. Supplying a value equal to -1 enables all hash functions supported by this PMD
|
||||
*/
|
||||
uint64_t rssHashFunction;
|
||||
|
||||
/**
|
||||
* A c'tor for this struct
|
||||
* @param[in] receiveDescriptorsNumber An optional parameter for defining the number of RX descriptors that will be allocated for each RX queue.
|
||||
* Default value is 128
|
||||
* @param[in] transmitDescriptorsNumber An optional parameter for defining the number of TX descriptors that will be allocated for each TX queue.
|
||||
* Default value is 512
|
||||
* @param[in] flushTxBufferTimeout An optional parameter for setting TX buffer timeout in usec. Default value is 100 usec
|
||||
* @param[in] rssHashFunction This parameter enable to configure the types of packets to which the RSS hashing must be applied.
|
||||
* The value provided here should be a mask composed of hash functions described in DpdkRssHashFunction enum. The default value is IPv4 and IPv6
|
||||
* @param[in] rssKey A pointer to an array holding the RSS key to use for hashing specific header of received packets. If not
|
||||
* specified, there is a default key defined inside DpdkDevice
|
||||
* @param[in] rssKeyLength The length in bytes of the array pointed by rssKey. Default value is the length of default rssKey
|
||||
*/
|
||||
DpdkDeviceConfiguration(uint16_t receiveDescriptorsNumber = 128,
|
||||
uint16_t transmitDescriptorsNumber = 512,
|
||||
uint16_t flushTxBufferTimeout = 100,
|
||||
uint64_t rssHashFunction = RSS_IPV4 | RSS_IPV6,
|
||||
uint8_t* rssKey = DpdkDevice::m_RSSKey,
|
||||
uint8_t rssKeyLength = 40)
|
||||
{
|
||||
this->receiveDescriptorsNumber = receiveDescriptorsNumber;
|
||||
this->transmitDescriptorsNumber = transmitDescriptorsNumber;
|
||||
this->flushTxBufferTimeout = flushTxBufferTimeout;
|
||||
this->rssKey = rssKey;
|
||||
this->rssKeyLength = rssKeyLength;
|
||||
this->rssHashFunction = rssHashFunction;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct LinkStatus
|
||||
* A struct that contains the link status of a DpdkDevice (DPDK port). Returned from DpdkDevice#getLinkStatus()
|
||||
*/
|
||||
struct LinkStatus
|
||||
{
|
||||
/** Enum for describing link duplex */
|
||||
enum LinkDuplex
|
||||
{
|
||||
/** Full duplex */
|
||||
FULL_DUPLEX,
|
||||
/** Half duplex */
|
||||
HALF_DUPLEX
|
||||
};
|
||||
|
||||
/** True if link is up, false if it's down */
|
||||
bool linkUp;
|
||||
/** Link speed in Mbps (for example: 10Gbe will show 10000) */
|
||||
int linkSpeedMbps;
|
||||
/** Link duplex (half/full duplex) */
|
||||
LinkDuplex linkDuplex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct RxTxStats
|
||||
* A container for RX/TX statistics
|
||||
*/
|
||||
struct RxTxStats
|
||||
{
|
||||
/** Total number of packets */
|
||||
uint64_t packets;
|
||||
/** Total number of successfully received bytes */
|
||||
uint64_t bytes;
|
||||
/** Packets per second */
|
||||
uint64_t packetsPerSec;
|
||||
/** Bytes per second */
|
||||
uint64_t bytesPerSec;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct DpdkDeviceStats
|
||||
* A container for DpdkDevice statistics
|
||||
*/
|
||||
struct DpdkDeviceStats
|
||||
{
|
||||
/** DpdkDevice ID */
|
||||
uint8_t devId;
|
||||
/** The timestamp of when the stats were written */
|
||||
timespec timestamp;
|
||||
/** RX statistics per RX queue */
|
||||
RxTxStats rxStats[DPDK_MAX_RX_QUEUES];
|
||||
/** TX statistics per TX queue */
|
||||
RxTxStats txStats[DPDK_MAX_RX_QUEUES];
|
||||
/** RX statistics, aggregated for all RX queues */
|
||||
RxTxStats aggregatedRxStats;
|
||||
/** TX statistics, aggregated for all TX queues */
|
||||
RxTxStats aggregatedTxStats;
|
||||
/** Total number of RX packets dropped by H/W because there are no available buffers (i.e RX queues are full) */
|
||||
uint64_t rxPacketsDroppedByHW;
|
||||
/** Total number of erroneous packets */
|
||||
uint64_t rxErroneousPackets;
|
||||
/** Total number of RX mbuf allocation failuers */
|
||||
uint64_t rxMbufAlocFailed;
|
||||
};
|
||||
|
||||
virtual ~DpdkDevice();
|
||||
|
||||
/**
|
||||
* @return The device ID (DPDK port ID)
|
||||
*/
|
||||
int getDeviceId() const { return m_Id; }
|
||||
/**
|
||||
* @return The device name which is in the format of 'DPDK_[PORT-ID]'
|
||||
*/
|
||||
std::string getDeviceName() const { return m_DeviceName; }
|
||||
|
||||
/**
|
||||
* @return The MAC address of the device (DPDK port)
|
||||
*/
|
||||
MacAddress getMacAddress() const { return m_MacAddress; }
|
||||
|
||||
/**
|
||||
* @return The name of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in the DPDK documentation:
|
||||
* http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html
|
||||
*/
|
||||
std::string getPMDName() const { return m_PMDName; }
|
||||
|
||||
/**
|
||||
* @return The enum type of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in the DPDK documentation:
|
||||
* http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html
|
||||
*/
|
||||
DpdkPMDType getPMDType() const { return m_PMDType; }
|
||||
|
||||
/**
|
||||
* @return The PCI address of the device
|
||||
*/
|
||||
std::string getPciAddress() const { return m_PciAddress; }
|
||||
|
||||
/**
|
||||
* @return The device's maximum transmission unit (MTU) in bytes
|
||||
*/
|
||||
uint16_t getMtu() const { return m_DeviceMtu; }
|
||||
|
||||
/**
|
||||
* Set a new maximum transmission unit (MTU) for this device
|
||||
* @param[in] newMtu The new MTU in bytes
|
||||
* @return True if MTU was set successfully, false if operation failed or if PMD doesn't support changing the MTU
|
||||
*/
|
||||
bool setMtu(uint16_t newMtu);
|
||||
|
||||
/**
|
||||
* @return True if this device is a virtual interface (such as VMXNET3, 1G/10G virtual function, etc.), false otherwise
|
||||
*/
|
||||
bool isVirtual() const;
|
||||
|
||||
/**
|
||||
* Get the link status (link up/down, link speed and link duplex)
|
||||
* @param[out] linkStatus A reference to object the result shall be written to
|
||||
*/
|
||||
void getLinkStatus(LinkStatus& linkStatus) const;
|
||||
|
||||
/**
|
||||
* @return The core ID used in this context
|
||||
*/
|
||||
uint32_t getCurrentCoreId() const;
|
||||
|
||||
/**
|
||||
* @return The number of RX queues currently opened for this device (as configured in openMultiQueues() )
|
||||
*/
|
||||
uint16_t getNumOfOpenedRxQueues() const { return m_NumOfRxQueuesOpened; }
|
||||
|
||||
/**
|
||||
* @return The number of TX queues currently opened for this device (as configured in openMultiQueues() )
|
||||
*/
|
||||
uint16_t getNumOfOpenedTxQueues() const { return m_NumOfTxQueuesOpened; }
|
||||
|
||||
/**
|
||||
* @return The total number of RX queues available on this device
|
||||
*/
|
||||
uint16_t getTotalNumOfRxQueues() const { return m_TotalAvailableRxQueues; }
|
||||
|
||||
/**
|
||||
* @return The total number of TX queues available on this device
|
||||
*/
|
||||
uint16_t getTotalNumOfTxQueues() const { return m_TotalAvailableTxQueues; }
|
||||
|
||||
|
||||
/**
|
||||
* Receive raw packets from the network
|
||||
* @param[out] rawPacketsArr A vector where all received packets will be written into
|
||||
* @param[in] rxQueueId The RX queue to receive packets from
|
||||
* @return The number of packets received. If an error occurred 0 will be returned and the error will be printed to log
|
||||
*/
|
||||
uint16_t receivePackets(MBufRawPacketVector& rawPacketsArr, uint16_t rxQueueId) const;
|
||||
|
||||
/**
|
||||
* Receive raw packets from the network. Please notice that in terms of performance, this is the best method to use
|
||||
* for receiving packets because out of all receivePackets overloads this method requires the least overhead and is
|
||||
* almost as efficient as receiving packets directly through DPDK. So if performance is a critical factor in your
|
||||
* application, please use this method
|
||||
* @param[out] rawPacketsArr A pointer to an array of MBufRawPacket pointers where all received packets will be written into. The array is expected to
|
||||
* be allocated by the user and its length should be provided in rawPacketArrLength. Number of packets received will be returned.
|
||||
* Notice it's the user responsibility to free the array and its content when done using it
|
||||
* @param[out] rawPacketArrLength The length of MBufRawPacket pointers array
|
||||
* @param[in] rxQueueId The RX queue to receive packets from
|
||||
* @return The number of packets received. If an error occurred 0 will be returned and the error will be printed to log
|
||||
*/
|
||||
uint16_t receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength, uint16_t rxQueueId) const;
|
||||
|
||||
/**
|
||||
* Receive parsed packets from the network
|
||||
* @param[out] packetsArr A pointer to an allocated array of Packet pointers where all received packets will be written into. The array is expected to
|
||||
* be allocated by the user and its length should be provided in packetsArrLength. Number of packets received will be returned.
|
||||
* Notice it's the user responsibility to free the array and its content when done using it
|
||||
* @param[out] packetsArrLength The length of Packet pointers array
|
||||
* @param[in] rxQueueId The RX queue to receive packets from
|
||||
* @return The number of packets received. If an error occurred 0 will be returned and the error will be printed to log
|
||||
*/
|
||||
uint16_t receivePackets(Packet** packetsArr, uint16_t packetsArrLength, uint16_t rxQueueId) const;
|
||||
|
||||
/**
|
||||
* Send an array of MBufRawPacket to the network. Please notice the following:<BR>
|
||||
* - In terms of performance, this is the best method to use for sending packets because out of all sendPackets overloads
|
||||
* this method requires the least overhead and is almost as efficient as sending the packets directly through DPDK. So if performance
|
||||
* is a critical factor in your application, please use this method
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is typically around 400 packets),
|
||||
* then after reaching this threshold there is a built-in 0.2 sec sleep to let the TX descriptors clean
|
||||
* - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] rawPacketsArr A pointer to an array of MBufRawPacket
|
||||
* @param[in] arrLength The length of the array
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, 0 will be returned.
|
||||
* Also, if TX buffer is being used and packets are buffered, some or all may not be actually sent
|
||||
*/
|
||||
uint16_t sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Send an array of parsed packets to the network. Please notice the following:<BR>
|
||||
* - If some or all of the packets contain raw packets which aren't of type MBufRawPacket, a new temp MBufRawPacket instances
|
||||
* will be created and packet data will be copied to them. This is necessary to allocate mbufs which will store the data to be sent.
|
||||
* If performance is a critical factor please make sure you send parsed packets that contain only raw packets of type MBufRawPacket
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is typically around 400 packets),
|
||||
* then after reaching this threshold there is a built-in 0.2 sec sleep to let the TX descriptors clean
|
||||
* - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] packetsArr A pointer to an array of parsed packet pointers
|
||||
* @param[in] arrLength The length of the array
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, 0 will be returned.
|
||||
* Also, if TX buffer is being used and packets are buffered, some or all may not be actually sent
|
||||
*/
|
||||
uint16_t sendPackets(Packet** packetsArr, uint16_t arrLength, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Send a vector of MBufRawPacket pointers to the network. Please notice the following:<BR>
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is typically around 400 packets),
|
||||
* then after reaching this threshold there is a built-in 0.2 sec sleep to let the TX descriptors clean
|
||||
* - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] rawPacketsVec The vector of raw packet
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, 0 will be returned.
|
||||
* Also, if TX buffer is being used and packets are buffered, some or all may not be actually sent
|
||||
*/
|
||||
uint16_t sendPackets(MBufRawPacketVector& rawPacketsVec, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Send a vector of RawPacket pointers to the network. Please notice the following:<BR>
|
||||
* - If some or all of the raw packets aren't of type MBufRawPacket, a new temp MBufRawPacket instances will be created
|
||||
* and packet data will be copied to them. This is necessary to allocate mbufs which will store the data to be sent. If
|
||||
* performance is a critical factor please make sure you send only raw packets of type MBufRawPacket (or use the sendPackets overload
|
||||
* that sends MBufRawPacketVector)
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is typically around 400 packets),
|
||||
* then after reaching this threshold there is a built-in 0.2 sec sleep to let the TX descriptors clean
|
||||
* - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] rawPacketsVec The vector of raw packet
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, 0 will be returned.
|
||||
* Also, if TX buffer is being used and packets are buffered, some or all may not be actually sent
|
||||
*/
|
||||
uint16_t sendPackets(RawPacketVector& rawPacketsVec, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Send a raw packet to the network. Please notice that if the raw packet isn't of type MBufRawPacket, a new temp MBufRawPacket
|
||||
* will be created and the data will be copied to it. This is necessary to allocate an mbuf which will store the data to be sent.
|
||||
* If performance is a critical factor please make sure you send a raw packet of type MBufRawPacket. Please also notice that the
|
||||
* mbuf used or allocated in this method isn't freed by this method, it will be transparently freed by DPDK
|
||||
* @param[in] rawPacket The raw packet to send
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if the packet wasn't
|
||||
* sent for any other reason. Please notice that when using TX buffers the packet may be buffered and not sent immediately, which
|
||||
* may also result in returning false
|
||||
*/
|
||||
bool sendPacket(RawPacket& rawPacket, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Send a MBufRawPacket to the network. Please notice that the mbuf used in this method isn't freed by this method, it will be
|
||||
* transparently freed by DPDK
|
||||
* @param[in] rawPacket The MBufRawPacket to send
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if the packet wasn't
|
||||
* sent for any other reason. Please notice that when using TX buffers the packet may be buffered and not sent immediately, which
|
||||
* may also result in returning false
|
||||
*/
|
||||
bool sendPacket(MBufRawPacket& rawPacket, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Send a parsed packet to the network. Please notice that the mbuf used or allocated in this method isn't freed by this method,
|
||||
* it will be transparently freed by DPDK
|
||||
* @param[in] packet The parsed packet to send. Please notice that if the packet contains a raw packet which isn't of type
|
||||
* MBufRawPacket, a new temp MBufRawPacket will be created and the data will be copied to it. This is necessary to
|
||||
* allocate an mbuf which will store the data to be sent. If performance is a critical factor please make sure you send a
|
||||
* parsed packet that contains a raw packet of type MBufRawPacket
|
||||
* @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent on. The default is
|
||||
* TX queue 0
|
||||
* @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about DPDK's
|
||||
* TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use this mechanism)
|
||||
* @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if the packet wasn't
|
||||
* sent for any other reason. Please notice that when using TX buffers the packet may be buffered and not sent immediately, which
|
||||
* may also result in returning false
|
||||
*/
|
||||
bool sendPacket(Packet& packet, uint16_t txQueueId = 0, bool useTxBuffer = false);
|
||||
|
||||
/**
|
||||
* Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__
|
||||
* @param[in] filter Not used in this method
|
||||
* @return Always false with a "Filters aren't supported in DPDK device" error message
|
||||
*/
|
||||
bool setFilter(GeneralFilter& filter);
|
||||
|
||||
/**
|
||||
* Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__
|
||||
* @param[in] filterAsString Not used in this method
|
||||
* @return Always false with a "Filters aren't supported in DPDK device" error message
|
||||
*/
|
||||
bool setFilter(std::string filterAsString);
|
||||
|
||||
/**
|
||||
* Open the DPDK device. Notice opening the device only makes it ready to use, it doesn't start packet capturing. This method initializes RX and TX queues,
|
||||
* configures the DPDK port and starts it. Call close() to close the device. The device is opened in promiscuous mode
|
||||
* @param[in] numOfRxQueuesToOpen Number of RX queues to setup. This number must be smaller or equal to the return value of getTotalNumOfRxQueues()
|
||||
* @param[in] numOfTxQueuesToOpen Number of TX queues to setup. This number must be smaller or equal to the return value of getTotalNumOfTxQueues()
|
||||
* @param[in] config Optional parameter for defining special port configuration parameters such as number of receive/transmit descriptors. If not set the default
|
||||
* parameters will be set (see DpdkDeviceConfiguration)
|
||||
* @return True if the device was opened successfully, false if device is already opened, if RX/TX queues configuration failed or of DPDK port
|
||||
* configuration and startup failed
|
||||
*/
|
||||
bool openMultiQueues(uint16_t numOfRxQueuesToOpen, uint16_t numOfTxQueuesToOpen, const DpdkDeviceConfiguration& config = DpdkDeviceConfiguration());
|
||||
|
||||
/**
|
||||
* There are two ways to capture packets using DpdkDevice: one of them is using worker threads (see DpdkDeviceList#startDpdkWorkerThreads() ) and
|
||||
* the other way is setting a callback which is invoked each time a burst of packets is captured. This method implements the second way.
|
||||
* After invoking this method the DpdkDevice enters capture mode and starts capturing packets.
|
||||
* This method assumes there is only 1 RX queue opened for this device, otherwise an error is returned. It then allocates a core and creates 1 thread
|
||||
* that runs in an endless loop and tries to capture packets using DPDK. Each time a burst of packets is captured the user callback is invoked with the user
|
||||
* cookie as a parameter. This loop continues until stopCapture() is called. Notice: since the callback is invoked for every packet burst
|
||||
* using this method can be slower than using worker threads. On the other hand, it's a simpler way comparing to worker threads
|
||||
* @param[in] onPacketsArrive The user callback which will be invoked each time a packet burst is captured by the device
|
||||
* @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be used to pass
|
||||
* information from the user application to the callback
|
||||
* @return True if capture thread started successfully or false if device is already in capture mode, number of opened RX queues isn't equal
|
||||
* to 1, if the method couldn't find an available core to allocate for the capture thread, or if thread invocation failed. In
|
||||
* all of these cases an appropriate error message will be printed
|
||||
*/
|
||||
bool startCaptureSingleThread(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie);
|
||||
|
||||
/**
|
||||
* This method does exactly what startCaptureSingleThread() does, but with more than one RX queue / capturing thread. It's called
|
||||
* with a core mask as a parameter and creates a packet capture thread on every core. Each capturing thread is assigned with a specific
|
||||
* RX queue. This method assumes all cores in the core-mask are available and there are enough opened RX queues to match for each thread.
|
||||
* If these assumptions are not true an error is returned. After invoking all threads, all of them run in an endless loop
|
||||
* and try to capture packets from their designated RX queues. Each time a burst of packets is captured the callback is invoked with the user
|
||||
* cookie and the thread ID that captured the packets
|
||||
* @param[in] onPacketsArrive The user callback which will be invoked each time a burst of packets is captured by the device
|
||||
* @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be used to pass
|
||||
* information from the user application to the callback
|
||||
* @param coreMask The core-mask for creating the cpature threads
|
||||
* @return True if all capture threads started successfully or false if device is already in capture mode, not all cores in the core-mask are
|
||||
* available to DPDK, there are not enough opened RX queues to match all cores in the core-mask, or if thread invocation failed. In
|
||||
* all of these cases an appropriate error message will be printed
|
||||
*/
|
||||
bool startCaptureMultiThreads(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask);
|
||||
|
||||
/**
|
||||
* If device is in capture mode started by invoking startCaptureSingleThread() or startCaptureMultiThreads(), this method
|
||||
* will stop all capturing threads and set the device to non-capturing mode
|
||||
*/
|
||||
void stopCapture();
|
||||
|
||||
/**
|
||||
* @return The number of free mbufs in device's mbufs pool
|
||||
*/
|
||||
int getAmountOfFreeMbufs() const;
|
||||
|
||||
/**
|
||||
* @return The number of mbufs currently in use in device's mbufs pool
|
||||
*/
|
||||
int getAmountOfMbufsInUse() const;
|
||||
|
||||
/**
|
||||
* Retrieve RX/TX statistics from device
|
||||
* @param[out] stats A reference to a DpdkDeviceStats object where stats will be written into
|
||||
*/
|
||||
void getStatistics(DpdkDeviceStats& stats) const;
|
||||
|
||||
/**
|
||||
* Clear device statistics
|
||||
*/
|
||||
void clearStatistics();
|
||||
|
||||
/**
|
||||
* DPDK supports an option to buffer TX packets and send them only when reaching a certain threshold. This method enables
|
||||
* the user to flush a TX buffer for certain TX queue and send the packets stored in it (you can read about it here:
|
||||
* http://dpdk.org/doc/api/rte__ethdev_8h.html#a0e941a74ae1b1b886764bc282458d946). It has the option to flush only
|
||||
* when timeout that was set in DpdkDeviceConfiguration#flushTxBufferTimeout expired or flush immediately regardless
|
||||
* of the timeout. The usage of this method can be in the main loop where you can call this method once every a couple
|
||||
* of iterations to make sure TX buffers are flushed
|
||||
* @param[in] flushOnlyIfTimeoutExpired When set to true, flush will happen only if the timeout defined in
|
||||
* DpdkDeviceConfiguration#flushTxBufferTimeout expired. If set to false flush will happen immediately. Default value
|
||||
* is false
|
||||
* @param[in] txQueueId The TX queue ID to flush its buffer. Default is 0
|
||||
* @return The number of packets sent after buffer was flushed
|
||||
*/
|
||||
uint16_t flushTxBuffer(bool flushOnlyIfTimeoutExpired = false, uint16_t txQueueId = 0);
|
||||
|
||||
/**
|
||||
* Check whether a specific RSS hash function is supported by this device (PMD)
|
||||
* @param[in] rssHF RSS hash function to check
|
||||
* @return True if this hash function is supported, false otherwise
|
||||
*/
|
||||
bool isDeviceSupportRssHashFunction(DpdkRssHashFunction rssHF) const;
|
||||
|
||||
/**
|
||||
* Check whether a mask of RSS hash functions is supported by this device (PMD)
|
||||
* @param[in] rssHFMask RSS hash functions mask to check. This mask should be built from values in DpdkRssHashFunction enum
|
||||
* @return True if all hash functions in this mask are supported, false otherwise
|
||||
*/
|
||||
bool isDeviceSupportRssHashFunction(uint64_t rssHFMask) const;
|
||||
|
||||
/**
|
||||
* @return A mask of all RSS hash functions supported by this device (PMD). This mask is built from values in DpdkRssHashFunction enum.
|
||||
* Value of zero means RSS is not supported by this device
|
||||
*/
|
||||
uint64_t getSupportedRssHashFunctions() const;
|
||||
|
||||
|
||||
//overridden methods
|
||||
|
||||
/**
|
||||
* Overridden method from IPcapDevice. It calls openMultiQueues() with 1 RX queue and 1 TX queue.
|
||||
* Notice opening the device only makes it ready to use, it doesn't start packet capturing. The device is opened in promiscuous mode
|
||||
* @return True if the device was opened successfully, false if device is already opened, if RX/TX queues configuration failed or of DPDK port
|
||||
* configuration and startup failed
|
||||
*/
|
||||
bool open() { return openMultiQueues(1, 1); };
|
||||
|
||||
/**
|
||||
* Close the DpdkDevice. When device is closed it's not possible work with it
|
||||
*/
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
||||
struct DpdkCoreConfiguration
|
||||
{
|
||||
int RxQueueId;
|
||||
bool IsCoreInUse;
|
||||
|
||||
void clear() { RxQueueId = -1; IsCoreInUse = false; }
|
||||
|
||||
DpdkCoreConfiguration() : RxQueueId(-1), IsCoreInUse(false) {}
|
||||
};
|
||||
|
||||
DpdkDevice(int port, uint32_t mBufPoolSize);
|
||||
bool initMemPool(struct rte_mempool*& memPool, const char* mempoolName, uint32_t mBufPoolSize);
|
||||
|
||||
bool configurePort(uint8_t numOfRxQueues, uint8_t numOfTxQueues);
|
||||
bool initQueues(uint8_t numOfRxQueuesToInit, uint8_t numOfTxQueuesToInit);
|
||||
bool startDevice();
|
||||
|
||||
static int dpdkCaptureThreadMain(void* ptr);
|
||||
|
||||
void clearCoreConfiguration();
|
||||
bool initCoreConfigurationByCoreMask(CoreMask coreMask);
|
||||
int getCoresInUseCount() const;
|
||||
|
||||
void setDeviceInfo();
|
||||
|
||||
typedef rte_mbuf* (*PacketIterator)(void* packetStorage, int index);
|
||||
uint16_t sendPacketsInner(uint16_t txQueueId, void* packetStorage, PacketIterator iter, int arrLength, bool useTxBuffer);
|
||||
|
||||
uint64_t convertRssHfToDpdkRssHf(uint64_t rssHF) const;
|
||||
uint64_t convertDpdkRssHfToRssHf(uint64_t dpdkRssHF) const;
|
||||
|
||||
std::string m_DeviceName;
|
||||
DpdkPMDType m_PMDType;
|
||||
std::string m_PMDName;
|
||||
std::string m_PciAddress;
|
||||
|
||||
DpdkDeviceConfiguration m_Config;
|
||||
|
||||
int m_Id;
|
||||
MacAddress m_MacAddress;
|
||||
uint16_t m_DeviceMtu;
|
||||
struct rte_mempool* m_MBufMempool;
|
||||
struct rte_eth_dev_tx_buffer** m_TxBuffers;
|
||||
uint64_t m_TxBufferDrainTsc;
|
||||
uint64_t* m_TxBufferLastDrainTsc;
|
||||
DpdkCoreConfiguration m_CoreConfiguration[MAX_NUM_OF_CORES];
|
||||
uint16_t m_TotalAvailableRxQueues;
|
||||
uint16_t m_TotalAvailableTxQueues;
|
||||
uint16_t m_NumOfRxQueuesOpened;
|
||||
uint16_t m_NumOfTxQueuesOpened;
|
||||
OnDpdkPacketsArriveCallback m_OnPacketsArriveCallback;
|
||||
void* m_OnPacketsArriveUserCookie;
|
||||
bool m_StopThread;
|
||||
|
||||
bool m_WasOpened;
|
||||
|
||||
// RSS key used by the NIC for load balancing the packets between cores
|
||||
static uint8_t m_RSSKey[40];
|
||||
|
||||
mutable DpdkDeviceStats m_PrevStats;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_DPDK_DEVICE */
|
||||
204
pcappp/include/pcapplusplus/DpdkDeviceList.h
Normal file
204
pcappp/include/pcapplusplus/DpdkDeviceList.h
Normal file
@@ -0,0 +1,204 @@
|
||||
#ifndef PCAPPP_DPDK_DEVICE_LIST
|
||||
#define PCAPPP_DPDK_DEVICE_LIST
|
||||
|
||||
#include "SystemUtils.h"
|
||||
#include "DpdkDevice.h"
|
||||
#include "Logger.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* For details about PcapPlusPlus support for DPDK see DpdkDevice.h file description
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class DpdkWorkerThread
|
||||
* There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way is using
|
||||
* a callback which is invoked on each a burst of packets are captured (see DpdkDevice#startCaptureSingleThread() ). This class
|
||||
* is a base class for implementing workers. A worker is basically a class that is activated by DpdkDeviceList#startDpdkWorkerThreads()
|
||||
* and runs on a designated core. When it runs it can do whatever the user wants it to do. The most common use it running in an
|
||||
* endless loop and receive, analyze and send packets using one or more DpdkDevice instances. It can do all kinds of processing for
|
||||
* these packets. The only restriction for a worker class is that it must implement the 3 abstract methods stated in this class-interface
|
||||
* for start running, stop running and get the core ID the worker is running on.
|
||||
*/
|
||||
class DpdkWorkerThread
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A virtual d'tor. Can be overridden by child class if needed
|
||||
*/
|
||||
virtual ~DpdkWorkerThread() {}
|
||||
|
||||
/**
|
||||
* An abstract method that must be implemented by child class. It's the indication for the worker to start running
|
||||
* @param[in] coreId The core ID the worker is running on (should be returned in getCoreId() )
|
||||
* @return True if all went well or false otherwise
|
||||
*/
|
||||
virtual bool run(uint32_t coreId) = 0;
|
||||
|
||||
/**
|
||||
* An abstract method that must be implemented by child class. It's the indication for the worker to stop running. After
|
||||
* this method is called the caller expects the worker to stop running as fast as possible
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void stop() = 0;
|
||||
|
||||
/**
|
||||
* An abstract method that must be implemented by child class. Get the core ID the worker is running on (as sent to the run() method
|
||||
* as a parameter)
|
||||
* @return The core ID the worker is running on
|
||||
*/
|
||||
virtual uint32_t getCoreId() const = 0;
|
||||
};
|
||||
|
||||
class KniDeviceList;
|
||||
|
||||
/**
|
||||
* @class DpdkDeviceList
|
||||
* A singleton class that encapsulates DPDK initialization and holds the list of DpdkDevice instances. As it's a singleton, it has only
|
||||
* one active instance doesn't have a public c'tor. This class has several main uses:
|
||||
* - it contains the initDpdk() static method which initializes the DPDK infrastructure. It should be called once in every application at
|
||||
* its startup process
|
||||
* - it contains the list of DpdkDevice instances and enables access to them
|
||||
* - it has methods to start and stop worker threads. See more details in startDpdkWorkerThreads()
|
||||
*/
|
||||
class DpdkDeviceList
|
||||
{
|
||||
friend class KniDeviceList;
|
||||
private:
|
||||
bool m_IsInitialized;
|
||||
static bool m_IsDpdkInitialized;
|
||||
static uint32_t m_MBufPoolSizePerDevice;
|
||||
static CoreMask m_CoreMask;
|
||||
std::vector<DpdkDevice*> m_DpdkDeviceList;
|
||||
std::vector<DpdkWorkerThread*> m_WorkerThreads;
|
||||
|
||||
DpdkDeviceList();
|
||||
|
||||
bool isInitialized() const { return (m_IsInitialized && m_IsDpdkInitialized); }
|
||||
bool initDpdkDevices(uint32_t mBufPoolSizePerDevice);
|
||||
static bool verifyHugePagesAndDpdkDriver();
|
||||
|
||||
static int dpdkWorkerThreadStart(void* ptr);
|
||||
public:
|
||||
|
||||
~DpdkDeviceList();
|
||||
|
||||
/**
|
||||
* As DpdkDeviceList is a singleton, this is the static getter to retrieve its instance. Note that if the static method
|
||||
* initDpdk() was not called or returned false this instance won't be initialized and DpdkDevices won't be initialized either
|
||||
* @return The singleton instance of DpdkDeviceList
|
||||
*/
|
||||
static DpdkDeviceList& getInstance()
|
||||
{
|
||||
static DpdkDeviceList instance;
|
||||
if (!instance.isInitialized())
|
||||
instance.initDpdkDevices(DpdkDeviceList::m_MBufPoolSizePerDevice);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* A static method that has to be called once at the startup of every application that uses DPDK. It does several things:
|
||||
* - verifies huge-pages are set and DPDK kernel module is loaded (these are set by the setup-dpdk.sh external script that
|
||||
* has to be run before application is started)
|
||||
* - initializes the DPDK infrastructure
|
||||
* - creates DpdkDevice instances for all ports available for DPDK
|
||||
*
|
||||
* @param[in] coreMask The cores to initialize DPDK with. After initialization, DPDK will only be able to use these cores
|
||||
* for its work. The core mask should have a bit set for every core to use. For example: if the user want to use cores 1,2
|
||||
* the core mask should be 6 (binary: 110)
|
||||
* @param[in] mBufPoolSizePerDevice The mbuf pool size each DpdkDevice will have. This has to be a number which is a power of 2
|
||||
* minus 1, for example: 1023 (= 2^10-1) or 4,294,967,295 (= 2^32-1), etc. This is a DPDK limitation, not PcapPlusPlus.
|
||||
* The size of the mbuf pool size dictates how many packets can be handled by the application at the same time. For example: if
|
||||
* pool size is 1023 it means that no more than 1023 packets can be handled or stored in application memory at every point in time
|
||||
* @param[in] masterCore The core DPDK will use as master to control all worker thread. The default, unless set otherwise, is 0
|
||||
* @param[in] initDpdkArgc Number of optional arguments
|
||||
* @param[in] initDpdkArgv Optional arguments
|
||||
* @return True if initialization succeeded or false if huge-pages or DPDK kernel driver are not loaded, if mBufPoolSizePerDevice
|
||||
* isn't power of 2 minus 1, if DPDK infra initialization failed or if DpdkDevice initialization failed. Anyway, if this method
|
||||
* returned false it's impossible to use DPDK with PcapPlusPlus. You can get some more details about mbufs and pools in
|
||||
* DpdkDevice.h file description or in DPDK web site
|
||||
*/
|
||||
static bool initDpdk(CoreMask coreMask, uint32_t mBufPoolSizePerDevice, uint8_t masterCore = 0, uint32_t initDpdkArgc = 0, char **initDpdkArgv = NULL);
|
||||
|
||||
/**
|
||||
* Get a DpdkDevice by port ID
|
||||
* @param[in] portId The port ID
|
||||
* @return A pointer to the DpdkDevice or NULL if no such device is found
|
||||
*/
|
||||
DpdkDevice* getDeviceByPort(int portId) const;
|
||||
|
||||
/**
|
||||
* Get a DpdkDevice by port PCI address
|
||||
* @param[in] pciAddr The port PCI address
|
||||
* @return A pointer to the DpdkDevice or NULL if no such device is found
|
||||
*/
|
||||
DpdkDevice* getDeviceByPciAddress(const std::string& pciAddr) const;
|
||||
|
||||
/**
|
||||
* @return A vector of all DpdkDevice instances
|
||||
*/
|
||||
const std::vector<DpdkDevice*>& getDpdkDeviceList() const { return m_DpdkDeviceList; }
|
||||
|
||||
/**
|
||||
* @return DPDK master core which is the core that initializes the application
|
||||
*/
|
||||
SystemCore getDpdkMasterCore() const;
|
||||
|
||||
/**
|
||||
* Change the log level of all modules of DPDK
|
||||
* @param[in] logLevel The log level to set. Logger#Info is RTE_LOG_NOTICE and Logger#Debug is RTE_LOG_DEBUG
|
||||
*/
|
||||
void setDpdkLogLevel(Logger::LogLevel logLevel);
|
||||
|
||||
/**
|
||||
* @return The current DPDK log level. RTE_LOG_NOTICE and lower are considered as Logger#Info. RTE_LOG_INFO or RTE_LOG_DEBUG
|
||||
* are considered as Logger#Debug
|
||||
*/
|
||||
Logger::LogLevel getDpdkLogLevel() const;
|
||||
|
||||
/**
|
||||
* Order DPDK to write all its logs to a file
|
||||
* @param[in] logFile The file to write to
|
||||
* @return True if action succeeded, false otherwise
|
||||
*/
|
||||
bool writeDpdkLogToFile(FILE* logFile);
|
||||
|
||||
/**
|
||||
* There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way is setting
|
||||
* a callback which is invoked each time a burst of packets is captured (see DpdkDevice#startCaptureSingleThread() ). This
|
||||
* method implements the first way. See a detailed description of workers in DpdkWorkerThread class description. This method
|
||||
* gets a vector of workers (classes that implement the DpdkWorkerThread interface) and a core mask and starts a worker thread
|
||||
* on each core (meaning - call the worker's DpdkWorkerThread#run() method). Workers usually run in an endless loop and will
|
||||
* be ordered to stop by calling stopDpdkWorkerThreads().<BR>
|
||||
* Note that number of cores in the core mask must be equal to the number of workers. In addition it's impossible to run a
|
||||
* worker thread on DPDK master core, so the core mask shouldn't include the master core (you can find the master core by
|
||||
* calling getDpdkMasterCore() ).
|
||||
* @param[in] coreMask The bitmask of cores to run worker threads on. This list shouldn't include DPDK master core
|
||||
* @param[in] workerThreadsVec A vector of worker instances to run (classes who implement the DpdkWorkerThread interface).
|
||||
* Number of workers in this vector must be equal to the number of cores in the core mask. Notice that the instances of
|
||||
* DpdkWorkerThread shouldn't be freed until calling stopDpdkWorkerThreads() as these instances are running
|
||||
* @return True if all worker threads started successfully or false if: DPDK isn't initialized (initDpdk() wasn't called or
|
||||
* returned false), number of cores differs from number of workers, core mask includes DPDK master core or if one of the
|
||||
* worker threads couldn't be run
|
||||
*/
|
||||
bool startDpdkWorkerThreads(CoreMask coreMask, std::vector<DpdkWorkerThread*>& workerThreadsVec);
|
||||
|
||||
/**
|
||||
* Assuming worker threads are running, this method orders them to stop by calling DpdkWorkerThread#stop(). Then it waits until
|
||||
* they stop running
|
||||
*/
|
||||
void stopDpdkWorkerThreads();
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_DPDK_DEVICE_LIST */
|
||||
129
pcappp/include/pcapplusplus/EthDot3Layer.h
Normal file
129
pcappp/include/pcapplusplus/EthDot3Layer.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#ifndef PACKETPP_ETH_DOT3_LAYER
|
||||
#define PACKETPP_ETH_DOT3_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "MacAddress.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct ether_dot3_header
|
||||
* Represents an IEEE 802.3 Ethernet header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ether_dot3_header
|
||||
{
|
||||
/** Destination MAC */
|
||||
uint8_t dstMac[6];
|
||||
/** Source MAC */
|
||||
uint8_t srcMac[6];
|
||||
/** EtherType */
|
||||
uint16_t length;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @class EthDot3Layer
|
||||
* Represents an IEEE 802.3 Ethernet protocol layer
|
||||
*/
|
||||
class EthDot3Layer : public Layer
|
||||
{
|
||||
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 ether_dot3_header)
|
||||
* @param[in] dataLen Size of the data in bytes
|
||||
* @param[in] packet A pointer to the Packet instance where layer will be stored in
|
||||
*/
|
||||
EthDot3Layer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = EthernetDot3; }
|
||||
|
||||
/**
|
||||
* 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 ether_header)
|
||||
* @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
|
||||
*/
|
||||
EthDot3Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = EthernetDot3; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new IEEE 802.3 Ethernet header and allocates the data
|
||||
* @param[in] sourceMac The source MAC address
|
||||
* @param[in] destMac The destination MAC address
|
||||
* @param[in] length The frame length
|
||||
*/
|
||||
EthDot3Layer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t length);
|
||||
|
||||
~EthDot3Layer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the ether_header
|
||||
*/
|
||||
ether_dot3_header* getEthHeader() const { return (ether_dot3_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get the source MAC address
|
||||
* @return The source MAC address
|
||||
*/
|
||||
MacAddress getSourceMac() const { return MacAddress(getEthHeader()->srcMac); }
|
||||
|
||||
/**
|
||||
* Set source MAC address
|
||||
* @param sourceMac Source MAC to set
|
||||
*/
|
||||
void setSourceMac(const MacAddress& sourceMac) { sourceMac.copyTo(getEthHeader()->srcMac); }
|
||||
|
||||
/**
|
||||
* Get the destination MAC address
|
||||
* @return The destination MAC address
|
||||
*/
|
||||
MacAddress getDestMac() const { return MacAddress(getEthHeader()->dstMac); }
|
||||
|
||||
/**
|
||||
* Set destination MAC address
|
||||
* @param destMac Destination MAC to set
|
||||
*/
|
||||
void setDestMac(const MacAddress& destMac) { destMac.copyTo(getEthHeader()->dstMac); }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently doesn't identify any particular layer (because LLC is not supported yet) so the payload will always be of type PayloadLayer.
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of ether_dot3_header
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(ether_dot3_header); }
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of an IEEE 802.3 Eth packet
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @return True if the data is valid and can represent an IEEE 802.3 Eth packet
|
||||
*/
|
||||
static bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // PACKETPP_ETH_DOT3_LAYER
|
||||
166
pcappp/include/pcapplusplus/EthLayer.h
Normal file
166
pcappp/include/pcapplusplus/EthLayer.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef PACKETPP_ETH_LAYER
|
||||
#define PACKETPP_ETH_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "MacAddress.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct ether_header
|
||||
* Represents an Ethernet II header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ether_header
|
||||
{
|
||||
/** Destination MAC */
|
||||
uint8_t dstMac[6];
|
||||
/** Source MAC */
|
||||
uint8_t srcMac[6];
|
||||
/** EtherType */
|
||||
uint16_t etherType;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/* Ethernet protocol ID's */
|
||||
|
||||
/** IP */
|
||||
#define PCPP_ETHERTYPE_IP 0x0800
|
||||
/** Address resolution */
|
||||
#define PCPP_ETHERTYPE_ARP 0x0806
|
||||
/** Transparent Ethernet Bridging */
|
||||
#define PCPP_ETHERTYPE_ETHBRIDGE 0x6558
|
||||
/** Reverse ARP */
|
||||
#define PCPP_ETHERTYPE_REVARP 0x8035
|
||||
/** AppleTalk protocol */
|
||||
#define PCPP_ETHERTYPE_AT 0x809B
|
||||
/** AppleTalk ARP */
|
||||
#define PCPP_ETHERTYPE_AARP 0x80F3
|
||||
/** IEEE 802.1Q VLAN tagging */
|
||||
#define PCPP_ETHERTYPE_VLAN 0x8100
|
||||
/** IPX */
|
||||
#define PCPP_ETHERTYPE_IPX 0x8137
|
||||
/** IP protocol version 6 */
|
||||
#define PCPP_ETHERTYPE_IPV6 0x86dd
|
||||
/** used to test interfaces */
|
||||
#define PCPP_ETHERTYPE_LOOPBACK 0x9000
|
||||
/** PPPoE discovery */
|
||||
#define PCPP_ETHERTYPE_PPPOED 0x8863
|
||||
/** PPPoE session */
|
||||
#define PCPP_ETHERTYPE_PPPOES 0x8864
|
||||
/** MPLS */
|
||||
#define PCPP_ETHERTYPE_MPLS 0x8847
|
||||
/** Point-to-point protocol (PPP) */
|
||||
#define PCPP_ETHERTYPE_PPP 0x880B
|
||||
/** RDMA over Converged Ethernet (RoCEv1) */
|
||||
#define PCPP_ETHERTYPE_ROCEV1 0x8915
|
||||
/** IEEE 802.1ad Provider Bridge, Q-in-Q */
|
||||
#define PCPP_ETHERTYPE_IEEE_802_1AD 0x88A8
|
||||
|
||||
|
||||
/**
|
||||
* @class EthLayer
|
||||
* Represents an Ethernet II protocol layer
|
||||
*/
|
||||
class EthLayer : public Layer
|
||||
{
|
||||
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 ether_header)
|
||||
* @param[in] dataLen Size of the data in bytes
|
||||
* @param[in] packet A pointer to the Packet instance where layer will be stored in
|
||||
*/
|
||||
EthLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = Ethernet; }
|
||||
|
||||
/**
|
||||
* 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 ether_header)
|
||||
* @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
|
||||
*/
|
||||
EthLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = Ethernet; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new Ethernet header and allocates the data
|
||||
* @param[in] sourceMac The source MAC address
|
||||
* @param[in] destMac The destination MAC address
|
||||
* @param[in] etherType The EtherType to be used. It's an optional parameter, a value of 0 will be set if not provided
|
||||
*/
|
||||
EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType = 0);
|
||||
|
||||
~EthLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the ether_header
|
||||
*/
|
||||
inline ether_header* getEthHeader() const { return (ether_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get the source MAC address
|
||||
* @return The source MAC address
|
||||
*/
|
||||
inline MacAddress getSourceMac() const { return MacAddress(getEthHeader()->srcMac); }
|
||||
|
||||
/**
|
||||
* Set source MAC address
|
||||
* @param sourceMac Source MAC to set
|
||||
*/
|
||||
inline void setSourceMac(const MacAddress& sourceMac) { sourceMac.copyTo(getEthHeader()->srcMac); }
|
||||
|
||||
/**
|
||||
* Get the destination MAC address
|
||||
* @return The destination MAC address
|
||||
*/
|
||||
inline MacAddress getDestMac() const { return MacAddress(getEthHeader()->dstMac); }
|
||||
|
||||
/**
|
||||
* Set destination MAC address
|
||||
* @param destMac Destination MAC to set
|
||||
*/
|
||||
inline void setDestMac(const MacAddress& destMac) { destMac.copyTo(getEthHeader()->dstMac); }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer,
|
||||
* MplsLayer.
|
||||
* Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of ether_header
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(ether_header); }
|
||||
|
||||
/**
|
||||
* Calculate ether_header#etherType for known protocols: IPv4, IPv6, ARP, VLAN
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of an Ethernet II packet
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @return True if the data is valid and can represent an Ethernet II packet
|
||||
*/
|
||||
static bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_ETH_LAYER */
|
||||
55
pcappp/include/pcapplusplus/GeneralUtils.h
Normal file
55
pcappp/include/pcapplusplus/GeneralUtils.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef PCAPPP_GENERAL_UTILS
|
||||
#define PCAPPP_GENERAL_UTILS
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* Convert a byte array into a string of hex characters. For example: for the array { 0xaa, 0x2b, 0x10 } the string
|
||||
* "aa2b10" will be returned
|
||||
* @param[in] byteArr A byte array
|
||||
* @param[in] byteArrSize The size of the byte array [in bytes]
|
||||
* @param[in] stringSizeLimit An optional parameter that enables to limit the returned string size. If set to a positive
|
||||
* integer value the returned string size will be equal or less than this value. If the string representation of the
|
||||
* whole array is longer than this size then only part of the array will be read. The default value is -1 which means no
|
||||
* string size limitation
|
||||
* @return A string of hex characters representing the byte array
|
||||
*/
|
||||
std::string byteArrayToHexString(const uint8_t* byteArr, size_t byteArrSize, int stringSizeLimit = -1);
|
||||
|
||||
/**
|
||||
* Convert a string of hex characters into a byte array. For example: for the string "aa2b10" an array of values
|
||||
* { 0xaa, 0x2b, 0x10 } will be returned
|
||||
* @param[in] hexString A string of hex characters
|
||||
* @param[out] resultByteArr A pre-allocated byte array where the result will be written to
|
||||
* @param[in] resultByteArrSize The size of the pre-allocated byte array
|
||||
* @return The size of the result array. If the string represents an array that is longer than the pre-allocated size
|
||||
* (resultByteArrSize) then the result array will contain only the part of the string that managed to fit into the
|
||||
* array, and the returned size will be resultByteArrSize. However if the string represents an array that is shorter
|
||||
* than the pre-allocated size then some of the cells will remain empty and contain zeros, and the returned size will
|
||||
* be the part of the array that contain data. If the input is an illegal hex string 0 will be returned.
|
||||
* Illegal hex string means odd number of characters or a string that contains non-hex characters
|
||||
*/
|
||||
size_t hexStringToByteArray(const std::string& hexString, uint8_t* resultByteArr, size_t resultByteArrSize);
|
||||
|
||||
/**
|
||||
* This is a cross platform version of memmem (https://man7.org/linux/man-pages/man3/memmem.3.html) which is not supported
|
||||
* on all platforms.
|
||||
* @param[in] haystack A pointer to the buffer to be searched
|
||||
* @param[in] haystackLen Length of the haystack buffer
|
||||
* @param[in] needle A pointer to a buffer that will be searched for
|
||||
* @param[in] needleLen Length of the needle buffer
|
||||
* @return A pointer to the beginning of the substring, or NULL if the substring is not found
|
||||
*/
|
||||
char* cross_platform_memmem(const char* haystack, size_t haystackLen, const char* needle, size_t needleLen);
|
||||
}
|
||||
|
||||
#endif // PCAPPP_GENERAL_UTILS
|
||||
426
pcappp/include/pcapplusplus/GreLayer.h
Normal file
426
pcappp/include/pcapplusplus/GreLayer.h
Normal file
@@ -0,0 +1,426 @@
|
||||
#ifndef PACKETPP_GRE_LAYER
|
||||
#define PACKETPP_GRE_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct gre_basic_header
|
||||
* Represents GRE basic protocol header (common for GREv0 and GREv1)
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct gre_basic_header
|
||||
{
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/** Number of additional encapsulations which are permitted. 0 is the default value */
|
||||
uint8_t recursionControl:3,
|
||||
/** Strict source routing bit (GRE v0 only) */
|
||||
strictSourceRouteBit:1,
|
||||
/** Set if sequence number exists */
|
||||
sequenceNumBit:1,
|
||||
/** Set if key exists */
|
||||
keyBit:1,
|
||||
/** Set if routing exists (GRE v0 only) */
|
||||
routingBit:1,
|
||||
/** Set if checksum exists (GRE v0 only) */
|
||||
checksumBit:1;
|
||||
#else
|
||||
/** Set if checksum exists (GRE v0 only) */
|
||||
uint8_t checksumBit:1,
|
||||
/** Set if routing exists (GRE v0 only) */
|
||||
routingBit:1,
|
||||
/** Set if key exists */
|
||||
keyBit:1,
|
||||
/** Set if sequence number exists */
|
||||
sequenceNumBit:1,
|
||||
/** Strict source routing bit (GRE v0 only) */
|
||||
strictSourceRouteBit:1,
|
||||
/** Number of additional encapsulations which are permitted. 0 is the default value */
|
||||
recursionControl:3;
|
||||
#endif
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/** GRE version - can be 0 or 1 */
|
||||
uint8_t version:3,
|
||||
/** Reserved */
|
||||
flags:4,
|
||||
/** Set if acknowledgment number is set (GRE v1 only) */
|
||||
ackSequenceNumBit:1;
|
||||
#else
|
||||
/** Set if acknowledgment number is set (GRE v1 only) */
|
||||
uint8_t ackSequenceNumBit:1,
|
||||
/** Reserved */
|
||||
flags:4,
|
||||
/** GRE version - can be 0 or 1 */
|
||||
version:3;
|
||||
#endif
|
||||
|
||||
/** Protocol type of the next layer */
|
||||
uint16_t protocol;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct gre1_header
|
||||
* Represents GREv1 protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct gre1_header : gre_basic_header
|
||||
{
|
||||
/** Size of the payload not including the GRE header */
|
||||
uint16_t payloadLength;
|
||||
/** Contains the Peer's Call ID for the session to which this packet belongs */
|
||||
uint16_t callID;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct ppp_pptp_header
|
||||
* Represents PPP layer that comes after GREv1 as part of PPTP protocol
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ppp_pptp_header
|
||||
{
|
||||
/** Broadcast address */
|
||||
uint8_t address;
|
||||
/** Control byte */
|
||||
uint8_t control;
|
||||
/** Protocol type of the next layer (see PPP_* macros at PPPoELayer.h) */
|
||||
uint16_t protocol;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @class GreLayer
|
||||
* Abstract base class for GRE layers (GREv0Layer and GREv1Layer). Cannot be instantiated and contains common logic for derived classes
|
||||
*/
|
||||
class GreLayer : public Layer
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~GreLayer() {}
|
||||
|
||||
/**
|
||||
* A static method that determines the GRE version of GRE layer raw data by looking at the gre_basic_header#version
|
||||
* field
|
||||
* @param[in] greData GRE layer raw data
|
||||
* @param[in] greDataLen Size of raw data
|
||||
* @return ::GREv0 or ::GREv1 values if raw data is GREv0 or GREv1 (accordingly) or ::UnknownProtocol otherwise
|
||||
*/
|
||||
static ProtocolType getGREVersion(uint8_t* greData, size_t greDataLen);
|
||||
|
||||
/**
|
||||
* Get sequence number value if field exists in layer
|
||||
* @param[out] seqNumber The returned sequence number value if exists in layer. Else remain unchanged
|
||||
* @return True if sequence number field exists in layer. In this case seqNumber will be filled with the value.
|
||||
* Or false if sequence number field doesn't exist in layer
|
||||
*/
|
||||
bool getSequenceNumber(uint32_t& seqNumber) const;
|
||||
|
||||
/**
|
||||
* Set sequence number value. If field already exists (gre_basic_header#sequenceNumBit is set) then only the new
|
||||
* value is set. If field doesn't exist it will be added to the layer, gre_basic_header#sequenceNumBit will be set
|
||||
* and the new value will be set
|
||||
* @param[in] seqNumber The sequence number value to set
|
||||
* @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer)
|
||||
*/
|
||||
bool setSequenceNumber(uint32_t seqNumber);
|
||||
|
||||
/**
|
||||
* Unset sequence number and remove it from the layer
|
||||
* @return True if managed to unset successfully or false (and error log) if sequence number wasn't set in the first
|
||||
* place or if didn't manage to remove it from the layer
|
||||
*/
|
||||
bool unsetSequenceNumber();
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers:
|
||||
* IPv4Layer, IPv6Layer, VlanLayer, MplsLayer, PPP_PPTPLayer, EthLayer, EthDot3Layer
|
||||
* Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of GRE header (may change if optional fields are added or removed)
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
||||
|
||||
protected:
|
||||
GreLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { }
|
||||
|
||||
GreLayer() {}
|
||||
|
||||
enum GreField
|
||||
{
|
||||
GreChecksumOrRouting = 0,
|
||||
GreKey = 1,
|
||||
GreSeq = 2,
|
||||
GreAck = 3
|
||||
};
|
||||
|
||||
uint8_t* getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const;
|
||||
|
||||
void computeCalculateFieldsInner();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class GREv0Layer
|
||||
* Represents a GRE version 0 protocol. Limitation: currently this layer doesn't support GRE routing information parsing
|
||||
* and editing. So if a GREv0 packet includes routing information it won't be parse correctly. I didn't add it because
|
||||
* of lack of time, but if you need it please tell me and I'll add it
|
||||
*/
|
||||
class GREv0Layer : public GreLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
GREv0Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : GreLayer(data, dataLen, prevLayer, packet) { m_Protocol = GREv0; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new GREv0 header and allocates the data
|
||||
*/
|
||||
GREv0Layer();
|
||||
|
||||
virtual ~GREv0Layer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the basic GRE header containing only non-optional fields. Notice this points directly to the data,
|
||||
* so every change will change the actual packet data. Also please notice that changing the set bits
|
||||
* (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit, gre_basic_header#routingBit,
|
||||
* gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using the proper set or unset methods (such
|
||||
* as setChecksum(), unsetChecksum(), etc.) may result to wrong calculation of header length and really weird bugs.
|
||||
* Please avoid doing so
|
||||
* @return A pointer to the gre_basic_header
|
||||
*/
|
||||
gre_basic_header* getGreHeader() const { return (gre_basic_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get checksum value if field exists in layer
|
||||
* @param[out] checksum The returned checksum value if exists in layer. Else remain unchanged
|
||||
* @return True if checksum field exists in layer. In this case checksum parameter will be filled with the value.
|
||||
* Or false if checksum field doesn't exist in layer
|
||||
*/
|
||||
bool getChecksum(uint16_t& checksum);
|
||||
|
||||
/**
|
||||
* Set checksum value. If checksum or offset fields already exist (gre_basic_header#checksumBit or gre_basic_header#routingBit are set)
|
||||
* then only the new value is set. If both fields don't exist a new 4-byte value will be added to the layer,
|
||||
* gre_basic_header#checksumBit will be set (gre_basic_header#routingBit will remain unset), the new checksum value
|
||||
* will be set and offset value will be set to 0. The reason both fields are added is that GREv0 protocol states
|
||||
* both of them or none of them should exist on packet (even if only one of the bits are set)
|
||||
* @param[in] checksum The checksum value to set
|
||||
* @return True if managed to set the value/s successfully, or false otherwise (if couldn't extend the layer)
|
||||
*/
|
||||
bool setChecksum(uint16_t checksum);
|
||||
|
||||
/**
|
||||
* Unset checksum and possibly remove it from the layer. It will be removed from the layer only if gre_basic_header#routingBit
|
||||
* is not set as well. Otherwise checksum field will remain on packet with value of 0
|
||||
* @return True if managed to unset successfully or false (and error log) if checksum wasn't set in the first
|
||||
* place or if didn't manage to remove it from the layer
|
||||
*/
|
||||
bool unsetChecksum();
|
||||
|
||||
/**
|
||||
* Get offset value if field exists in layer. Notice there is no setOffset() method as GRE routing information isn't
|
||||
* supported yet (see comment on class description)
|
||||
* @param[out] offset The returned offset value if exists in layer. Else remain unchanged
|
||||
* @return True if offset field exists in layer. In this case offset parameter will be filled with the value.
|
||||
* Or false if offset field doesn't exist in layer
|
||||
*/
|
||||
bool getOffset(uint16_t& offset) const;
|
||||
|
||||
/**
|
||||
* Get key value if field exists in layer
|
||||
* @param[out] key The returned key value if exists in layer. Else remain unchanged
|
||||
* @return True if key field exists in layer. In this case key parameter will be filled with the value.
|
||||
* Or false if key field doesn't exist in layer
|
||||
*/
|
||||
bool getKey(uint32_t& key) const;
|
||||
|
||||
/**
|
||||
* Set key value. If field already exists (gre_basic_header#keyBit is set) then only the new value is set.
|
||||
* If field doesn't exist it will be added to the layer, gre_basic_header#keyBit will be set
|
||||
* and the new value will be set
|
||||
* @param[in] key The key value to set
|
||||
* @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer)
|
||||
*/
|
||||
bool setKey(uint32_t key);
|
||||
|
||||
/**
|
||||
* Unset key and remove it from the layer
|
||||
* @return True if managed to unset successfully or false (and error log) if key wasn't set in the first
|
||||
* place or if didn't manage to remove it from the layer
|
||||
*/
|
||||
bool unsetKey();
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - gre_basic_header#protocol
|
||||
* - GRE checksum field (if exists in packet)
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class GREv1Layer
|
||||
* Represents a GRE version 1 protocol
|
||||
*/
|
||||
class GREv1Layer : public GreLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
GREv1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : GreLayer(data, dataLen, prevLayer, packet) { m_Protocol = GREv1; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new GREv1 header and allocates the data
|
||||
* @param[in] callID The call ID to set
|
||||
*/
|
||||
GREv1Layer(uint16_t callID);
|
||||
|
||||
virtual ~GREv1Layer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the basic GREv1 header containing all non-optional fields. Notice this points directly to the data, so every change will change the actual
|
||||
* packet data. Also please notice that changing the set bits (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit,
|
||||
* gre_basic_header#routingBit, gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using the proper set or unset methods
|
||||
* (such as setAcknowledgmentNum(), unsetSequenceNumber(), etc.) may result to wrong calculation of header length or illegal GREv1 packet and
|
||||
* to some really weird bugs. Please avoid doing so
|
||||
* @return A pointer to the gre1_header
|
||||
*/
|
||||
gre1_header* getGreHeader() const { return (gre1_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get acknowledgment (ack) number value if field exists in layer
|
||||
* @param[out] ackNum The returned ack number value if exists in layer. Else remain unchanged
|
||||
* @return True if ack number field exists in layer. In this case ackNum will be filled with the value.
|
||||
* Or false if ack number field doesn't exist in layer
|
||||
*/
|
||||
bool getAcknowledgmentNum(uint32_t& ackNum) const;
|
||||
|
||||
/**
|
||||
* Set acknowledgment (ack) number value. If field already exists (gre_basic_header#ackSequenceNumBit is set)
|
||||
* then only the new value is set. If field doesn't exist it will be added to the layer,
|
||||
* gre_basic_header#ackSequenceNumBit will be set and the new value will be set
|
||||
* @param[in] ackNum The ack number value to set
|
||||
* @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer)
|
||||
*/
|
||||
bool setAcknowledgmentNum(uint32_t ackNum);
|
||||
|
||||
/**
|
||||
* Unset acknowledgment (ack) number and remove it from the layer
|
||||
* @return True if managed to unset successfully or false (and error log) if ack number wasn't set in the first
|
||||
* place or if didn't manage to remove it from the layer
|
||||
*/
|
||||
bool unsetAcknowledgmentNum();
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - gre1_header#payloadLength
|
||||
* - gre_basic_header#protocol
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PPP_PPTPLayer
|
||||
* Represent a PPP (point-to-point) protocol header that comes after GREv1 header, as part of PPTP - Point-to-Point Tunneling Protocol
|
||||
*/
|
||||
class PPP_PPTPLayer : public Layer
|
||||
{
|
||||
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 ppp_pptp_header)
|
||||
* @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
|
||||
*/
|
||||
PPP_PPTPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = PPP_PPTP; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new PPP-PPTP header
|
||||
* @param[in] address Address field
|
||||
* @param[in] control Control field
|
||||
*/
|
||||
PPP_PPTPLayer(uint8_t address, uint8_t control);
|
||||
|
||||
~PPP_PPTPLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the PPP-PPTP header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref ppp_pptp_header
|
||||
*/
|
||||
ppp_pptp_header* getPPP_PPTPHeader() const { return (ppp_pptp_header*)m_Data; }
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return The size of @ref ppp_pptp_header
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(ppp_pptp_header); }
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - ppp_pptp_header#protocol
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const { return "PPP for PPTP Layer"; }
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; }
|
||||
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_GRE_LAYER */
|
||||
462
pcappp/include/pcapplusplus/GtpLayer.h
Normal file
462
pcappp/include/pcapplusplus/GtpLayer.h
Normal file
@@ -0,0 +1,462 @@
|
||||
#ifndef PACKETPP_GTP_LAYER
|
||||
#define PACKETPP_GTP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
#pragma pack(push, 1)
|
||||
/**
|
||||
* @struct gtpv1_header
|
||||
* GTP v1 common message header
|
||||
*/
|
||||
struct gtpv1_header
|
||||
{
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/** A 1-bit value that states whether there is a N-PDU number optional field */
|
||||
uint8_t npduNumberFlag:1,
|
||||
/** A 1-bit value that states whether there is a Sequence Number optional field */
|
||||
sequenceNumberFlag:1,
|
||||
/** A 1-bit value that states whether there is an extension header optional field */
|
||||
extensionHeaderFlag:1,
|
||||
/** Reserved bit */
|
||||
reserved:1,
|
||||
/** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */
|
||||
protocolType:1,
|
||||
/** GTP version */
|
||||
version:3;
|
||||
#else
|
||||
/** GTP version */
|
||||
uint8_t version:3,
|
||||
/** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */
|
||||
protocolType:1,
|
||||
/** Reserved bit */
|
||||
reserved:1,
|
||||
/** A 1-bit value that states whether there is an extension header optional field */
|
||||
extensionHeaderFlag:1,
|
||||
/** A 1-bit value that states whether there is a Sequence Number optional field */
|
||||
sequenceNumberFlag:1,
|
||||
/** A 1-bit value that states whether there is a N-PDU number optional field */
|
||||
npduNumberFlag:1;
|
||||
#endif
|
||||
/** An 8-bit field that indicates the type of GTP message */
|
||||
uint8_t messageType;
|
||||
|
||||
/** A 16-bit field that indicates the length of the payload in bytes (rest of the packet following the mandatory 8-byte GTP header). Includes the optional fields */
|
||||
uint16_t messageLength;
|
||||
|
||||
/** Tunnel endpoint identifier - A 32-bit(4-octet) field used to multiplex different connections in the same GTP tunnel */
|
||||
uint32_t teid;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* An enum representing the possible GTP v1 message types.
|
||||
* All of the message types except for #GtpV1_GPDU are considered GTP-C messages. #GtpV1_GPDU is considered a GTP-U message
|
||||
*/
|
||||
enum GtpV1MessageType
|
||||
{
|
||||
/** GTPv1 Message Type Unknown */
|
||||
GtpV1_MessageTypeUnknown = 0,
|
||||
/** Echo Request */
|
||||
GtpV1_EchoRequest = 1,
|
||||
/** Echo Response */
|
||||
GtpV1_EchoResponse = 2,
|
||||
/** Version Not Supported */
|
||||
GtpV1_VersionNotSupported = 3,
|
||||
/** Node Alive Request */
|
||||
GtpV1_NodeAliveRequest = 4,
|
||||
/** Node Alive Response */
|
||||
GtpV1_NodeAliveResponse = 5,
|
||||
/** Redirection Request */
|
||||
GtpV1_RedirectionRequest = 6,
|
||||
/** Create PDP Context Request */
|
||||
GtpV1_CreatePDPContextRequest = 7,
|
||||
/** Create PDP Context Response */
|
||||
GtpV1_CreatePDPContextResponse = 16,
|
||||
/** Update PDP Context Request */
|
||||
GtpV1_UpdatePDPContextRequest = 17,
|
||||
/** Update PDP Context Response */
|
||||
GtpV1_UpdatePDPContextResponse = 18,
|
||||
/** Delete PDP Context Request */
|
||||
GtpV1_DeletePDPContextRequest = 19,
|
||||
/** Delete PDP Context Response */
|
||||
GtpV1_DeletePDPContextResponse = 20,
|
||||
/** Initiate PDP Context Activation Request */
|
||||
GtpV1_InitiatePDPContextActivationRequest = 22,
|
||||
/** Initiate PDP Context Activation Response */
|
||||
GtpV1_InitiatePDPContextActivationResponse = 23,
|
||||
/** Error Indication */
|
||||
GtpV1_ErrorIndication = 26,
|
||||
/** PDU Notification Request */
|
||||
GtpV1_PDUNotificationRequest = 27,
|
||||
/** PDU Notification Response */
|
||||
GtpV1_PDUNotificationResponse = 28,
|
||||
/** PDU Notification Reject Request */
|
||||
GtpV1_PDUNotificationRejectRequest = 29,
|
||||
/** PDU Notification Reject Response */
|
||||
GtpV1_PDUNotificationRejectResponse = 30,
|
||||
/** Supported Extensions Header Notification */
|
||||
GtpV1_SupportedExtensionsHeaderNotification = 31,
|
||||
/** Send Routing for GPRS Request */
|
||||
GtpV1_SendRoutingforGPRSRequest = 32,
|
||||
/** Send Routing for GPRS Response */
|
||||
GtpV1_SendRoutingforGPRSResponse = 33,
|
||||
/** Failure Report Request */
|
||||
GtpV1_FailureReportRequest = 34,
|
||||
/** Failure Report Response */
|
||||
GtpV1_FailureReportResponse = 35,
|
||||
/** Note MS Present Request */
|
||||
GtpV1_NoteMSPresentRequest = 36,
|
||||
/** Note MS Present Response */
|
||||
GtpV1_NoteMSPresentResponse = 37,
|
||||
/** Identification Request */
|
||||
GtpV1_IdentificationRequest = 38,
|
||||
/** Identification Response */
|
||||
GtpV1_IdentificationResponse = 39,
|
||||
/** SGSN Context Request */
|
||||
GtpV1_SGSNContextRequest = 50,
|
||||
/** SGSN Context Response */
|
||||
GtpV1_SGSNContextResponse = 51,
|
||||
/** SGSN Context Acknowledge */
|
||||
GtpV1_SGSNContextAcknowledge = 52,
|
||||
/** Forward Relocation Request */
|
||||
GtpV1_ForwardRelocationRequest = 53,
|
||||
/** Forward Relocation Response */
|
||||
GtpV1_ForwardRelocationResponse = 54,
|
||||
/** Forward Relocation Complete */
|
||||
GtpV1_ForwardRelocationComplete = 55,
|
||||
/** Relocation Cancel Request */
|
||||
GtpV1_RelocationCancelRequest = 56,
|
||||
/** Relocation Cancel Response */
|
||||
GtpV1_RelocationCancelResponse = 57,
|
||||
/** Forward SRNS Context */
|
||||
GtpV1_ForwardSRNSContext = 58,
|
||||
/** Forward Relocation Complete Acknowledge */
|
||||
GtpV1_ForwardRelocationCompleteAcknowledge = 59,
|
||||
/** Forward SRNS Context Acknowledge */
|
||||
GtpV1_ForwardSRNSContextAcknowledge = 60,
|
||||
/** UE Registration Request */
|
||||
GtpV1_UERegistrationRequest = 61,
|
||||
/** UE Registration Response */
|
||||
GtpV1_UERegistrationResponse = 62,
|
||||
/** RAN Information Relay */
|
||||
GtpV1_RANInformationRelay = 70,
|
||||
/** MBMS Notification Request */
|
||||
GtpV1_MBMSNotificationRequest = 96,
|
||||
/** MBMS Notification Response */
|
||||
GtpV1_MBMSNotificationResponse = 97,
|
||||
/** MBMS Notification Reject Request */
|
||||
GtpV1_MBMSNotificationRejectRequest = 98,
|
||||
/** MBMS Notification Reject Response */
|
||||
GtpV1_MBMSNotificationRejectResponse = 99,
|
||||
/** Create MBMS Notification Request */
|
||||
GtpV1_CreateMBMSNotificationRequest = 100,
|
||||
/** Create MBMS Notification Response */
|
||||
GtpV1_CreateMBMSNotificationResponse = 101,
|
||||
/** Update MBMS Notification Request */
|
||||
GtpV1_UpdateMBMSNotificationRequest = 102,
|
||||
/** Update MBMS Notification Response */
|
||||
GtpV1_UpdateMBMSNotificationResponse = 103,
|
||||
/** Delete MBMS Notification Request */
|
||||
GtpV1_DeleteMBMSNotificationRequest = 104,
|
||||
/** Delete MBMS Notification Response */
|
||||
GtpV1_DeleteMBMSNotificationResponse = 105,
|
||||
/** MBMS Registration Request */
|
||||
GtpV1_MBMSRegistrationRequest = 112,
|
||||
/** MBMS Registration Response */
|
||||
GtpV1_MBMSRegistrationResponse = 113,
|
||||
/** MBMS De-Registration Request */
|
||||
GtpV1_MBMSDeRegistrationRequest = 114,
|
||||
/** MBMS De-Registration Response */
|
||||
GtpV1_MBMSDeRegistrationResponse = 115,
|
||||
/** MBMS Session Start Request */
|
||||
GtpV1_MBMSSessionStartRequest = 116,
|
||||
/** MBMS Session Start Response */
|
||||
GtpV1_MBMSSessionStartResponse = 117,
|
||||
/** MBMS Session Stop Request */
|
||||
GtpV1_MBMSSessionStopRequest = 118,
|
||||
/** MBMS Session Stop Response */
|
||||
GtpV1_MBMSSessionStopResponse = 119,
|
||||
/** MBMS Session Update Request */
|
||||
GtpV1_MBMSSessionUpdateRequest = 120,
|
||||
/** MBMS Session Update Response */
|
||||
GtpV1_MBMSSessionUpdateResponse = 121,
|
||||
/** MS Info Change Request */
|
||||
GtpV1_MSInfoChangeRequest = 128,
|
||||
/** MS Info Change Response */
|
||||
GtpV1_MSInfoChangeResponse = 129,
|
||||
/** Data Record Transfer Request */
|
||||
GtpV1_DataRecordTransferRequest = 240,
|
||||
/** Data Record Transfer Response */
|
||||
GtpV1_DataRecordTransferResponse = 241,
|
||||
/** End Marker */
|
||||
GtpV1_EndMarker = 254,
|
||||
/** G-PDU */
|
||||
GtpV1_GPDU = 255
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class GtpV1Layer
|
||||
* A class representing the [GTP v1](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol) protocol.
|
||||
*/
|
||||
class GtpV1Layer : public Layer
|
||||
{
|
||||
private:
|
||||
struct gtpv1_header_extra
|
||||
{
|
||||
uint16_t sequenceNumber;
|
||||
uint8_t npduNumber;
|
||||
uint8_t nextExtensionHeader;
|
||||
};
|
||||
|
||||
gtpv1_header_extra* getHeaderExtra() const;
|
||||
|
||||
void init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @class GtpExtension
|
||||
* A class that represents [GTP header extensions](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol)
|
||||
*/
|
||||
class GtpExtension
|
||||
{
|
||||
friend class GtpV1Layer;
|
||||
|
||||
private:
|
||||
uint8_t* m_Data;
|
||||
size_t m_DataLen;
|
||||
uint8_t m_ExtType;
|
||||
|
||||
GtpExtension(uint8_t* data, size_t dataLen, uint8_t type);
|
||||
|
||||
void setNextHeaderType(uint8_t nextHeaderType);
|
||||
|
||||
static GtpExtension createGtpExtension(uint8_t* data, size_t dataLen, uint8_t extType, uint16_t content);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* An empty c'tor that creates an empty object, meaning one that isNull() returns "true")
|
||||
*/
|
||||
GtpExtension();
|
||||
|
||||
/**
|
||||
* A copy c'tor for this class
|
||||
* @param[in] other The GTP extension to copy from
|
||||
*/
|
||||
GtpExtension(const GtpExtension& other);
|
||||
|
||||
/**
|
||||
* An assignment operator for this class
|
||||
* @param[in] other The extension to assign from
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
GtpExtension& operator=(const GtpExtension& other);
|
||||
|
||||
/**
|
||||
* @return Instances of this class may be initialized as empty, meaning they don't contain any data. In
|
||||
* these cases this method returns true
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
/**
|
||||
* @return The extension type. If the object is empty a value of zero is returned
|
||||
*/
|
||||
uint8_t getExtensionType() const;
|
||||
|
||||
/**
|
||||
* @return The total length of the extension including the length and next extension type fields.
|
||||
* If the object is empty a value of zero is returned
|
||||
*/
|
||||
size_t getTotalLength() const;
|
||||
|
||||
/**
|
||||
* @return The length of the extension's content, excluding the extension length and next extension type fields.
|
||||
* If the object is empty a value of zero is returned
|
||||
*/
|
||||
size_t getContentLength() const;
|
||||
|
||||
/**
|
||||
* @return A byte array that includes the extension's content. The length of this array can be determined by
|
||||
* getContentLength(). If the object is empty a null value is returned
|
||||
*/
|
||||
uint8_t* getContent() const;
|
||||
|
||||
/**
|
||||
* @return The extension type of the next header. If there are no more header extensions or if this object is empty
|
||||
* a value of zero is returned
|
||||
*/
|
||||
uint8_t getNextExtensionHeaderType() const;
|
||||
|
||||
/**
|
||||
* @return An instance of this class representing the next extension header, if exists in the message. If there are
|
||||
* no more header extensions or if this object is empty an empty instance of GtpExtension is returned, meaning
|
||||
* one that GtpExtension#isNull() returns "true"
|
||||
*/
|
||||
GtpExtension getNextExtension() const;
|
||||
}; // GtpExtension
|
||||
|
||||
virtual ~GtpV1Layer() {}
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
GtpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = GTPv1; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new GTPv1 layer and sets the message type and the TEID value
|
||||
* @param[in] messageType The GTPv1 message type to be set in the newly created layer
|
||||
* @param[in] teid The TEID value to be set in the newly created layer
|
||||
*/
|
||||
GtpV1Layer(GtpV1MessageType messageType, uint32_t teid);
|
||||
|
||||
/**
|
||||
* A constructor that creates a new GTPv1 layer and sets various parameters
|
||||
* @param[in] messageType The GTPv1 message type to be set in the newly created layer
|
||||
* @param[in] teid The TEID value to be set in the newly created layer
|
||||
* @param[in] setSeqNum A flag indicating whether to set a sequence number. If set to "false" then the parameter "seqNum" will be ignored
|
||||
* @param[in] seqNum The sequence number to be set in the newly created later. If "setSeqNum" is set to false this parameter will be ignored
|
||||
* @param[in] setNpduNum A flag indicating whether to set the N-PDU number. If set to "false" then the parameter "npduNum" will be ignored
|
||||
* @param[in] npduNum The N-PDU number to be set in the newly created later. If "setNpduNum" is set to false this parameter will be ignored
|
||||
*/
|
||||
GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum);
|
||||
|
||||
/**
|
||||
* A static method that takes a byte array and detects whether it is a GTP v1 message
|
||||
* @param[in] data A byte array
|
||||
* @param[in] dataSize The byte array size (in bytes)
|
||||
* @return True if the data is identified as GTP v1 message (GTP-C or GTP-U)
|
||||
*/
|
||||
static bool isGTPv1(const uint8_t* data, size_t dataSize);
|
||||
|
||||
/**
|
||||
* @return The GTP v1 common header structure. Notice this points directly to the data, so every change will change the actual packet data
|
||||
*/
|
||||
gtpv1_header* getHeader() const { return (gtpv1_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get the sequence number if exists on the message (sequence number is an optional field in GTP messages)
|
||||
* @param[out] seqNumber Set with the sequence number value if exists in the layer. Otherwise remains unchanged
|
||||
* @return True if the sequence number field exists in layer, in which case seqNumber is set with the value.
|
||||
* Or false otherwise
|
||||
*/
|
||||
bool getSequenceNumber(uint16_t& seqNumber) const;
|
||||
|
||||
/**
|
||||
* Set a sequence number
|
||||
* @param[in] seqNumber The sequence number to set
|
||||
* @return True if the value was set successfully, false otherwise. In case of failure a corresponding error message will be written to log
|
||||
*/
|
||||
bool setSequenceNumber(const uint16_t seqNumber);
|
||||
|
||||
/**
|
||||
* Get the N-PDU number if exists on the message (N-PDU number is an optional field in GTP messages)
|
||||
* @param[out] npduNum Set with the N-PDU number value if exists in the layer. Otherwise remains unchanged
|
||||
* @return True if the N-PDU number field exists in layer, in which case npduNum is set with the value.
|
||||
* Or false otherwise
|
||||
*/
|
||||
bool getNpduNumber(uint8_t& npduNum) const;
|
||||
|
||||
/**
|
||||
* Set an N-PDU number
|
||||
* @param[in] npduNum The N-PDU number to set
|
||||
* @return True if the value was set successfully, false otherwise. In case of failure a corresponding error message will be written to log
|
||||
*/
|
||||
bool setNpduNumber(const uint8_t npduNum);
|
||||
|
||||
/**
|
||||
* Get the type of the next header extension if exists on the message (extensions are optional in GTP messages)
|
||||
* @param[out] nextExtType Set with the next header extension type if exists in layer. Otherwise remains unchanged
|
||||
* @return True if the message contains header extensions, in which case nextExtType is set to the next
|
||||
* header extension type. If there are no header extensions false is returned and nextExtType remains unchanged
|
||||
*/
|
||||
bool getNextExtensionHeaderType(uint8_t& nextExtType) const;
|
||||
|
||||
/**
|
||||
* @return An object that represents the next extension header, if exists in the message. If there are no extensions
|
||||
* an empty object is returned, meaning an object which GtpExtension#isNull() returns "true"
|
||||
*/
|
||||
GtpExtension getNextExtension() const;
|
||||
|
||||
/**
|
||||
* Add a GTPv1 header extension. It is assumed that the extension is 4 bytes in length and its content is 2 bytes in length.
|
||||
* If you need a different content size please reach out to me. This method takes care of extending the layer to make room for
|
||||
* the new extension and also sets the relevant flags and fields
|
||||
* @param[in] extensionType The type of the new extension
|
||||
* @param[in] extensionContent A 2-byte long content
|
||||
* @return An object representing the newly added extension. If there was an error adding the extension a null object will be
|
||||
* returned (meaning GtpExtension#isNull() will return "true") and a corresponding error message will be written to log
|
||||
*/
|
||||
GtpExtension addExtension(uint8_t extensionType, uint16_t extensionContent);
|
||||
|
||||
/**
|
||||
* @return The message type of this GTP packet
|
||||
*/
|
||||
GtpV1MessageType getMessageType() const;
|
||||
|
||||
/**
|
||||
* @return A string representation of the packet's message type
|
||||
*/
|
||||
std::string getMessageTypeAsString() const;
|
||||
|
||||
/**
|
||||
* @return True if this is a GTP-U message, false otherwise
|
||||
*/
|
||||
bool isGTPUMessage() const;
|
||||
|
||||
/**
|
||||
* @return True if this is a GTP-C message, false otherwise
|
||||
*/
|
||||
bool isGTPCMessage() const;
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as GTPv1
|
||||
* @param[in] port The port number to be checked
|
||||
* @return True if the port matches those associated with the BGP protocol
|
||||
*/
|
||||
static bool isGTPv1Port(uint16_t port) { return port == 2152 /* GTP-U */ || port == 2123 /* GTP-C */; }
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Identifies the following next layers for GTP-U packets: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return The size of the GTP header. For GTP-C packets the size is determined by the value of
|
||||
* gtpv1_header#messageLength and for GTP-U the size only includes the GTP header itself (meaning
|
||||
* the size of gtpv1_header plus the size of the optional fields such as sequence number, N-PDU
|
||||
* or extensions if exist)
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - gtpv1_header#messageLength
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif //PACKETPP_GTP_LAYER
|
||||
703
pcappp/include/pcapplusplus/HttpLayer.h
Normal file
703
pcappp/include/pcapplusplus/HttpLayer.h
Normal file
@@ -0,0 +1,703 @@
|
||||
#ifndef PACKETPP_HTTP_LAYER
|
||||
#define PACKETPP_HTTP_LAYER
|
||||
|
||||
#include "TextBasedProtocol.h"
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* An enum for HTTP version
|
||||
*/
|
||||
enum HttpVersion
|
||||
{
|
||||
/** HTTP/0.9 */
|
||||
ZeroDotNine,
|
||||
/** HTTP/1.0 */
|
||||
OneDotZero,
|
||||
/** HTTP/1.1 */
|
||||
OneDotOne,
|
||||
/** Unknown HTTP version */
|
||||
HttpVersionUnknown
|
||||
};
|
||||
|
||||
// some popular HTTP fields
|
||||
|
||||
/** Host field */
|
||||
#define PCPP_HTTP_HOST_FIELD "Host"
|
||||
/** Connection field */
|
||||
#define PCPP_HTTP_CONNECTION_FIELD "Connection"
|
||||
/** User-Agent field */
|
||||
#define PCPP_HTTP_USER_AGENT_FIELD "User-Agent"
|
||||
/** Referer field */
|
||||
#define PCPP_HTTP_REFERER_FIELD "Referer"
|
||||
/** Accept field */
|
||||
#define PCPP_HTTP_ACCEPT_FIELD "Accept"
|
||||
/** Accept-Encoding field */
|
||||
#define PCPP_HTTP_ACCEPT_ENCODING_FIELD "Accept-Encoding"
|
||||
/** Accept-Language field */
|
||||
#define PCPP_HTTP_ACCEPT_LANGUAGE_FIELD "Accept-Language"
|
||||
/** Cookie field */
|
||||
#define PCPP_HTTP_COOKIE_FIELD "Cookie"
|
||||
/** Content-Length field */
|
||||
#define PCPP_HTTP_CONTENT_LENGTH_FIELD "Content-Length"
|
||||
/** Content-Encoding field */
|
||||
#define PCPP_HTTP_CONTENT_ENCODING_FIELD "Content-Encoding"
|
||||
/** Content-Type field */
|
||||
#define PCPP_HTTP_CONTENT_TYPE_FIELD "Content-Type"
|
||||
/** Transfer-Encoding field */
|
||||
#define PCPP_HTTP_TRANSFER_ENCODING_FIELD "Transfer-Encoding"
|
||||
/** Server field */
|
||||
#define PCPP_HTTP_SERVER_FIELD "Server"
|
||||
|
||||
|
||||
|
||||
// -------- Class HttpMessage -----------------
|
||||
|
||||
|
||||
/**
|
||||
* @class HttpMessage
|
||||
* Represents a general HTTP message. It's an abstract class and cannot be instantiated. It's inherited by HttpRequestLayer and HttpResponseLayer
|
||||
*/
|
||||
class HttpMessage : public TextBasedProtocolMessage
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~HttpMessage() {}
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as HTTP
|
||||
* @param[in] port The port number to be checked
|
||||
* @return True if the port matches those associated with the HTTP protocol
|
||||
*/
|
||||
static bool isHttpPort(uint16_t port) { return port == 80 || port == 8080; }
|
||||
|
||||
// overridden methods
|
||||
|
||||
virtual HeaderField* addField(const std::string& fieldName, const std::string& fieldValue);
|
||||
virtual HeaderField* addField(const HeaderField& newField);
|
||||
virtual HeaderField* insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue);
|
||||
virtual HeaderField* insertField(HeaderField* prevField, const HeaderField& newField);
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
protected:
|
||||
HttpMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) {}
|
||||
HttpMessage() : TextBasedProtocolMessage() {}
|
||||
HttpMessage(const HttpMessage& other) : TextBasedProtocolMessage(other) {}
|
||||
HttpMessage& operator=(const HttpMessage& other) { TextBasedProtocolMessage::operator=(other); return *this; }
|
||||
|
||||
// implementation of abstract methods
|
||||
char getHeaderFieldNameValueSeparator() const { return ':'; }
|
||||
bool spacesAllowedBetweenHeaderFieldNameAndValue() const { return true; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class HttpRequestFirstLine;
|
||||
|
||||
|
||||
|
||||
// -------- Class HttpRequestLayer -----------------
|
||||
|
||||
/**
|
||||
* @class HttpRequestLayer
|
||||
* Represents an HTTP request header and inherits all basic functionality of HttpMessage and TextBasedProtocolMessage.
|
||||
* The functionality that is added for this class is the HTTP first line concept. An HTTP request has the following first line:
|
||||
* <i>GET /bla/blabla.asp HTTP/1.1</i>
|
||||
* Since it's not an "ordinary" HTTP field, it requires a special treatment and gets a class of it's own: HttpRequestFirstLine.
|
||||
* Unlike most L2-4 protocols, an HTTP request header can spread over more than 1 packet. PcapPlusPlus currently doesn't support a header
|
||||
* that is spread over more than 1 packet so in such cases: 1) only the first packet will be parsed as HttpRequestLayer (the other packets
|
||||
* won't be recognized as HttpRequestLayer) and 2) the HTTP header for the first packet won't be complete (as it continues in the following
|
||||
* packets), this why PcapPlusPlus can indicate that HTTP request header is complete or not(doesn't end with "\r\n\r\n" or "\n\n") using
|
||||
* HttpMessage#isHeaderComplete()
|
||||
*/
|
||||
class HttpRequestLayer : public HttpMessage
|
||||
{
|
||||
friend class HttpRequestFirstLine;
|
||||
public:
|
||||
/**
|
||||
* HTTP request methods
|
||||
*/
|
||||
enum HttpMethod
|
||||
{
|
||||
/** GET */
|
||||
HttpGET,
|
||||
/** HEAD */
|
||||
HttpHEAD,
|
||||
/** POST */
|
||||
HttpPOST,
|
||||
/** PUT */
|
||||
HttpPUT,
|
||||
/** DELETE */
|
||||
HttpDELETE,
|
||||
/** TRACE */
|
||||
HttpTRACE,
|
||||
/** OPTIONS */
|
||||
HttpOPTIONS,
|
||||
/** CONNECT */
|
||||
HttpCONNECT,
|
||||
/** PATCH */
|
||||
HttpPATCH,
|
||||
/** Unknown HTTP method */
|
||||
HttpMethodUnknown
|
||||
};
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
HttpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new HTTP request header with only the first line filled. Object will be created without further fields.
|
||||
* The user can then add fields using addField() methods
|
||||
* @param[in] method The HTTP method used in this HTTP request
|
||||
* @param[in] uri The URI of the first line
|
||||
* @param[in] version HTTP version to be used in this request
|
||||
*/
|
||||
HttpRequestLayer(HttpMethod method, std::string uri, HttpVersion version);
|
||||
|
||||
virtual ~HttpRequestLayer();
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer. This copy constructor inherits base copy constructor HttpMessage#HttpMessage() and add the functionality
|
||||
* of copying the first line as well
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
HttpRequestLayer(const HttpRequestLayer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator overload for this layer. This method inherits base assignment operator HttpMessage#operator=() and add the functionality
|
||||
* of copying the first line as well
|
||||
* @param[in] other The instance to copy from
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
HttpRequestLayer& operator=(const HttpRequestLayer& other);
|
||||
|
||||
/**
|
||||
* @return A pointer to the first line instance for this message
|
||||
*/
|
||||
HttpRequestFirstLine* getFirstLine() const { return m_FirstLine; }
|
||||
|
||||
/**
|
||||
* The URL is hostname+uri. So given the following URL, for example: "www.cnn.com/main.html", the hostname is "www.cnn.com" and the URI
|
||||
* is "/.main.html". URI and hostname are split to 2 different places inside the HTTP request packet: URI is in the first line and hostname
|
||||
* is in "HOST" field.
|
||||
* This methods concatenates the hostname and URI to the full URL
|
||||
* @return The URL of the HTTP request message
|
||||
*/
|
||||
std::string getUrl() const;
|
||||
|
||||
// implement Layer's abstract methods
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
HttpRequestFirstLine* m_FirstLine;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------- Class HttpResponseLayer -----------------
|
||||
|
||||
class HttpResponseFirstLine;
|
||||
|
||||
|
||||
/**
|
||||
* @class HttpResponseLayer
|
||||
* Represents an HTTP response header and inherits all basic functionality of HttpMessage and TextBasedProtocolMessage.
|
||||
* The functionality that is added for this class is the HTTP first line concept. An HTTP response has the following first line:
|
||||
* <i>200 OK HTTP/1.1</i>
|
||||
* Since it's not an "ordinary" HTTP field, it requires a special treatment and gets a class of it's own: HttpResponseFirstLine.
|
||||
* Unlike most L2-4 protocols, an HTTP response header can spread over more than 1 packet. PcapPlusPlus currently doesn't support a header
|
||||
* that is spread over more than 1 packet so in such cases: 1) only the first packet will be parsed as HttpResponseLayer (the other packets
|
||||
* won't be recognized as HttpResponseLayer) and 2) the HTTP header for the first packet won't be complete (as it continues in the following
|
||||
* packets), this why PcapPlusPlus can indicate that HTTP response header is complete or not (doesn't end with "\r\n\r\n" or "\n\n") using
|
||||
* HttpMessage#isHeaderComplete()
|
||||
*/
|
||||
class HttpResponseLayer : public HttpMessage
|
||||
{
|
||||
friend class HttpResponseFirstLine;
|
||||
public:
|
||||
/**
|
||||
* Enum for HTTP response status codes
|
||||
*/
|
||||
enum HttpResponseStatusCode
|
||||
{
|
||||
/** 100 Continue*/
|
||||
Http100Continue,
|
||||
/** 101 Switching Protocols*/
|
||||
Http101SwitchingProtocols,
|
||||
/** 102 Processing */
|
||||
Http102Processing,
|
||||
/** 200 OK */
|
||||
Http200OK,
|
||||
/** 201 Created */
|
||||
Http201Created,
|
||||
/** 202 Accepted */
|
||||
Http202Accepted,
|
||||
/** 203 Non-Authoritative Information */
|
||||
Http203NonAuthoritativeInformation,
|
||||
/** 204 No Content*/
|
||||
Http204NoContent,
|
||||
/** 205 Reset Content*/
|
||||
Http205ResetContent,
|
||||
/** 206 Partial Content */
|
||||
Http206PartialContent,
|
||||
/** 207 Multi-Status */
|
||||
Http207MultiStatus,
|
||||
/** 208 Already Reported */
|
||||
Http208AlreadyReported,
|
||||
/** 226 IM Used */
|
||||
Http226IMUsed,
|
||||
/** 300 Multiple Choices */
|
||||
Http300MultipleChoices,
|
||||
/** 301 Moved Permanently */
|
||||
Http301MovedPermanently,
|
||||
/** 302 (various messages) */
|
||||
Http302,
|
||||
/** 303 See Other */
|
||||
Http303SeeOther,
|
||||
/** 304 Not Modified */
|
||||
Http304NotModified,
|
||||
/** 305 Use Proxy */
|
||||
Http305UseProxy,
|
||||
/** 306 Switch Proxy */
|
||||
Http306SwitchProxy,
|
||||
/** 307 Temporary Redirect */
|
||||
Http307TemporaryRedirect,
|
||||
/** 308 Permanent Redirect, */
|
||||
Http308PermanentRedirect,
|
||||
/** 400 Bad Request */
|
||||
Http400BadRequest,
|
||||
/** 401 Unauthorized */
|
||||
Http401Unauthorized,
|
||||
/** 402 Payment Required */
|
||||
Http402PaymentRequired,
|
||||
/** 403 Forbidden */
|
||||
Http403Forbidden,
|
||||
/** 404 Not Found */
|
||||
Http404NotFound,
|
||||
/** 405 Method Not Allowed */
|
||||
Http405MethodNotAllowed,
|
||||
/** 406 Not Acceptable */
|
||||
Http406NotAcceptable,
|
||||
/** 407 Proxy Authentication Required */
|
||||
Http407ProxyAuthenticationRequired,
|
||||
/** 408 Request Timeout */
|
||||
Http408RequestTimeout,
|
||||
/** 409 Conflict */
|
||||
Http409Conflict,
|
||||
/** 410 Gone */
|
||||
Http410Gone,
|
||||
/** 411 Length Required */
|
||||
Http411LengthRequired,
|
||||
/** 412 Precondition Failed */
|
||||
Http412PreconditionFailed,
|
||||
/** 413 RequestEntity Too Large */
|
||||
Http413RequestEntityTooLarge,
|
||||
/** 414 Request-URI Too Long */
|
||||
Http414RequestURITooLong,
|
||||
/** 415 Unsupported Media Type */
|
||||
Http415UnsupportedMediaType,
|
||||
/** 416 Requested Range Not Satisfiable */
|
||||
Http416RequestedRangeNotSatisfiable,
|
||||
/** 417 Expectation Failed */
|
||||
Http417ExpectationFailed,
|
||||
/** 418 I'm a teapot */
|
||||
Http418Imateapot,
|
||||
/** 419 Authentication Timeout */
|
||||
Http419AuthenticationTimeout,
|
||||
/** 420 (various messages) */
|
||||
Http420,
|
||||
/** 422 Unprocessable Entity */
|
||||
Http422UnprocessableEntity,
|
||||
/** 423 Locked */
|
||||
Http423Locked,
|
||||
/** 424 Failed Dependency */
|
||||
Http424FailedDependency,
|
||||
/** 426 Upgrade Required */
|
||||
Http426UpgradeRequired,
|
||||
/** 428 Precondition Required */
|
||||
Http428PreconditionRequired,
|
||||
/** 429 Too Many Requests */
|
||||
Http429TooManyRequests,
|
||||
/** 431 Request Header Fields Too Large */
|
||||
Http431RequestHeaderFieldsTooLarge,
|
||||
/** 440 Login Timeout */
|
||||
Http440LoginTimeout,
|
||||
/** 444 No Response */
|
||||
Http444NoResponse,
|
||||
/** 449 Retry With */
|
||||
Http449RetryWith,
|
||||
/** 450 Blocked by Windows Parental Controls */
|
||||
Http450BlockedByWindowsParentalControls,
|
||||
/** 451 (various messages) */
|
||||
Http451,
|
||||
/** 494 Request Header Too Large */
|
||||
Http494RequestHeaderTooLarge,
|
||||
/** 495 Cert Error */
|
||||
Http495CertError,
|
||||
/** 496 No Cert */
|
||||
Http496NoCert,
|
||||
/** 497 HTTP to HTTPS */
|
||||
Http497HTTPtoHTTPS,
|
||||
/** 498 Token expired/invalid */
|
||||
Http498TokenExpiredInvalid,
|
||||
/** 499 (various messages) */
|
||||
Http499,
|
||||
/** 500 Internal Server Error */
|
||||
Http500InternalServerError,
|
||||
/** 501 Not Implemented */
|
||||
Http501NotImplemented,
|
||||
/** 502 Bad Gateway */
|
||||
Http502BadGateway,
|
||||
/** 503 Service Unavailable */
|
||||
Http503ServiceUnavailable,
|
||||
/** 504 Gateway Timeout */
|
||||
Http504GatewayTimeout,
|
||||
/** 505 HTTP Version Not Supported */
|
||||
Http505HTTPVersionNotSupported,
|
||||
/** 506 Variant Also Negotiates */
|
||||
Http506VariantAlsoNegotiates,
|
||||
/** 507 Insufficient Storage */
|
||||
Http507InsufficientStorage,
|
||||
/** 508 Loop Detected */
|
||||
Http508LoopDetected,
|
||||
/** 509 Bandwidth Limit Exceeded */
|
||||
Http509BandwidthLimitExceeded,
|
||||
/** 510 Not Extended */
|
||||
Http510NotExtended,
|
||||
/** 511 Network Authentication Required */
|
||||
Http511NetworkAuthenticationRequired,
|
||||
/** 520 Origin Error */
|
||||
Http520OriginError,
|
||||
/** 521 Web server is down */
|
||||
Http521WebServerIsDown,
|
||||
/** 522 Connection timed out */
|
||||
Http522ConnectionTimedOut,
|
||||
/** 523 Proxy Declined Request */
|
||||
Http523ProxyDeclinedRequest,
|
||||
/** 524 A timeout occurred */
|
||||
Http524aTimeoutOccurred,
|
||||
/** 598 Network read timeout error */
|
||||
Http598NetworkReadTimeoutError,
|
||||
/** 599 Network connect timeout error */
|
||||
Http599NetworkConnectTimeoutError,
|
||||
/** Unknown status code */
|
||||
HttpStatusCodeUnknown
|
||||
};
|
||||
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
HttpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new HTTP response header with only the first line filled. Object will be created without further fields.
|
||||
* The user can then add fields using addField() methods
|
||||
* @param[in] version HTTP version to be used
|
||||
* @param[in] statusCode Status code to be used
|
||||
* @param[in] statusCodeString Most status codes have their default string, e.g 200 is usually "OK", 404 is usually "Not Found", etc.
|
||||
* But the user can set a non-default status code string and it will be written in the header first line. Empty string ("") means using the
|
||||
* default status code string
|
||||
*/
|
||||
HttpResponseLayer(HttpVersion version, HttpResponseLayer::HttpResponseStatusCode statusCode, std::string statusCodeString = "");
|
||||
|
||||
virtual ~HttpResponseLayer();
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer. This copy constructor inherits base copy constructor HttpMessage#HttpMessage() and adds the functionality
|
||||
* of copying the first line as well
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
HttpResponseLayer(const HttpResponseLayer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator overload for this layer. This method inherits base assignment operator HttpMessage#operator=() and adds the functionality
|
||||
* of copying the first line as well
|
||||
* @param[in] other The instance to copy from
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
HttpResponseLayer& operator=(const HttpResponseLayer& other);
|
||||
|
||||
/**
|
||||
* @return A pointer to the first line instance for this message
|
||||
*/
|
||||
HttpResponseFirstLine* getFirstLine() const { return m_FirstLine; }
|
||||
|
||||
/**
|
||||
* The length of the body of many HTTP response messages is determined by a HTTP header field called "Content-Length". This method sets
|
||||
* The content-length field value. The method supports several cases:
|
||||
* - If the "Content-Length" field exists - the method will only replace the existing value with the new value
|
||||
* - If the "Content-Length" field doesn't exist - the method will create this field and put the value in it. Here are also 2 cases:
|
||||
* - If prevFieldName is specified - the new "Content-Length" field will be created after it
|
||||
* - If prevFieldName isn't specified or doesn't exist - the new "Content-Length" field will be created as the last field before
|
||||
* end-of-header field
|
||||
* @param[in] contentLength The content length value to set
|
||||
* @param[in] prevFieldName Optional field, if specified and "Content-Length" field doesn't exist, it will be created after it
|
||||
* @return A pointer to the "Content-Length" field, or NULL if creation failed for some reason
|
||||
*/
|
||||
HeaderField* setContentLength(int contentLength, const std::string prevFieldName = "");
|
||||
|
||||
/**
|
||||
* The length of the body of many HTTP response messages is determined by a HTTP header field called "Content-Length". This method
|
||||
* parses this field, extracts its value and return it. If this field doesn't exist the method will return 0
|
||||
* @return HTTP response body length determined by "Content-Length" field
|
||||
*/
|
||||
int getContentLength() const;
|
||||
|
||||
// implement Layer's abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
HttpResponseFirstLine* m_FirstLine;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------- Class HttpRequestFirstLine -----------------
|
||||
|
||||
/**
|
||||
* @class HttpRequestFirstLine
|
||||
* Represents an HTTP request header first line. The first line includes 3 parameters: HTTP method (e.g GET, POST, etc.),
|
||||
* URI (e.g /main/index.html) and HTTP version (e.g HTTP/1.1). All these parameters are included in this class, and the user
|
||||
* can retrieve or set them.
|
||||
* This class cannot be instantiated by users, it's created inside HttpRequestLayer and user can get a pointer to an instance of it. All "get"
|
||||
* methods of this class will retrieve the actual data of the HTTP request and the "set" methods will change the packet data.
|
||||
* Since HTTP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "set" methods
|
||||
* of this class need in most cases to shorten or extend the data in HttpRequestLayer. These methods will return a false value if this
|
||||
* action failed
|
||||
*/
|
||||
class HttpRequestFirstLine
|
||||
{
|
||||
friend class HttpRequestLayer;
|
||||
public:
|
||||
/**
|
||||
* @return The HTTP method
|
||||
*/
|
||||
HttpRequestLayer::HttpMethod getMethod() const { return m_Method; }
|
||||
|
||||
/**
|
||||
* Set the HTTP method
|
||||
* @param[in] newMethod The method to set
|
||||
* @return False if newMethod is HttpRequestLayer#HttpMethodUnknown or if shortening/extending the HttpRequestLayer data failed. True otherwise
|
||||
*/
|
||||
bool setMethod(HttpRequestLayer::HttpMethod newMethod);
|
||||
|
||||
/**
|
||||
* @return A copied version of the URI (notice changing the return value won't change the actual data of the packet)
|
||||
*/
|
||||
std::string getUri() const;
|
||||
|
||||
/**
|
||||
* Set the URI
|
||||
* @param[in] newUri The URI to set
|
||||
* @return False if shortening/extending the HttpRequestLayer data failed. True otherwise
|
||||
*/
|
||||
bool setUri(std::string newUri);
|
||||
|
||||
/**
|
||||
* @return The HTTP version
|
||||
*/
|
||||
HttpVersion getVersion() const { return m_Version; }
|
||||
|
||||
/**
|
||||
* Set the HTTP version. This method doesn't return a value since all supported HTTP versions are of the same size
|
||||
* (HTTP/0.9, HTTP/1.0, HTTP/1.1)
|
||||
* @param[in] newVersion The HTTP version to set
|
||||
*/
|
||||
void setVersion(HttpVersion newVersion);
|
||||
|
||||
/**
|
||||
* A static method for parsing the HTTP method out of raw data
|
||||
* @param[in] data The raw data
|
||||
* @param[in] dataLen The raw data length
|
||||
* @return The parsed HTTP method
|
||||
*/
|
||||
static HttpRequestLayer::HttpMethod parseMethod(char* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* @return The size in bytes of the HTTP first line
|
||||
*/
|
||||
int getSize() const { return m_FirstLineEndOffset; }
|
||||
|
||||
/**
|
||||
* As explained in HttpRequestLayer, an HTTP header can spread over more than 1 packet, so when looking at a single packet
|
||||
* the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication
|
||||
* whether the first line is partial
|
||||
* @return False if the first line is partial, true if it's complete
|
||||
*/
|
||||
bool isComplete() const { return m_IsComplete; }
|
||||
|
||||
/**
|
||||
* @class HttpRequestFirstLineException
|
||||
* This exception can be thrown while constructing HttpRequestFirstLine (the constructor is private, so the construction happens
|
||||
* only in HttpRequestLayer). This kind of exception will be thrown if trying to construct with HTTP method of
|
||||
* HttpRequestLayer#HttpMethodUnknown or with undefined HTTP version ::HttpVersionUnknown
|
||||
*/
|
||||
class HttpRequestFirstLineException : public std::exception
|
||||
{
|
||||
public:
|
||||
~HttpRequestFirstLineException() throw() {}
|
||||
void setMessage(std::string message) { m_Message = message; }
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
private:
|
||||
std::string m_Message;
|
||||
};
|
||||
private:
|
||||
HttpRequestFirstLine(HttpRequestLayer* httpRequest);
|
||||
HttpRequestFirstLine(HttpRequestLayer* httpRequest, HttpRequestLayer::HttpMethod method, HttpVersion version, std::string uri = "/");
|
||||
//throw(HttpRequestFirstLineException); // Deprecated in C++17
|
||||
|
||||
void parseVersion();
|
||||
|
||||
HttpRequestLayer* m_HttpRequest;
|
||||
HttpRequestLayer::HttpMethod m_Method;
|
||||
HttpVersion m_Version;
|
||||
int m_VersionOffset;
|
||||
int m_UriOffset;
|
||||
int m_FirstLineEndOffset;
|
||||
bool m_IsComplete;
|
||||
HttpRequestFirstLineException m_Exception;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------- Class HttpResponseFirstLine -----------------
|
||||
|
||||
/**
|
||||
* @class HttpResponseFirstLine
|
||||
* Represents an HTTP response header first line. The first line includes 2 parameters: status code (e.g 200 OK, 404 Not Found, etc.),
|
||||
* and HTTP version (e.g HTTP/1.1). These 2 parameters are included in this class, and the user can retrieve or set them.
|
||||
* This class cannot be instantiated by users, it's created inside HttpResponseLayer and user can get a pointer to an instance of it. The "get"
|
||||
* methods of this class will retrieve the actual data of the HTTP response and the "set" methods will change the packet data.
|
||||
* Since HTTP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "set" methods
|
||||
* of this class need in most cases to shorten or extend the data in HttpResponseLayer. These methods will return a false value if this
|
||||
* action failed
|
||||
*/
|
||||
class HttpResponseFirstLine
|
||||
{
|
||||
friend class HttpResponseLayer;
|
||||
public:
|
||||
/**
|
||||
* @return The status code as HttpResponseLayer::HttpResponseStatusCode enum
|
||||
*/
|
||||
HttpResponseLayer::HttpResponseStatusCode getStatusCode() const { return m_StatusCode; }
|
||||
|
||||
/**
|
||||
* @return The status code number as integer (e.g 200, 404, etc.)
|
||||
*/
|
||||
int getStatusCodeAsInt() const;
|
||||
|
||||
/**
|
||||
* @return The status code message (e.g "OK", "Not Found", etc.)
|
||||
*/
|
||||
std::string getStatusCodeString() const;
|
||||
|
||||
/**
|
||||
* Set the status code
|
||||
* @param[in] newStatusCode The new status code to set
|
||||
* @param[in] statusCodeString An optional parameter: set a non-default status code message (e.g "Bla Bla" instead of "Not Found"). If
|
||||
* this parameter isn't supplied or supplied as empty string (""), the default message for the status code will be set
|
||||
* @return True if setting the status code was completed successfully, false otherwise
|
||||
*/
|
||||
bool setStatusCode(HttpResponseLayer::HttpResponseStatusCode newStatusCode, std::string statusCodeString = "");
|
||||
|
||||
/**
|
||||
* @return The HTTP version
|
||||
*/
|
||||
HttpVersion getVersion() const { return m_Version; }
|
||||
|
||||
/**
|
||||
* Set the HTTP version. This method doesn't return a value since all supported HTTP versions are of the same size
|
||||
* (HTTP/0.9, HTTP/1.0, HTTP/1.1)
|
||||
* @param[in] newVersion The HTTP version to set
|
||||
*/
|
||||
void setVersion(HttpVersion newVersion);
|
||||
|
||||
/**
|
||||
* A static method for parsing the HTTP status code out of raw data
|
||||
* @param[in] data The raw data
|
||||
* @param[in] dataLen The raw data length
|
||||
* @return The parsed HTTP status code as enum
|
||||
*/
|
||||
static HttpResponseLayer::HttpResponseStatusCode parseStatusCode(char* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* @return The size in bytes of the HTTP first line
|
||||
*/
|
||||
int getSize() const { return m_FirstLineEndOffset; }
|
||||
|
||||
/**
|
||||
* As explained in HttpResponseLayer, an HTTP header can spread over more than 1 packet, so when looking at a single packet
|
||||
* the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication
|
||||
* whether the first line is partial
|
||||
* @return False if the first line is partial, true if it's complete
|
||||
*/
|
||||
bool isComplete() const { return m_IsComplete; }
|
||||
|
||||
/**
|
||||
* @class HttpResponseFirstLineException
|
||||
* This exception can be thrown while constructing HttpResponseFirstLine (the constructor is private, so the construction happens
|
||||
* only in HttpResponseLayer). This kind of exception will be thrown if trying to construct with HTTP status code of
|
||||
* HttpResponseLayer#HttpStatusCodeUnknown or with undefined HTTP version ::HttpVersionUnknown
|
||||
*/
|
||||
class HttpResponseFirstLineException : public std::exception
|
||||
{
|
||||
public:
|
||||
~HttpResponseFirstLineException() throw() {}
|
||||
void setMessage(std::string message) { m_Message = message; }
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
private:
|
||||
std::string m_Message;
|
||||
};
|
||||
|
||||
private:
|
||||
HttpResponseFirstLine(HttpResponseLayer* httpResponse);
|
||||
HttpResponseFirstLine(HttpResponseLayer* httpResponse, HttpVersion version, HttpResponseLayer::HttpResponseStatusCode statusCode, std::string statusCodeString = "");
|
||||
|
||||
static HttpVersion parseVersion(char* data, size_t dataLen);
|
||||
static HttpResponseLayer::HttpResponseStatusCode validateStatusCode(char* data, size_t dataLen, HttpResponseLayer::HttpResponseStatusCode potentialCode);
|
||||
|
||||
|
||||
HttpResponseLayer* m_HttpResponse;
|
||||
HttpVersion m_Version;
|
||||
HttpResponseLayer::HttpResponseStatusCode m_StatusCode;
|
||||
int m_FirstLineEndOffset;
|
||||
bool m_IsComplete;
|
||||
HttpResponseFirstLineException m_Exception;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_HTTP_LAYER */
|
||||
46
pcappp/include/pcapplusplus/IPLayer.h
Normal file
46
pcappp/include/pcapplusplus/IPLayer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef PACKETPP_IP_LAYER
|
||||
#define PACKETPP_IP_LAYER
|
||||
|
||||
#include "IpAddress.h"
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @class IPLayer
|
||||
* This is an interface (abstract class) implemented in the IP layers (IPv4Layer and IPv6Layer).
|
||||
* It provides methods to fetch the source and destination IP addresses in an abdtract way
|
||||
* that hides the IP type (IPv4 or IPv6). This is useful for use-cases in which the IP type doesn't matter.
|
||||
* For example: if you're only interested in printing the IP address the IP type shouldn't matter.
|
||||
*/
|
||||
class IPLayer
|
||||
{
|
||||
protected:
|
||||
IPLayer() {}
|
||||
public:
|
||||
/**
|
||||
* An abstract method to get the source IP address
|
||||
* @return An IPAddress object containing the source address
|
||||
*/
|
||||
virtual IPAddress getSrcIPAddress() const = 0;
|
||||
|
||||
/**
|
||||
* An abstract method to get the destination IP address
|
||||
* @return An IPAddress object containing the destination address
|
||||
*/
|
||||
virtual IPAddress getDstIPAddress() const = 0;
|
||||
|
||||
/**
|
||||
* An empty destructor
|
||||
*/
|
||||
virtual ~IPLayer() {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PACKETPP_IP_LAYER
|
||||
457
pcappp/include/pcapplusplus/IPReassembly.h
Normal file
457
pcappp/include/pcapplusplus/IPReassembly.h
Normal file
@@ -0,0 +1,457 @@
|
||||
#ifndef PACKETPP_IP_REASSEMBLY
|
||||
#define PACKETPP_IP_REASSEMBLY
|
||||
|
||||
#include "Packet.h"
|
||||
#include "LRUList.h"
|
||||
#include "IpAddress.h"
|
||||
#include "PointerVector.h"
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes an implementation of IP reassembly mechanism (a.k.a IP de-fragmentation), which is the mechanism of assembling IPv4 or IPv6
|
||||
* fragments back into one whole packet. As the previous sentence imply, this module supports both IPv4 and IPv6 reassembly which means
|
||||
* the same pcpp#IPReassembly instance can reassemble both IPv4 and IPv6 fragments. You can read more about IP fragmentation here:
|
||||
* https://en.wikipedia.org/wiki/IP_fragmentation.<BR>
|
||||
* The API is rather simple and contains one main method: pcpp#IPReassembly#processPacket() which gets a fragment packet as a parameter, does the
|
||||
* reassembly and returns a fully reassembled packet when done.<BR>
|
||||
*
|
||||
* The logic works as follows:
|
||||
* - There is an internal map that stores the reassembly data for each packet. The key to this map, meaning the way to uniquely associate a
|
||||
* fragment to a (reassembled) packet is the triplet of source IP, destination IP and IP ID (for IPv4) or Fragment ID (for IPv6)
|
||||
* - When the first fragment arrives a new record is created in the map and the fragment data is copied
|
||||
* - With each fragment arriving the fragment data is copied right after the previous fragment and the reassembled packet is gradually being built
|
||||
* - When the last fragment arrives the packet is fully reassembled and returned to the user. Since all fragment data is copied, the packet pointer
|
||||
* returned to the user has to be freed by the user when done using it
|
||||
* - The logic supports out-of-order fragments, meaning that a fragment which arrives out-of-order, its data will be copied to a list of out-of-order
|
||||
* fragments where it waits for its turn. This list is observed each time a new fragment arrives to see if the next fragment(s) wait(s) in this
|
||||
* list
|
||||
* - If a non-IP packet arrives it's returned as is to the user
|
||||
* - If a non-fragment packet arrives it's returned as is to the user
|
||||
*
|
||||
* In order to limit the amount of memory used by this mechanism there is a limit to the number of concurrent packets being reassembled.
|
||||
* The default limit is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE but the user can set any value (determined in pcpp#IPReassembly
|
||||
* c'tor). Once capacity (the number of concurrent reassembled packets) exceeds this number, the packet that was least recently used will be
|
||||
* dropped from the map along with all the data that was reassembled so far. This means that if the next fragment from this packet suddenly
|
||||
* appears it will be treated as a new reassembled packet (which will create another record in the map). The user can be notified when
|
||||
* reassembled packets are removed from the map by registering to the pcpp#IPReassembly#OnFragmentsClean callback in pcpp#IPReassembly c'tor
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace pcpp
|
||||
* @brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/** IP reassembly mechanism default capacity. If concurrent packet volume exceeds this numbers, packets will start to be dropped in
|
||||
* a LRU manner
|
||||
*/
|
||||
#define PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE 500000
|
||||
|
||||
/**
|
||||
* @class IPReassembly
|
||||
* Contains the IP reassembly (a.k.a IP de-fragmentation) mechanism. Encapsulates both IPv4 and IPv6 reassembly.
|
||||
* Please refer to the documentation at the top of IPReassembly.h
|
||||
* to understand how this mechanism works. The main APIs are:
|
||||
* - IPReassembly#processPacket() - process a fragment. This is the main method which should be called whenever a new fragment arrives.
|
||||
* This method processes the fragment, runs the reassembly logic and returns the result packet when it's fully reassembled
|
||||
* - IPReassembly#getCurrentPacket() - get the reassembled data that is currently available, even if reassembly process is not yet completed
|
||||
* - IPReassembly#removePacket() - remove all data that is currently stored for a packet, including the reassembled data that was gathered
|
||||
* so far
|
||||
*/
|
||||
class IPReassembly
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @class PacketKey
|
||||
* An abstract class that represents a key that can uniquely identify an IP packet. This class cannot be instantiated or copied,
|
||||
* only its derived classes can
|
||||
*/
|
||||
class PacketKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A default virtual d'tor
|
||||
*/
|
||||
virtual ~PacketKey() {}
|
||||
|
||||
/**
|
||||
* @return A 4-byte hash value of the packet key
|
||||
*/
|
||||
virtual uint32_t getHashValue() const = 0;
|
||||
|
||||
/**
|
||||
* @return The IP protocol this key represents (pcpp#IPv4 or pcpp#IPv6)
|
||||
*/
|
||||
virtual ProtocolType getProtocolType() const = 0;
|
||||
|
||||
/**
|
||||
* @return A pointer to a new instance which is a clone of the current instance
|
||||
*/
|
||||
virtual PacketKey* clone() const = 0;
|
||||
|
||||
protected:
|
||||
// private c'tor
|
||||
PacketKey() {}
|
||||
|
||||
// private copy c'tor
|
||||
PacketKey(const PacketKey& other) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4PacketKey
|
||||
* Represents a key that can uniquely identify IPv4 packets. The key comprises of source IPv4 address, dest IPv4 address and IP ID
|
||||
*/
|
||||
class IPv4PacketKey : public PacketKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A default c'tor which zeros all members
|
||||
*/
|
||||
IPv4PacketKey() : m_IpID(0), m_SrcIP(IPv4Address::Zero), m_DstIP(IPv4Address::Zero) { }
|
||||
|
||||
/**
|
||||
* A c'tor that sets values in each one of the members
|
||||
* @param[in] ipid IP ID value
|
||||
* @param[in] srcip Source IPv4 address
|
||||
* @param[in] dstip Dest IPv4 address
|
||||
*/
|
||||
IPv4PacketKey(uint16_t ipid, IPv4Address srcip, IPv4Address dstip) : m_IpID(ipid), m_SrcIP(srcip), m_DstIP(dstip) { }
|
||||
|
||||
/**
|
||||
* A copy c'tor for this class
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
IPv4PacketKey(const IPv4PacketKey& other) : PacketKey(other), m_IpID(other.m_IpID), m_SrcIP(other.m_SrcIP), m_DstIP(other.m_DstIP) { }
|
||||
|
||||
/**
|
||||
* Assignment operator for this class
|
||||
* @param[in] other The instance to assign from
|
||||
*/
|
||||
IPv4PacketKey& operator=(const IPv4PacketKey& other)
|
||||
{
|
||||
m_IpID = other.m_IpID;
|
||||
m_SrcIP = other.m_SrcIP;
|
||||
m_DstIP = other.m_DstIP;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IP ID value
|
||||
*/
|
||||
uint16_t getIpID() const { return m_IpID; }
|
||||
|
||||
/**
|
||||
* @return Source IP address
|
||||
*/
|
||||
IPv4Address getSrcIP() const { return m_SrcIP; }
|
||||
|
||||
/**
|
||||
* @return Dest IP address
|
||||
*/
|
||||
IPv4Address getDstIP() const { return m_DstIP; }
|
||||
|
||||
/**
|
||||
* Set IP ID
|
||||
* @param[in] ipID IP ID value to set
|
||||
*/
|
||||
void setIpID(uint16_t ipID) { m_IpID = ipID; }
|
||||
|
||||
/**
|
||||
* Set source IPv4 address
|
||||
* @param[in] srcIP Source IP to set
|
||||
*/
|
||||
void setSrcIP(const IPv4Address& srcIP) { m_SrcIP = srcIP; }
|
||||
|
||||
/**
|
||||
* Set dest IPv4 address
|
||||
* @param[in] dstIP Dest IP to set
|
||||
*/
|
||||
void setDstIP(const IPv4Address& dstIP) { m_DstIP = dstIP; }
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
uint32_t getHashValue() const;
|
||||
|
||||
/**
|
||||
* @return pcpp#IPv4 protocol
|
||||
*/
|
||||
ProtocolType getProtocolType() const { return IPv4; }
|
||||
|
||||
PacketKey* clone() const { return new IPv4PacketKey(*this); }
|
||||
|
||||
private:
|
||||
uint16_t m_IpID;
|
||||
IPv4Address m_SrcIP;
|
||||
IPv4Address m_DstIP;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6PacketKey
|
||||
* Represents a key that can uniquely identify IPv6 fragment packets. The key comprises of source IPv6 address, dest IPv6 address
|
||||
* and fragment ID (which resides in the IPv6 fragmentation extension)
|
||||
*/
|
||||
class IPv6PacketKey : public PacketKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A default c'tor which zeros all members
|
||||
*/
|
||||
IPv6PacketKey() : m_FragmentID(0), m_SrcIP(IPv6Address::Zero), m_DstIP(IPv6Address::Zero) { }
|
||||
|
||||
/**
|
||||
* A c'tor that sets values in each one of the members
|
||||
* @param[in] fragmentID Fragment ID value
|
||||
* @param[in] srcip Source IPv6 address
|
||||
* @param[in] dstip Dest IPv6 address
|
||||
*/
|
||||
IPv6PacketKey(uint32_t fragmentID, IPv6Address srcip, IPv6Address dstip) : m_FragmentID(fragmentID), m_SrcIP(srcip), m_DstIP(dstip) { }
|
||||
|
||||
/**
|
||||
* A copy c'tor for this class
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
IPv6PacketKey(const IPv6PacketKey& other) : PacketKey(other), m_FragmentID(other.m_FragmentID), m_SrcIP(other.m_SrcIP), m_DstIP(other.m_DstIP) { }
|
||||
|
||||
/**
|
||||
* Assignment operator for this class
|
||||
* @param[in] other The instance to assign from
|
||||
*/
|
||||
IPv6PacketKey& operator=(const IPv6PacketKey& other)
|
||||
{
|
||||
m_FragmentID = other.m_FragmentID;
|
||||
m_SrcIP = other.m_SrcIP;
|
||||
m_SrcIP = other.m_DstIP;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Fragment ID value
|
||||
*/
|
||||
uint32_t getFragmentID() const { return m_FragmentID; }
|
||||
|
||||
/**
|
||||
* @return Source IP address
|
||||
*/
|
||||
IPv6Address getSrcIP() const { return m_SrcIP; }
|
||||
|
||||
/**
|
||||
* @return Dest IP address
|
||||
*/
|
||||
IPv6Address getDstIP() const { return m_DstIP; }
|
||||
|
||||
/**
|
||||
* Set fragment ID
|
||||
* @param[in] fragID Fragment ID value to set
|
||||
*/
|
||||
void setFragmentID(uint32_t fragID) { m_FragmentID = fragID; }
|
||||
|
||||
/**
|
||||
* Set source IPv6 address
|
||||
* @param[in] srcIP Source IP to set
|
||||
*/
|
||||
void setSrcIP(const IPv6Address& srcIP) { m_SrcIP = srcIP; }
|
||||
|
||||
/**
|
||||
* Set dest IPv6 address
|
||||
* @param[in] dstIP Dest IP to set
|
||||
*/
|
||||
void setDstIP(const IPv6Address& dstIP) { m_DstIP = dstIP; }
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
uint32_t getHashValue() const;
|
||||
|
||||
/**
|
||||
* @return pcpp#IPv6 protocol
|
||||
*/
|
||||
ProtocolType getProtocolType() const { return IPv6; }
|
||||
|
||||
PacketKey* clone() const { return new IPv6PacketKey(*this); }
|
||||
|
||||
private:
|
||||
uint32_t m_FragmentID;
|
||||
IPv6Address m_SrcIP;
|
||||
IPv6Address m_DstIP;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @typedef OnFragmentsClean
|
||||
* The IP reassembly mechanism has a certain capacity of concurrent packets it can handle. This capacity is determined in its c'tor
|
||||
* (default value is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE). When traffic volume exceeds this capacity the mechanism starts
|
||||
* dropping packets in a LRU manner (least recently used are dropped first). Whenever a packet is dropped this callback is fired
|
||||
* @param[in] key A pointer to the identifier of the packet that is being dropped
|
||||
* @param[in] userCookie A pointer to the cookie provided by the user in IPReassemby c'tor (or NULL if no cookie provided)
|
||||
*/
|
||||
typedef void (*OnFragmentsClean)(const PacketKey* key, void* userCookie);
|
||||
|
||||
/**
|
||||
* An enum representing the status returned from processing a fragment
|
||||
*/
|
||||
enum ReassemblyStatus
|
||||
{
|
||||
/** The processed packet isn't of type IPv4 or IPv6 */
|
||||
NON_IP_PACKET = 0x00,
|
||||
/** The processed packet isn't a fragment */
|
||||
NON_FRAGMENT = 0x01,
|
||||
/** The processed fragment is the first fragment */
|
||||
FIRST_FRAGMENT = 0x02,
|
||||
/** The processed fragment is a fragment (but not the first one) */
|
||||
FRAGMENT = 0x04,
|
||||
/** The processed fragment is not the fragment that was expected at this time */
|
||||
OUT_OF_ORDER_FRAGMENT = 0x08,
|
||||
/** The processed fragment is malformed, meaning a fragment which has offset of zero but isn't the first fragment */
|
||||
MALFORMED_FRAGMENT = 0x10,
|
||||
/** Packet is now fully reassembled */
|
||||
REASSEMBLED = 0x20
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for this class.
|
||||
* @param[in] onFragmentsCleanCallback The callback to be called when packets are dropped due to capacity limit.
|
||||
* Please read more about capacity limit in IPReassembly.h file description. This parameter is optional, default value is NULL (no callback)
|
||||
* @param[in] callbackUserCookie A pointer to an object provided by the user. This pointer will be returned when invoking the
|
||||
* onFragmentsCleanCallback. This parameter is optional, default cookie is NULL
|
||||
* @param[in] maxPacketsToStore Set the capacity limit of the IP reassembly mechanism. Default capacity is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE
|
||||
*/
|
||||
IPReassembly(OnFragmentsClean onFragmentsCleanCallback = NULL, void *callbackUserCookie = NULL, size_t maxPacketsToStore = PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE)
|
||||
: m_PacketLRU(maxPacketsToStore), m_OnFragmentsCleanCallback(onFragmentsCleanCallback), m_CallbackUserCookie(callbackUserCookie) {}
|
||||
|
||||
/**
|
||||
* A d'tor for this class
|
||||
*/
|
||||
~IPReassembly();
|
||||
|
||||
/**
|
||||
* The main API that drives IPReassembly. This method should be called whenever a fragment arrives. This method finds the relevant
|
||||
* packet this fragment belongs to and runs the IP reassembly logic that is described in IPReassembly.h.
|
||||
* @param[in] fragment The fragment to process (IPv4 or IPv6). Please notice that the reassembly logic doesn't change or manipulate
|
||||
* this object in any way. All of its data is copied to internal structures and manipulated there
|
||||
* @param[out] status An indication of the packet reassembly status following the processing of this fragment. Possible values are:
|
||||
* - The input fragment is not a IPv4 or IPv6 packet
|
||||
* - The input fragment is not a IPv4 or IPv6 fragment packet
|
||||
* - The input fragment is the first fragment of the packet
|
||||
* - The input fragment is not the first or last fragment
|
||||
* - The input fragment came out-of-order, meaning that wasn't the fragment that was currently expected (it's data is copied to
|
||||
* the out-of-order fragment list)
|
||||
* - The input fragment is malformed and will be ignored
|
||||
* - The input fragment is the last one and the packet is now fully reassembled. In this case the return value will contain
|
||||
* a pointer to the reassebmled packet
|
||||
* @param[in] parseUntil Optional parameter. Parse the reassembled packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a
|
||||
* certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this
|
||||
* parameter into account
|
||||
* @param[in] parseUntilLayer Optional parameter. Parse the reassembled packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to
|
||||
* parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet.
|
||||
* Default value is ::OsiModelLayerUnknown which means don't take this parameter into account
|
||||
* @return
|
||||
* - If the input fragment isn't an IPv4/IPv6 packet or if it isn't an IPv4/IPv6 fragment, the return value is a pointer to the input fragment
|
||||
* - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled packet is
|
||||
* returned. Notice it's the user's responsibility to free this pointer when done using it
|
||||
* - If the reassembled packet isn't ready then NULL is returned
|
||||
*/
|
||||
Packet* processPacket(Packet* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
|
||||
|
||||
/**
|
||||
* The main API that drives IPReassembly. This method should be called whenever a fragment arrives. This method finds the relevant
|
||||
* packet this fragment belongs to and runs the IPv4 reassembly logic that is described in IPReassembly.h.
|
||||
* @param[in] fragment The fragment to process (IPv4 or IPv6). Please notice that the reassembly logic doesn't change or manipulate
|
||||
* this object in any way. All of its data is copied to internal structures and manipulated there
|
||||
* @param[out] status An indication of the packet reassembly status following the processing of this fragment. Possible values are:
|
||||
* - The input fragment is not a IPv4 or IPv6 packet
|
||||
* - The input fragment is not a IPv4 or IPv6 fragment packet
|
||||
* - The input fragment is the first fragment of the packet
|
||||
* - The input fragment is not the first or last fragment
|
||||
* - The input fragment came out-of-order, meaning that wasn't the fragment that was currently expected (it's data is copied to
|
||||
* the out-of-order fragment list)
|
||||
* - The input fragment is malformed and will be ignored
|
||||
* - The input fragment is the last one and the packet is now fully reassembled. In this case the return value will contain
|
||||
* a pointer to the reassebmled packet
|
||||
* @param[in] parseUntil Optional parameter. Parse the raw and reassembled packets until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a
|
||||
* certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this
|
||||
* parameter into account
|
||||
* @param[in] parseUntilLayer Optional parameter. Parse the raw and reassembled packets until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to
|
||||
* parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet.
|
||||
* Default value is ::OsiModelLayerUnknown which means don't take this parameter into account
|
||||
* @return
|
||||
* - If the input fragment isn't an IPv4/IPv6 packet or if it isn't an IPv4/IPv6 fragment, the return value is a pointer to a Packet object
|
||||
* wrapping the input fragment RawPacket object. It's the user responsibility to free this instance
|
||||
* - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled packet is
|
||||
* returned. Notice it's the user's responsibility to free this pointer when done using it
|
||||
* - If the reassembled packet isn't ready then NULL is returned
|
||||
*/
|
||||
Packet* processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
|
||||
|
||||
/**
|
||||
* Get a partially reassembled packet. This method returns all the reassembled data that was gathered so far which is obviously not
|
||||
* a fully reassembled packet (otherwise it would have returned by processPacket()). Notice all data is being copied so the user is
|
||||
* responsible to free the returned Packet object when done using it. Notice#2 - calling this method doesn't interfere with the
|
||||
* reassembly of this packet - all internal structures and data remain
|
||||
* @param[in] key The identifiers of the packet to return
|
||||
* @return A pointer to a Packet object containing the partially reassembled packet. Notice the user is responsible to free this
|
||||
* object when done using it
|
||||
*/
|
||||
Packet* getCurrentPacket(const PacketKey& key);
|
||||
|
||||
/**
|
||||
* Remove a partially reassembled packet from all internal structures. That means that if another fragment of this packet appears
|
||||
* it will be treated as a new packet
|
||||
* @param[in] key The identifiers of the packet to remove
|
||||
*/
|
||||
void removePacket(const PacketKey& key);
|
||||
|
||||
/**
|
||||
* Get the maximum capacity as determined in the c'tor
|
||||
*/
|
||||
size_t getMaxCapacity() const { return m_PacketLRU.getMaxSize(); }
|
||||
|
||||
/**
|
||||
* Get the current number of packets being processed
|
||||
*/
|
||||
size_t getCurrentCapacity() const { return m_FragmentMap.size(); }
|
||||
|
||||
private:
|
||||
|
||||
struct IPFragment
|
||||
{
|
||||
uint16_t fragmentOffset;
|
||||
bool lastFragment;
|
||||
uint8_t* fragmentData;
|
||||
size_t fragmentDataLen;
|
||||
IPFragment() { fragmentOffset = 0; lastFragment = false; fragmentData = NULL; fragmentDataLen = 0; }
|
||||
~IPFragment() { delete [] fragmentData; }
|
||||
};
|
||||
|
||||
struct IPFragmentData
|
||||
{
|
||||
uint16_t currentOffset;
|
||||
RawPacket* data;
|
||||
bool deleteData;
|
||||
uint32_t fragmentID;
|
||||
PacketKey* packetKey;
|
||||
PointerVector<IPFragment> outOfOrderFragments;
|
||||
IPFragmentData(PacketKey* pktKey, uint32_t fragId) { currentOffset = 0; data = NULL; deleteData = true; fragmentID = fragId; packetKey = pktKey; }
|
||||
~IPFragmentData() { delete packetKey; if (deleteData && data != NULL) { delete data; } }
|
||||
};
|
||||
|
||||
LRUList<uint32_t> m_PacketLRU;
|
||||
std::map<uint32_t, IPFragmentData*> m_FragmentMap;
|
||||
OnFragmentsClean m_OnFragmentsCleanCallback;
|
||||
void* m_CallbackUserCookie;
|
||||
|
||||
void addNewFragment(uint32_t hash, IPFragmentData* fragData);
|
||||
bool matchOutOfOrderFragments(IPFragmentData* fragData);
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // PACKETPP_IP_REASSEMBLY
|
||||
212
pcappp/include/pcapplusplus/IPSecLayer.h
Normal file
212
pcappp/include/pcapplusplus/IPSecLayer.h
Normal file
@@ -0,0 +1,212 @@
|
||||
#ifndef PACKETPP_IPSEC_LAYER
|
||||
#define PACKETPP_IPSEC_LAYER
|
||||
|
||||
/// @file
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @struct ipsec_authentication_header
|
||||
* Represents IPSec AuthenticationHeader (AH) structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ipsec_authentication_header
|
||||
{
|
||||
/** Type of the next header */
|
||||
uint8_t nextHeader;
|
||||
/** The length of the Authentication Header in 4-octet units, minus 2 */
|
||||
uint8_t payloadLen;
|
||||
/** Reserved */
|
||||
uint16_t reserved;
|
||||
/** Security Parameters Index */
|
||||
uint32_t spi;
|
||||
/** Sequence Number */
|
||||
uint32_t sequenceNumber;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @struct ipsec_esp
|
||||
* Represents IPSec Encapsulating Security Payload (ESP) structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ipsec_esp
|
||||
{
|
||||
/** Security Parameters Index */
|
||||
uint32_t spi;
|
||||
/** Sequence Number */
|
||||
uint32_t sequenceNumber;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @class AuthenticationHeaderLayer
|
||||
* Represents an IPSec AuthenticationHeader (AH) layer
|
||||
*/
|
||||
class AuthenticationHeaderLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
AuthenticationHeaderLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = AuthenticationHeader; }
|
||||
|
||||
/**
|
||||
* Get a pointer to the raw AH header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the ipsec_authentication_header
|
||||
*/
|
||||
ipsec_authentication_header* getAHHeader() const { return (ipsec_authentication_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The Security Parameters Index (SPI) field value
|
||||
*/
|
||||
uint32_t getSPI() const;
|
||||
|
||||
/**
|
||||
* @return The sequence number value
|
||||
*/
|
||||
uint32_t getSequenceNumber() const;
|
||||
|
||||
/**
|
||||
* @return The size of the Integrity Check Value (ICV)
|
||||
*/
|
||||
size_t getICVLength() const;
|
||||
|
||||
/**
|
||||
* @return A pointer to the raw data of the Integrity Check Value (ICV)
|
||||
*/
|
||||
uint8_t* getICVBytes() const;
|
||||
|
||||
/**
|
||||
* @return The value of the Integrity Check Value (ICV) as a hex string
|
||||
*/
|
||||
std::string getICVHexStream() const;
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of a AuthenticationHeader layer
|
||||
* @param[in] dataLen The length of byte stream
|
||||
* @return True if the data is valid and can represent an AuthenticationHeader layer
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size of the AH header
|
||||
*/
|
||||
size_t getHeaderLen() const { return 4*(getAHHeader()->payloadLen + 2); }
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
||||
|
||||
private:
|
||||
// this layer supports parsing only
|
||||
AuthenticationHeaderLayer() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class ESPLayer
|
||||
* Represents an IPSec Encapsulating Security Payload (ESP) layer
|
||||
*/
|
||||
class ESPLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
ESPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ESP; }
|
||||
|
||||
ipsec_esp* getESPHeader() const { return (ipsec_esp*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The Security Parameters Index (SPI) field value
|
||||
*/
|
||||
uint32_t getSPI() const;
|
||||
|
||||
/**
|
||||
* @return The sequence number value
|
||||
*/
|
||||
uint32_t getSequenceNumber() const;
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of a ESP layer
|
||||
* @param[in] dataLen The length of byte stream
|
||||
* @return True if the data is valid and can represent an ESP layer
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size of the ESP header (8 bytes)
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(ipsec_esp); }
|
||||
|
||||
/**
|
||||
* The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer)
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; }
|
||||
|
||||
private:
|
||||
// this layer supports parsing only
|
||||
ESPLayer() {}
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool AuthenticationHeaderLayer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
if (dataLen < sizeof(ipsec_authentication_header))
|
||||
return false;
|
||||
|
||||
size_t payloadLen = 4 * (data[1] + 2);
|
||||
if (payloadLen < sizeof(ipsec_authentication_header) || payloadLen > dataLen)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESPLayer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
return dataLen >= sizeof(ipsec_esp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PACKETPP_IPSEC_LAYER
|
||||
657
pcappp/include/pcapplusplus/IPv4Layer.h
Normal file
657
pcappp/include/pcapplusplus/IPv4Layer.h
Normal file
@@ -0,0 +1,657 @@
|
||||
#ifndef PACKETPP_IPV4_LAYER
|
||||
#define PACKETPP_IPV4_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
#include "IpAddress.h"
|
||||
#include "IPLayer.h"
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct iphdr
|
||||
* Represents an IPv4 protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct iphdr
|
||||
{
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/** IP header length, has the value of 5 for IPv4 */
|
||||
uint8_t internetHeaderLength:4,
|
||||
/** IP version number, has the value of 4 for IPv4 */
|
||||
ipVersion:4;
|
||||
#else
|
||||
/** IP version number, has the value of 4 for IPv4 */
|
||||
uint8_t ipVersion:4,
|
||||
/** IP header length, has the value of 5 for IPv4 */
|
||||
internetHeaderLength:4;
|
||||
#endif
|
||||
/** type of service, same as Differentiated Services Code Point (DSCP)*/
|
||||
uint8_t typeOfService;
|
||||
/** Entire packet (fragment) size, including header and data, in bytes */
|
||||
uint16_t totalLength;
|
||||
/** Identification field. Primarily used for uniquely identifying the group of fragments of a single IP datagram*/
|
||||
uint16_t ipId;
|
||||
/** Fragment offset field, measured in units of eight-byte blocks (64 bits) */
|
||||
uint16_t fragmentOffset;
|
||||
/** An eight-bit time to live field helps prevent datagrams from persisting (e.g. going in circles) on an internet. In practice, the field has become a hop count */
|
||||
uint8_t timeToLive;
|
||||
/** Defines the protocol used in the data portion of the IP datagram. Must be one of ::IPProtocolTypes */
|
||||
uint8_t protocol;
|
||||
/** Error-checking of the header */
|
||||
uint16_t headerChecksum;
|
||||
/** IPv4 address of the sender of the packet */
|
||||
uint32_t ipSrc;
|
||||
/** IPv4 address of the receiver of the packet */
|
||||
uint32_t ipDst;
|
||||
/*The options start here. */
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* An enum for all possible IPv4 and IPv6 protocol types
|
||||
*/
|
||||
enum IPProtocolTypes
|
||||
{
|
||||
/** Dummy protocol for TCP */
|
||||
PACKETPP_IPPROTO_IP = 0,
|
||||
/** IPv6 Hop-by-Hop options */
|
||||
PACKETPP_IPPROTO_HOPOPTS = 0,
|
||||
/** Internet Control Message Protocol */
|
||||
PACKETPP_IPPROTO_ICMP = 1,
|
||||
/** Internet Gateway Management Protocol */
|
||||
PACKETPP_IPPROTO_IGMP = 2,
|
||||
/** IPIP tunnels (older KA9Q tunnels use 94) */
|
||||
PACKETPP_IPPROTO_IPIP = 4,
|
||||
/** Transmission Control Protocol */
|
||||
PACKETPP_IPPROTO_TCP = 6,
|
||||
/** Exterior Gateway Protocol */
|
||||
PACKETPP_IPPROTO_EGP = 8,
|
||||
/** PUP protocol */
|
||||
PACKETPP_IPPROTO_PUP = 12,
|
||||
/** User Datagram Protocol */
|
||||
PACKETPP_IPPROTO_UDP = 17,
|
||||
/** XNS IDP protocol */
|
||||
PACKETPP_IPPROTO_IDP = 22,
|
||||
/** IPv6 header */
|
||||
PACKETPP_IPPROTO_IPV6 = 41,
|
||||
/** IPv6 Routing header */
|
||||
PACKETPP_IPPROTO_ROUTING = 43,
|
||||
/** IPv6 fragmentation header */
|
||||
PACKETPP_IPPROTO_FRAGMENT = 44,
|
||||
/** GRE protocol */
|
||||
PACKETPP_IPPROTO_GRE = 47,
|
||||
/** encapsulating security payload */
|
||||
PACKETPP_IPPROTO_ESP = 50,
|
||||
/** authentication header */
|
||||
PACKETPP_IPPROTO_AH = 51,
|
||||
/** ICMPv6 */
|
||||
PACKETPP_IPPROTO_ICMPV6 = 58,
|
||||
/** IPv6 no next header */
|
||||
PACKETPP_IPPROTO_NONE = 59,
|
||||
/** IPv6 Destination options */
|
||||
PACKETPP_IPPROTO_DSTOPTS = 60,
|
||||
/** Raw IP packets */
|
||||
PACKETPP_IPPROTO_RAW = 255,
|
||||
/** Maximum value */
|
||||
PACKETPP_IPPROTO_MAX
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An enum for supported IPv4 option types
|
||||
*/
|
||||
enum IPv4OptionTypes
|
||||
{
|
||||
/** End of Options List */
|
||||
IPV4OPT_EndOfOptionsList = 0,
|
||||
/** No Operation */
|
||||
IPV4OPT_NOP = 1,
|
||||
/** Record Route */
|
||||
IPV4OPT_RecordRoute = 7,
|
||||
/** MTU Probe */
|
||||
IPV4OPT_MTUProbe = 11,
|
||||
/** MTU Reply */
|
||||
IPV4OPT_MTUReply = 12,
|
||||
/** Quick-Start */
|
||||
IPV4OPT_QuickStart = 25,
|
||||
/** Timestamp */
|
||||
IPV4OPT_Timestamp = 68,
|
||||
/** Traceroute */
|
||||
IPV4OPT_Traceroute = 82,
|
||||
/** Security */
|
||||
IPV4OPT_Security = 130,
|
||||
/** Loose Source Route */
|
||||
IPV4OPT_LooseSourceRoute = 131,
|
||||
/** Extended Security */
|
||||
IPV4OPT_ExtendedSecurity = 133,
|
||||
/** Commercial Security */
|
||||
IPV4OPT_CommercialSecurity = 134,
|
||||
/** Stream ID */
|
||||
IPV4OPT_StreamID = 136,
|
||||
/** Strict Source Route */
|
||||
IPV4OPT_StrictSourceRoute = 137,
|
||||
/** Extended Internet Protocol */
|
||||
IPV4OPT_ExtendedInternetProtocol = 145,
|
||||
/** Address Extension */
|
||||
IPV4OPT_AddressExtension = 147,
|
||||
/** Router Alert */
|
||||
IPV4OPT_RouterAlert = 148,
|
||||
/** Selective Directed Broadcast */
|
||||
IPV4OPT_SelectiveDirectedBroadcast = 149,
|
||||
/** Dynamic Packet State */
|
||||
IPV4OPT_DynamicPacketState = 151,
|
||||
/** Upstream Multicast Pkt. */
|
||||
IPV4OPT_UpstreamMulticastPkt = 152,
|
||||
/** Unknown IPv4 option */
|
||||
IPV4OPT_Unknown
|
||||
};
|
||||
|
||||
#define PCPP_IP_DONT_FRAGMENT 0x40
|
||||
#define PCPP_IP_MORE_FRAGMENTS 0x20
|
||||
|
||||
/**
|
||||
* @struct IPv4TimestampOptionValue
|
||||
* A struct representing a parsed value of the IPv4 timestamp option. This struct is used returned in IPv4OptionData#getTimestampOptionValue() method
|
||||
*/
|
||||
struct IPv4TimestampOptionValue
|
||||
{
|
||||
/**
|
||||
* An enum for IPv4 timestamp option types
|
||||
*/
|
||||
enum TimestampType
|
||||
{
|
||||
/** Value containing only timestamps */
|
||||
TimestampOnly = 0,
|
||||
/** Value containing both timestamps and IPv4 addresses */
|
||||
TimestampAndIP = 1,
|
||||
/** The IPv4 addresses are prespecified */
|
||||
TimestampsForPrespecifiedIPs = 2,
|
||||
/** Invalid or unknown value type */
|
||||
Unknown = 3
|
||||
};
|
||||
|
||||
/** The timestamp value type */
|
||||
TimestampType type;
|
||||
|
||||
/** A list of timestamps parsed from the IPv4 timestamp option value */
|
||||
std::vector<uint32_t> timestamps;
|
||||
|
||||
/** A list of IPv4 addresses parsed from the IPv4 timestamp option value */
|
||||
std::vector<IPv4Address> ipAddresses;
|
||||
|
||||
/** The default constructor */
|
||||
IPv4TimestampOptionValue() : type(IPv4TimestampOptionValue::Unknown) {}
|
||||
|
||||
/**
|
||||
* Clear the structure. Clean the timestamps and IP addresses vectors and set the type as IPv4TimestampOptionValue#Unknown
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
type = IPv4TimestampOptionValue::Unknown;
|
||||
timestamps.clear();
|
||||
ipAddresses.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4Option
|
||||
* A wrapper class for IPv4 options. This class does not create or modify IPv4 option records, but rather
|
||||
* serves as a wrapper and provides useful methods for retrieving data from them
|
||||
*/
|
||||
class IPv4Option : public TLVRecord<uint8_t, uint8_t>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the option raw data (byte array)
|
||||
* @param[in] optionRawData A pointer to the IPv4 option raw data
|
||||
*/
|
||||
IPv4Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
~IPv4Option() { }
|
||||
|
||||
/**
|
||||
* A method for parsing the IPv4 option value as a list of IPv4 addresses. This method is relevant only for certain types of IPv4 options which their value is a list of IPv4 addresses
|
||||
* such as ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute, etc. This method returns a vector of the IPv4 addresses. Blank IP addresses
|
||||
* (meaning zeroed addresses - 0.0.0.0) will not be added to the returned list. If some error occurs during the parsing or the value is invalid an empty vector is returned
|
||||
* @return A vector of IPv4 addresses parsed from the IPv4 option value
|
||||
*/
|
||||
std::vector<IPv4Address> getValueAsIpList() const
|
||||
{
|
||||
std::vector<IPv4Address> res;
|
||||
|
||||
if (m_Data == NULL)
|
||||
return res;
|
||||
|
||||
size_t dataSize = getDataSize();
|
||||
if (dataSize < 2)
|
||||
return res;
|
||||
|
||||
uint8_t valueOffset = (uint8_t)(1);
|
||||
|
||||
while ((size_t)valueOffset < dataSize)
|
||||
{
|
||||
uint32_t curValue;
|
||||
memcpy(&curValue, m_Data->recordValue + valueOffset, sizeof(uint32_t));
|
||||
if (curValue == 0)
|
||||
break;
|
||||
|
||||
res.push_back(IPv4Address(curValue));
|
||||
|
||||
valueOffset += (uint8_t)(4);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* A method for parsing the IPv4 timestamp option value. This method is relevant only for IPv4 timestamp option. For other option types an empty result will be returned.
|
||||
* The returned structure contains the timestamp value type (timestamp only, timestamp + IP addresses, etc.) as well as 2 vectors containing the list of timestamps and the list
|
||||
* of IP addresses (if applicable for the timestamp value type). Blank timestamps or IP addresses (meaning zeroed values - timestamp=0 or IP address=0.0.0.0) will not be added to
|
||||
* the lists. If some error occurs during the parsing or the value is invalid an empty result is returned
|
||||
* @return A structured containing the IPv4 timestamp value
|
||||
*/
|
||||
IPv4TimestampOptionValue getTimestampOptionValue() const
|
||||
{
|
||||
IPv4TimestampOptionValue res;
|
||||
res.clear();
|
||||
|
||||
if (m_Data == NULL)
|
||||
return res;
|
||||
|
||||
if (getIPv4OptionType() != IPV4OPT_Timestamp)
|
||||
return res;
|
||||
|
||||
size_t dataSize = getDataSize();
|
||||
if (dataSize < 2)
|
||||
return res;
|
||||
|
||||
res.type = (IPv4TimestampOptionValue::TimestampType)m_Data->recordValue[1];
|
||||
|
||||
uint8_t valueOffset = (uint8_t)(2);
|
||||
bool readIPAddr = (res.type == IPv4TimestampOptionValue::TimestampAndIP);
|
||||
|
||||
while ((size_t)valueOffset < dataSize)
|
||||
{
|
||||
uint32_t curValue;
|
||||
memcpy(&curValue, m_Data->recordValue + valueOffset, sizeof(uint32_t));
|
||||
if (curValue == 0)
|
||||
break;
|
||||
|
||||
if (readIPAddr)
|
||||
res.ipAddresses.push_back(IPv4Address(curValue));
|
||||
else
|
||||
res.timestamps.push_back(curValue);
|
||||
|
||||
if (res.type == IPv4TimestampOptionValue::TimestampAndIP)
|
||||
readIPAddr = !readIPAddr;
|
||||
|
||||
valueOffset += (uint8_t)(4);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IPv4 option type casted as pcpp::IPv4OptionTypes enum
|
||||
*/
|
||||
IPv4OptionTypes getIPv4OptionType() const
|
||||
{
|
||||
if (m_Data == NULL)
|
||||
return IPV4OPT_Unknown;
|
||||
|
||||
return (IPv4OptionTypes)m_Data->recordType;
|
||||
}
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
if (m_Data == NULL)
|
||||
return 0;
|
||||
|
||||
if (getIPv4OptionType() == (uint8_t)IPV4OPT_EndOfOptionsList || m_Data->recordType == (uint8_t)IPV4OPT_NOP)
|
||||
return sizeof(uint8_t);
|
||||
|
||||
return (size_t)m_Data->recordLen;
|
||||
}
|
||||
|
||||
size_t getDataSize() const
|
||||
{
|
||||
if (m_Data == NULL)
|
||||
return 0;
|
||||
|
||||
if (getIPv4OptionType() == (uint8_t)IPV4OPT_EndOfOptionsList || m_Data->recordType == (uint8_t)IPV4OPT_NOP)
|
||||
return (size_t)0;
|
||||
|
||||
return (size_t)m_Data->recordLen - (2*sizeof(uint8_t));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4OptionBuilder
|
||||
* A class for building IPv4 option records. This builder receives the IPv4 option parameters in its c'tor,
|
||||
* builds the IPv4 option raw buffer and provides a build() method to get a IPv4Option object out of it
|
||||
*/
|
||||
class IPv4OptionBuilder : public TLVRecordBuilder
|
||||
{
|
||||
private:
|
||||
bool m_BuilderParamsValid;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv4 options which their value is a byte array. The IPv4Option object can be later
|
||||
* retrieved by calling build()
|
||||
* @param[in] optionType IPv4 option type
|
||||
* @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way.
|
||||
* For option types ::IPV4OPT_NOP and ::IPV4OPT_EndOfOptionsList this parameter is ignored (expected to be NULL) as these
|
||||
* option types don't contain any data
|
||||
* @param[in] optionValueLen Option value length in bytes
|
||||
*/
|
||||
IPv4OptionBuilder(IPv4OptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) { m_BuilderParamsValid = true; }
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv4 options which have a 2-byte value. The IPv4Option object can be later retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType IPv4 option type
|
||||
* @param[in] optionValue A 2-byte option value
|
||||
*/
|
||||
IPv4OptionBuilder(IPv4OptionTypes optionType, uint16_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) { m_BuilderParamsValid = true; }
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv4 options which their value is a list of IPv4 addresses, for example:
|
||||
* ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute. The IPv4Option object can be later retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType IPv4 option type
|
||||
* @param[in] ipList A vector of IPv4 addresses that will be used as the option value
|
||||
*/
|
||||
IPv4OptionBuilder(IPv4OptionTypes optionType, const std::vector<IPv4Address>& ipList);
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv4 timestamp option (::IPV4OPT_Timestamp). The IPv4Option object can be later retrieved by calling build()
|
||||
* @param[in] timestampValue The timestamp value to build the IPv4 option with
|
||||
*/
|
||||
IPv4OptionBuilder(const IPv4TimestampOptionValue& timestampValue);
|
||||
|
||||
/**
|
||||
* Build the IPv4Option object out of the parameters defined in the c'tor
|
||||
* @return The IPv4Option object
|
||||
*/
|
||||
IPv4Option build() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4Layer
|
||||
* Represents an IPv4 protocol layer
|
||||
*/
|
||||
class IPv4Layer : 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 iphdr)
|
||||
* @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
|
||||
*/
|
||||
IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* 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 iphdr)
|
||||
* @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
|
||||
* @param[in] setTotalLenAsDataLen When setting this value to "true" or when using the other c'tor, the layer data length is calculated
|
||||
* from iphdr#totalLength field. When setting to "false" the data length is set as the value of dataLen parameter. Please notice that
|
||||
* if iphdr#totalLength is equal to zero (which can happen in TCP Segmentation Offloading), this flag is ignored and the layer data
|
||||
* length is calculated by the actual data captured on the wire
|
||||
*/
|
||||
IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen);
|
||||
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new IPv4 header with empty fields
|
||||
*/
|
||||
IPv4Layer();
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new IPv4 header with source and destination IPv4 addresses
|
||||
* @param[in] srcIP Source IPv4 address
|
||||
* @param[in] dstIP Destination IPv4 address
|
||||
*/
|
||||
IPv4Layer(const IPv4Address& srcIP, const IPv4Address& dstIP);
|
||||
|
||||
/**
|
||||
* A copy constructor that copy the entire header from the other IPv4Layer (including IPv4 options)
|
||||
*/
|
||||
IPv4Layer(const IPv4Layer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator that first delete all data from current layer and then copy the entire header from the other IPv4Layer (including IPv4 options)
|
||||
*/
|
||||
IPv4Layer& operator=(const IPv4Layer& other);
|
||||
|
||||
/**
|
||||
* Get a pointer to the IPv4 header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref iphdr
|
||||
*/
|
||||
iphdr* getIPv4Header() const { return (iphdr*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv4Address(),
|
||||
* 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 getSrcIPv4Address(); }
|
||||
|
||||
/**
|
||||
* Get the source IP address in the form of IPv4Address
|
||||
* @return An IPv4Address containing the source address
|
||||
*/
|
||||
IPv4Address getSrcIPv4Address() const { return getIPv4Header()->ipSrc; }
|
||||
|
||||
/**
|
||||
* Set the source IP address
|
||||
* @param[in] ipAddr The IP address to set
|
||||
*/
|
||||
void setSrcIPv4Address(const IPv4Address& ipAddr) { getIPv4Header()->ipSrc = ipAddr.toInt(); }
|
||||
|
||||
/**
|
||||
* Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv4Address(),
|
||||
* 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 getDstIPv4Address(); }
|
||||
|
||||
/**
|
||||
* Get the destination IP address in the form of IPv4Address
|
||||
* @return An IPv4Address containing the destination address
|
||||
*/
|
||||
IPv4Address getDstIPv4Address() const { return getIPv4Header()->ipDst; }
|
||||
|
||||
/**
|
||||
* Set the dest IP address
|
||||
* @param[in] ipAddr The IP address to set
|
||||
*/
|
||||
void setDstIPv4Address(const IPv4Address& ipAddr) { getIPv4Header()->ipDst = ipAddr.toInt(); }
|
||||
|
||||
/**
|
||||
* @return True if this packet is a fragment (in sense of IP fragmentation), false otherwise
|
||||
*/
|
||||
bool isFragment() const;
|
||||
|
||||
/**
|
||||
* @return True if this packet is a fragment (in sense of IP fragmentation) and is the first fragment
|
||||
* (which usually contains the L4 header). Return false otherwise (not a fragment or not the first fragment)
|
||||
*/
|
||||
bool isFirstFragment() const;
|
||||
|
||||
/**
|
||||
* @return True if this packet is a fragment (in sense of IP fragmentation) and is the last fragment.
|
||||
* Return false otherwise (not a fragment or not the last fragment)
|
||||
*/
|
||||
bool isLastFragment() const;
|
||||
|
||||
/**
|
||||
* @return A bitmask containing the fragmentation flags (e.g IP_DONT_FRAGMENT or IP_MORE_FRAGMENTS)
|
||||
*/
|
||||
uint8_t getFragmentFlags() const;
|
||||
|
||||
/**
|
||||
* @return The fragment offset in case this packet is a fragment, 0 otherwise
|
||||
*/
|
||||
uint16_t getFragmentOffset() const;
|
||||
|
||||
/**
|
||||
* Get an IPv4 option by type.
|
||||
* @param[in] option IPv4 option type
|
||||
* @return An IPv4Option object that contains the first option that matches this type, or logical NULL
|
||||
* (IPv4Option#isNull() == true) if no such option found
|
||||
*/
|
||||
IPv4Option getOption(IPv4OptionTypes option) const;
|
||||
|
||||
/**
|
||||
* @return The first IPv4 option in the packet. If the current layer contains no options the returned value will contain
|
||||
* a logical NULL (IPv4Option#isNull() == true)
|
||||
*/
|
||||
IPv4Option getFirstOption() const;
|
||||
|
||||
/**
|
||||
* Get the IPv4 option that comes after a given option. If the given option was the last one, the
|
||||
* returned value will contain a logical NULL (IPv4Option#isNull() == true)
|
||||
* @param[in] option An IPv4 option object that exists in the current layer
|
||||
* @return A IPv4Option object that contains the IPv4 option data that comes next, or logical NULL if the given
|
||||
* IPv4 option: (1) was the last one; or (2) contains a logical NULL; or (3) doesn't belong to this packet
|
||||
*/
|
||||
IPv4Option getNextOption(IPv4Option& option) const;
|
||||
|
||||
/**
|
||||
* @return The number of IPv4 options in this layer
|
||||
*/
|
||||
size_t getOptionCount() const;
|
||||
|
||||
/**
|
||||
* Add a new IPv4 option at the end of the layer (after the last IPv4 option)
|
||||
* @param[in] optionBuilder An IPv4OptionBuilder object that contains the IPv4 option data to be added
|
||||
* @return A IPv4Option object that contains the newly added IPv4 option data or logical NULL
|
||||
* (IPv4Option#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
|
||||
* printed to log
|
||||
*/
|
||||
IPv4Option addOption(const IPv4OptionBuilder& optionBuilder);
|
||||
|
||||
/**
|
||||
* Add a new IPv4 option after an existing one
|
||||
* @param[in] optionBuilder An IPv4OptionBuilder object that contains the requested IPv4 option data to be added
|
||||
* @param[in] prevOptionType The IPv4 option which the newly added option should come after. This is an optional parameter which
|
||||
* gets a default value of ::IPV4OPT_Unknown if omitted, which means the new option will be added as the first option in the layer
|
||||
* @return A IPv4Option object containing the newly added IPv4 option data or logical NULL
|
||||
* (IPv4Option#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
|
||||
* printed to log
|
||||
*/
|
||||
IPv4Option addOptionAfter(const IPv4OptionBuilder& optionBuilder, IPv4OptionTypes prevOptionType = IPV4OPT_Unknown);
|
||||
|
||||
/**
|
||||
* Remove an IPv4 option
|
||||
* @param[in] option The option type to remove
|
||||
* @return True if option was removed successfully or false if option type wasn't found or failed to shorten the layer. If an option appears twice in the layer, its first instance
|
||||
* will be removed
|
||||
*/
|
||||
bool removeOption(IPv4OptionTypes option);
|
||||
|
||||
/**
|
||||
* Remove all IPv4 options from the layer
|
||||
* @return True if options removed successfully or false if some error occurred (an appropriate error message will be printed to log)
|
||||
*/
|
||||
bool removeAllOptions();
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers:
|
||||
* - UdpLayer
|
||||
* - TcpLayer
|
||||
* - IcmpLayer
|
||||
* - IPv4Layer (IP-in-IP)
|
||||
* - IPv6Layer (IP-in-IP)
|
||||
* - GreLayer
|
||||
* - IgmpLayer
|
||||
* - AuthenticationHeaderLayer (IPSec)
|
||||
* - ESPLayer (IPSec)
|
||||
*
|
||||
* Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of IPv4 header (including IPv4 options if exist)
|
||||
*/
|
||||
size_t getHeaderLen() const { return (size_t)((uint16_t)(getIPv4Header()->internetHeaderLength) * 4) + m_TempHeaderExtension; }
|
||||
|
||||
/**
|
||||
* Calculate the following fields:
|
||||
* - iphdr#ipVersion = 4;
|
||||
* - iphdr#totalLength = total packet length
|
||||
* - iphdr#headerChecksum = calculated
|
||||
* - iphdr#protocol = 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; }
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of a byte stream of IP packet
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @return True if the data is valid and can represent an IPv4 packet
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
private:
|
||||
int m_NumOfTrailingBytes;
|
||||
int m_TempHeaderExtension;
|
||||
TLVRecordReader<IPv4Option> m_OptionReader;
|
||||
|
||||
void copyLayerData(const IPv4Layer& other);
|
||||
uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(iphdr); }
|
||||
IPv4Option addOptionAt(const IPv4OptionBuilder& optionBuilder, int offset);
|
||||
void adjustOptionsTrailer(size_t totalOptSize);
|
||||
void initLayer();
|
||||
void initLayerInPacket(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen);
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool IPv4Layer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
const iphdr* hdr = reinterpret_cast<const iphdr*>(data);
|
||||
return dataLen >= sizeof(iphdr) && hdr->ipVersion == 4 && hdr->internetHeaderLength >= 5;
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_IPV4_LAYER */
|
||||
536
pcappp/include/pcapplusplus/IPv6Extensions.h
Normal file
536
pcappp/include/pcapplusplus/IPv6Extensions.h
Normal file
@@ -0,0 +1,536 @@
|
||||
#ifndef PACKETPP_IPV6_EXTENSION
|
||||
#define PACKETPP_IPV6_EXTENSION
|
||||
|
||||
#include <vector>
|
||||
#include "IpAddress.h"
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class IPv6Extension
|
||||
* A base class for all supported IPv6 extensions. This class is abstract, meaning it cannot be instantiated or copied
|
||||
* (has private c'tor and copy c'tor)
|
||||
*/
|
||||
class IPv6Extension
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum representing all supported IPv6 extension types
|
||||
*/
|
||||
enum IPv6ExtensionType
|
||||
{
|
||||
/** Hop-By-Hop extension type */
|
||||
IPv6HopByHop = 0,
|
||||
/** Routing extension type */
|
||||
IPv6Routing = 43,
|
||||
/** IPv6 fragmentation extension type */
|
||||
IPv6Fragmentation = 44,
|
||||
/** Authentication Header extension type */
|
||||
IPv6AuthenticationHdr = 51,
|
||||
/** Destination extension type */
|
||||
IPv6Destination = 60,
|
||||
/** Unknown or unsupported extension type */
|
||||
IPv6ExtensionUnknown = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* @return The size of extension in bytes, meaning (for most extensions): 8 * ([headerLen field] + 1)
|
||||
*/
|
||||
virtual size_t getExtensionLen() const { return 8 * (getBaseHeader()->headerLen+1); }
|
||||
|
||||
/**
|
||||
* @return The type of the extension
|
||||
*/
|
||||
IPv6ExtensionType getExtensionType() const { return m_ExtType; }
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~IPv6Extension();
|
||||
|
||||
/**
|
||||
* @return A pointer to the next header or NULL if the extension is the last one
|
||||
*/
|
||||
IPv6Extension* getNextHeader() const { return m_NextHeader; }
|
||||
|
||||
protected:
|
||||
|
||||
struct ipv6_ext_base_header
|
||||
{
|
||||
uint8_t nextHeader;
|
||||
uint8_t headerLen;
|
||||
};
|
||||
|
||||
// protected c'tor
|
||||
IPv6Extension(IDataContainer* dataContainer, size_t offset) :
|
||||
m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(dataContainer), m_Offset(offset), m_ShadowData(NULL) {}
|
||||
|
||||
// protected empty c'tor
|
||||
IPv6Extension() :
|
||||
m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(NULL), m_Offset(0), m_ShadowData(NULL) {}
|
||||
|
||||
// protected assignment operator
|
||||
IPv6Extension& operator=(const IPv6Extension& other);
|
||||
|
||||
uint8_t* getDataPtr() const;
|
||||
|
||||
void initShadowPtr(size_t size);
|
||||
|
||||
ipv6_ext_base_header* getBaseHeader() const { return (ipv6_ext_base_header*)getDataPtr(); }
|
||||
|
||||
void setNextHeader(IPv6Extension* nextHeader) { m_NextHeader = nextHeader; }
|
||||
|
||||
IPv6Extension* m_NextHeader;
|
||||
IPv6ExtensionType m_ExtType;
|
||||
|
||||
private:
|
||||
IDataContainer* m_DataContainer;
|
||||
size_t m_Offset;
|
||||
uint8_t* m_ShadowData;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6FragmentationHeader
|
||||
* Represents an IPv6 fragmentation extension header and allows easy access to all fragmentation parameters
|
||||
*/
|
||||
class IPv6FragmentationHeader : public IPv6Extension
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct ipv6_frag_header
|
||||
* A struct representing IPv6 fragmentation header
|
||||
*/
|
||||
struct ipv6_frag_header
|
||||
{
|
||||
/** Next header type */
|
||||
uint8_t nextHeader;
|
||||
/** Fragmentation header size is fixed 8 bytes, so len is always zero */
|
||||
uint8_t headerLen;
|
||||
/** Offset, in 8-octet units, relative to the start of the fragmentable part of the original packet
|
||||
* plus 1-bit indicating if more fragments will follow */
|
||||
uint16_t fragOffsetAndFlags;
|
||||
/** packet identification value. Needed for reassembly of the original packet */
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for creating a new IPv6 fragmentation extension object not bounded to a packet. Useful for adding new extensions to an
|
||||
* IPv6 layer with IPv6Layer#addExtension()
|
||||
* @param[in] fragId Fragmentation ID
|
||||
* @param[in] fragOffset Fragmentation offset
|
||||
* @param[in] lastFragment Indicates whether this fragment is the last one
|
||||
*/
|
||||
IPv6FragmentationHeader(uint32_t fragId, uint16_t fragOffset, bool lastFragment);
|
||||
|
||||
/**
|
||||
* Get a pointer to the fragmentation header. Notice the returned pointer points directly to the data, so every change will modify
|
||||
* the actual packet data
|
||||
* @return A pointer to the @ref ipv6_frag_header
|
||||
*/
|
||||
ipv6_frag_header* getFragHeader() const { return (ipv6_frag_header*)getDataPtr(); }
|
||||
|
||||
/**
|
||||
* @return True if this is the first fragment (which usually contains the L4 header), false otherwise
|
||||
*/
|
||||
bool isFirstFragment() const;
|
||||
|
||||
/**
|
||||
* @return True if this is the last fragment, false otherwise
|
||||
*/
|
||||
bool isLastFragment() const;
|
||||
|
||||
/**
|
||||
* @return True if the "more fragments" bit is set, meaning more fragments are expected to follow this fragment
|
||||
*/
|
||||
bool isMoreFragments() const;
|
||||
|
||||
/**
|
||||
* @return The fragment offset
|
||||
*/
|
||||
uint16_t getFragmentOffset() const;
|
||||
|
||||
private:
|
||||
|
||||
IPv6FragmentationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset)
|
||||
{
|
||||
m_ExtType = IPv6Fragmentation;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An abstract base class for Hop-By-Hop and Destination IPv6 extensions which their structure contains Type-Length-Value (TLV) options.
|
||||
* This class provides access to these options and their data as well as methods to create new options. Notice this class is abstract
|
||||
* and cannot be instantiated
|
||||
*/
|
||||
class IPv6TLVOptionHeader : public IPv6Extension
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @class IPv6Option
|
||||
* A class representing a Type-Length-Value (TLV) options that are used inside Hop-By-Hop and Destinations IPv6
|
||||
* extensions. This class does not create or modify IPv6 option records, but rather serves as a wrapper and
|
||||
* provides useful methods for retrieving data from them
|
||||
*/
|
||||
class IPv6Option : public TLVRecord<uint8_t, uint8_t>
|
||||
{
|
||||
public:
|
||||
|
||||
static const uint8_t Pad0OptionType = 0;
|
||||
static const uint8_t PadNOptionType = 1;
|
||||
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the option raw data (byte array)
|
||||
* @param[in] optionRawData A pointer to the attribute raw data
|
||||
*/
|
||||
IPv6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
~IPv6Option() { }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
if (m_Data->recordType == Pad0OptionType)
|
||||
return sizeof(uint8_t);
|
||||
|
||||
return (size_t)(m_Data->recordLen + sizeof(uint16_t));
|
||||
}
|
||||
|
||||
size_t getDataSize() const
|
||||
{
|
||||
if (m_Data->recordType == Pad0OptionType)
|
||||
return (size_t)0;
|
||||
|
||||
return (size_t)m_Data->recordLen;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6TLVOptionBuilder
|
||||
* A class for building IPv6 Type-Length-Value (TLV) options. This builder receives the option parameters in its c'tor,
|
||||
* builds the option raw buffer and provides a method to build a IPv6Option object out of it
|
||||
*/
|
||||
class IPv6TLVOptionBuilder : public TLVRecordBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv6 TLV options which their value is a byte array. The IPv6Option object can later
|
||||
* be retrieved by calling build()
|
||||
* @param[in] optType IPv6 option type
|
||||
* @param[in] optValue A buffer containing the option value. This buffer is read-only and isn't modified in any way
|
||||
* @param[in] optValueLen Option value length in bytes
|
||||
*/
|
||||
IPv6TLVOptionBuilder(uint8_t optType, const uint8_t* optValue, uint8_t optValueLen) :
|
||||
TLVRecordBuilder(optType, optValue, optValueLen) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv6 TLV options which have a 1-byte value. The IPv6Option object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] optType IPv6 option type
|
||||
* @param[in] optValue A 1-byte option value
|
||||
*/
|
||||
IPv6TLVOptionBuilder(uint8_t optType, uint8_t optValue) :
|
||||
TLVRecordBuilder(optType, optValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building IPv6 TLV options which have a 2-byte value. The IPv6Option object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] optType IPv6 option type
|
||||
* @param[in] optValue A 2-byte option value
|
||||
*/
|
||||
IPv6TLVOptionBuilder(uint8_t optType, uint16_t optValue) :
|
||||
TLVRecordBuilder(optType, optValue) { }
|
||||
|
||||
/**
|
||||
* A copy c'tor that creates an instance of this class out of another instance and copies all the data from it
|
||||
* @param[in] other The instance to copy data from
|
||||
*/
|
||||
IPv6TLVOptionBuilder(const IPv6TLVOptionBuilder& other) :
|
||||
TLVRecordBuilder(other) {}
|
||||
|
||||
/**
|
||||
* Assignment operator that copies all data from another instance of IPv6TLVOptionBuilder
|
||||
* @param[in] other The instance to assign from
|
||||
*/
|
||||
IPv6TLVOptionBuilder& operator=(const IPv6TLVOptionBuilder& other)
|
||||
{
|
||||
TLVRecordBuilder::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the IPv6Option object out of the parameters defined in the c'tor
|
||||
* @return The IPv6Option object
|
||||
*/
|
||||
IPv6Option build() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve an option by its type
|
||||
* @param[in] optionType Option type
|
||||
* @return An IPv6Option object that wraps the option data. If option isn't found a logical NULL is returned
|
||||
* (IPv6Option#isNull() == true)
|
||||
*/
|
||||
IPv6Option getOption(uint8_t optionType) const;
|
||||
|
||||
/**
|
||||
* @return An IPv6Option that wraps the first option data or logical NULL (IPv6Option#isNull() == true) if no options exist
|
||||
*/
|
||||
IPv6Option getFirstOption() const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the option that comes after the option given as the parameter
|
||||
* @param[in] option A pointer to an option instance
|
||||
* @return An IPv6Option object that wraps the option data. In the following cases logical NULL (IPv6Option#isNull() == true)
|
||||
* is returned:
|
||||
* (1) input parameter is out-of-bounds for this extension or
|
||||
* (2) the next option doesn't exist or
|
||||
* (3) the input option is NULL
|
||||
*/
|
||||
IPv6Option getNextOption(IPv6Option& option) const;
|
||||
|
||||
/**
|
||||
* @returns The number of options this IPv6 extension contains
|
||||
*/
|
||||
size_t getOptionCount() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** A private c'tor to keep this object from being constructed */
|
||||
IPv6TLVOptionHeader(const std::vector<IPv6TLVOptionBuilder>& options);
|
||||
|
||||
IPv6TLVOptionHeader(IDataContainer* dataContainer, size_t offset);
|
||||
|
||||
private:
|
||||
|
||||
TLVRecordReader<IPv6Option> m_OptionReader;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6HopByHopHeader
|
||||
* Represents IPv6 Hop-By-Hop extension header and allows easy access to all of its data including the TLV options stored
|
||||
*/
|
||||
class IPv6HopByHopHeader : public IPv6TLVOptionHeader
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for creating a new IPv6 Hop-By-Hop extension object not bounded to a packet. Useful for adding new extensions to an
|
||||
* IPv6 layer with IPv6Layer#addExtension()
|
||||
* @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that will be stored in the
|
||||
* extension data. Notice this vector is read-only and its content won't be modified
|
||||
*/
|
||||
IPv6HopByHopHeader(const std::vector<IPv6TLVOptionBuilder>& options) : IPv6TLVOptionHeader(options) { m_ExtType = IPv6HopByHop; }
|
||||
|
||||
private:
|
||||
|
||||
IPv6HopByHopHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) { m_ExtType = IPv6HopByHop; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6DestinationHeader
|
||||
* Represents IPv6 destination extension header and allows easy access to all of its data including the TLV options stored in it
|
||||
*/
|
||||
class IPv6DestinationHeader : public IPv6TLVOptionHeader
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for creating a new IPv6 destination extension object not bounded to a packet. Useful for adding new extensions to an
|
||||
* IPv6 layer with IPv6Layer#addExtension()
|
||||
* @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that will be stored in the
|
||||
* extension data. Notice this vector is read-only and its content won't be modified
|
||||
*/
|
||||
IPv6DestinationHeader(const std::vector<IPv6TLVOptionBuilder>& options) : IPv6TLVOptionHeader(options) { m_ExtType = IPv6Destination; }
|
||||
|
||||
private:
|
||||
|
||||
IPv6DestinationHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) { m_ExtType = IPv6Destination; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6RoutingHeader
|
||||
* Represents IPv6 routing extension header and allows easy access to all of its data
|
||||
*/
|
||||
class IPv6RoutingHeader : public IPv6Extension
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct ipv6_routing_header
|
||||
* A struct representing the fixed part of the IPv6 routing extension header
|
||||
*/
|
||||
struct ipv6_routing_header
|
||||
{
|
||||
/** Next header type */
|
||||
uint8_t nextHeader;
|
||||
/** The length of this header, in multiples of 8 octets, not including the first 8 octets */
|
||||
uint8_t headerLen;
|
||||
/** A value representing the routing type */
|
||||
uint8_t routingType;
|
||||
/** Number of nodes this packet still has to visit before reaching its final destination */
|
||||
uint8_t segmentsLeft;
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for creating a new IPv6 routing extension object not bounded to a packet. Useful for adding new extensions to an
|
||||
* IPv6 layer with IPv6Layer#addExtension()
|
||||
* @param[in] routingType Routing type value (will be written to ipv6_routing_header#routingType field)
|
||||
* @param[in] segmentsLeft Segments left value (will be written to ipv6_routing_header#segmentsLeft field)
|
||||
* @param[in] additionalRoutingData A pointer to a buffer containing the additional routing data for this extension. Notice this
|
||||
* buffer is read-only and its content isn't modified
|
||||
* @param[in] additionalRoutingDataLen The length of the additional routing data buffer
|
||||
*/
|
||||
IPv6RoutingHeader(uint8_t routingType, uint8_t segmentsLeft, const uint8_t* additionalRoutingData, size_t additionalRoutingDataLen);
|
||||
|
||||
/**
|
||||
* Get a pointer to the fixed part of the routing header. Notice the return pointer points directly to the data, so every change will modify
|
||||
* the actual packet data
|
||||
* @return A pointer to the @ref ipv6_routing_header
|
||||
*/
|
||||
ipv6_routing_header* getRoutingHeader() const { return (ipv6_routing_header*)getDataPtr(); }
|
||||
|
||||
/**
|
||||
* @return A pointer to the buffer containing the additional routing data for this extension. Notice that any change in this buffer
|
||||
* will lead to a change in the extension data
|
||||
*/
|
||||
uint8_t* getRoutingAdditionalData() const;
|
||||
|
||||
/**
|
||||
* @return The length of the additional routing parameters buffer
|
||||
*/
|
||||
size_t getRoutingAdditionalDataLength() const;
|
||||
|
||||
/**
|
||||
* In many cases the additional routing data is actually IPv6 address(es). This method converts the raw buffer data into an IPv6 address
|
||||
* @param[in] offset An offset in the additional routing buffer pointing to where the IPv6 address begins. In some cases there are
|
||||
* multiple IPv6 addresses in the additional routing data buffer so this offset points to where the request IPv6 address begins. Also,
|
||||
* even if there is only one IPv6 address in this buffer, sometimes it isn't written in the beginning of the buffer, so the offset points
|
||||
* to where the IPv6 address begins. This is an optional parameter and the default offset is 0
|
||||
* @return The IPv6 address stored in the additional routing data buffer from the offset defined by the user. If offset is out-of-bounds
|
||||
* of the extension of doesn't have 16 bytes (== the length of IPv6 address) until the end of the buffer - IPv6Address#Zero is returned
|
||||
*/
|
||||
IPv6Address getRoutingAdditionalDataAsIPv6Address(size_t offset = 0) const;
|
||||
|
||||
private:
|
||||
|
||||
IPv6RoutingHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6Routing; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv6AuthenticationHeader
|
||||
* Represents IPv6 authentication header extension (used in IPSec protocol) and allows easy access to all of its data
|
||||
*/
|
||||
class IPv6AuthenticationHeader : public IPv6Extension
|
||||
{
|
||||
friend class IPv6Layer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct ipv6_authentication_header
|
||||
* A struct representing the fixed part of the IPv6 authentication header extension
|
||||
*/
|
||||
struct ipv6_authentication_header
|
||||
{
|
||||
/** Next header type */
|
||||
uint8_t nextHeader;
|
||||
/** The length of this Authentication Header in 4-octet units, minus 2. For example, an AH value of 4
|
||||
* equals: [ 3×(32-bit fixed-length AH fields) + 3×(32-bit ICV fields) − 2 ] and thus an AH value of 4 means 24 octets */
|
||||
uint8_t headerLen;
|
||||
/** Reserved bytes, all zeros */
|
||||
uint16_t reserved;
|
||||
/** Arbitrary value which is used (together with the destination IP address) to identify the security association of the receiving party */
|
||||
uint32_t securityParametersIndex;
|
||||
/** A monotonic strictly increasing sequence number (incremented by 1 for every packet sent) */
|
||||
uint32_t sequenceNumber;
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for creating a new IPv6 authentication header extension object not bounded to a packet. Useful for adding new extensions to an
|
||||
* IPv6 layer with IPv6Layer#addExtension()
|
||||
* @param[in] securityParametersIndex Security Parameters Index (SPI) value (will be written to ipv6_authentication_header#securityParametersIndex field)
|
||||
* @param[in] sequenceNumber Sequence number value (will be written to ipv6_authentication_header#sequenceNumber field)
|
||||
* @param[in] integrityCheckValue A pointer to a buffer containing the integrity check value (ICV) data for this extension. Notice this
|
||||
* pointer is read-only and its content isn't modified in any way
|
||||
* @param[in] integrityCheckValueLen The length of the integrity check value (ICV) buffer
|
||||
*/
|
||||
IPv6AuthenticationHeader(uint32_t securityParametersIndex, uint32_t sequenceNumber, const uint8_t* integrityCheckValue, size_t integrityCheckValueLen);
|
||||
|
||||
/**
|
||||
* Get a pointer to the fixed part of the authentication header. Notice the return pointer points directly to the data, so every change
|
||||
* will modify the actual packet data
|
||||
* @return A pointer to the @ref ipv6_authentication_header
|
||||
*/
|
||||
ipv6_authentication_header* getAuthHeader() const { return (ipv6_authentication_header*)getDataPtr(); }
|
||||
|
||||
/**
|
||||
* @return A pointer to the buffer containing the integrity check value (ICV) for this extension. Notice that any change in this buffer
|
||||
* will lead to a change in the extension data
|
||||
*/
|
||||
uint8_t* getIntegrityCheckValue() const;
|
||||
|
||||
/**
|
||||
* @return The length of the integrity check value (ICV) buffer
|
||||
*/
|
||||
size_t getIntegrityCheckValueLength() const;
|
||||
|
||||
// overridden methods
|
||||
|
||||
/**
|
||||
* In the authentication header the extension length is calculated in a different way than other extensions. The
|
||||
* calculation is: [ 4 * (ipv6_authentication_header#headerLen + 2) ]
|
||||
* @return The length of this extension
|
||||
*/
|
||||
size_t getExtensionLen() const { return 4 * (getBaseHeader()->headerLen+2); }
|
||||
|
||||
private:
|
||||
|
||||
IPv6AuthenticationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6AuthenticationHdr; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_IPV6_EXTENSION
|
||||
279
pcappp/include/pcapplusplus/IPv6Layer.h
Normal file
279
pcappp/include/pcapplusplus/IPv6Layer.h
Normal file
@@ -0,0 +1,279 @@
|
||||
#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 */
|
||||
754
pcappp/include/pcapplusplus/IcmpLayer.h
Normal file
754
pcappp/include/pcapplusplus/IcmpLayer.h
Normal file
@@ -0,0 +1,754 @@
|
||||
#ifndef PACKETPP_ICMP_LAYER
|
||||
#define PACKETPP_ICMP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "IPv4Layer.h"
|
||||
#ifdef _MSC_VER
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct icmphdr
|
||||
* Represents ICMP basic protocol header (common for all ICMP message types)
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmphdr
|
||||
{
|
||||
/** message type */
|
||||
uint8_t type;
|
||||
/** message code */
|
||||
uint8_t code;
|
||||
/** message checksum */
|
||||
uint16_t checksum;
|
||||
} icmphdr;
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* An enum of all supported ICMP message types
|
||||
*/
|
||||
enum IcmpMessageType
|
||||
{
|
||||
/** ICMP echo (ping) reply message */
|
||||
ICMP_ECHO_REPLY = 0,
|
||||
/** ICMP destination unreachable message */
|
||||
ICMP_DEST_UNREACHABLE = 3,
|
||||
/** ICMP source quench message */
|
||||
ICMP_SOURCE_QUENCH = 4,
|
||||
/** ICMP redirect message */
|
||||
ICMP_REDIRECT = 5,
|
||||
/** ICMP echo (ping) request message */
|
||||
ICMP_ECHO_REQUEST = 8,
|
||||
/** ICMP router advertisement message */
|
||||
ICMP_ROUTER_ADV = 9,
|
||||
/** ICMP router soliciatation message */
|
||||
ICMP_ROUTER_SOL = 10,
|
||||
/** ICMP time-to-live excceded message */
|
||||
ICMP_TIME_EXCEEDED = 11,
|
||||
/** ICMP parameter problem message */
|
||||
ICMP_PARAM_PROBLEM = 12,
|
||||
/** ICMP timestamp request message */
|
||||
ICMP_TIMESTAMP_REQUEST = 13,
|
||||
/** ICMP timestamp reply message */
|
||||
ICMP_TIMESTAMP_REPLY = 14,
|
||||
/** ICMP information request message */
|
||||
ICMP_INFO_REQUEST = 15,
|
||||
/** ICMP information reply message */
|
||||
ICMP_INFO_REPLY = 16,
|
||||
/** ICMP address mask request message */
|
||||
ICMP_ADDRESS_MASK_REQUEST = 17,
|
||||
/** ICMP address mask reply message */
|
||||
ICMP_ADDRESS_MASK_REPLY = 18,
|
||||
/** ICMP message type unsupported by PcapPlusPlus */
|
||||
ICMP_UNSUPPORTED = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* An enum for all possible codes for a destination unreachable message type
|
||||
* Documentation is taken from Wikipedia: https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol
|
||||
*/
|
||||
enum IcmpDestUnreachableCodes
|
||||
{
|
||||
/** Network unreachable error */
|
||||
IcmpNetworkUnreachable = 0,
|
||||
/** Host unreachable error */
|
||||
IcmpHostUnreachable = 1,
|
||||
/** Protocol unreachable error (the designated transport protocol is not supported) */
|
||||
IcmpProtocolUnreachable = 2,
|
||||
/** Port unreachable error (the designated protocol is unable to inform the host of the incoming message) */
|
||||
IcmpPortUnreachable = 3,
|
||||
/** The datagram is too big. Packet fragmentation is required but the 'don't fragment' (DF) flag is on */
|
||||
IcmpDatagramTooBig = 4,
|
||||
/** Source route failed error */
|
||||
IcmpSourceRouteFailed = 5,
|
||||
/** Destination network unknown error */
|
||||
IcmpDestinationNetworkUnknown = 6,
|
||||
/** Destination host unknown error */
|
||||
IcmpDestinationHostUnknown = 7,
|
||||
/** Source host isolated error */
|
||||
IcmpSourceHostIsolated = 8,
|
||||
/** The destination network is administratively prohibited */
|
||||
IcmpDestinationNetworkProhibited = 9,
|
||||
/** The destination host is administratively prohibited */
|
||||
IcmpDestinationHostProhibited = 10,
|
||||
/** The network is unreachable for Type Of Service */
|
||||
IcmpNetworkUnreachableForTypeOfService = 11,
|
||||
/** The host is unreachable for Type Of Service */
|
||||
IcmpHostUnreachableForTypeOfService = 12,
|
||||
/** Communication administratively prohibited (administrative filtering prevents
|
||||
* packet from being forwarded)
|
||||
*/
|
||||
IcmpCommunicationProhibited = 13,
|
||||
/** Host precedence violation (indicates the requested precedence is not permitted for
|
||||
* the combination of host or network and port)
|
||||
*/
|
||||
IcmpHostPrecedenceViolation = 14,
|
||||
/** Precedence cutoff in effect (precedence of datagram is below the level set by
|
||||
* the network administrators)
|
||||
*/
|
||||
IcmpPrecedenceCutoff = 15
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_echo_hdr
|
||||
* ICMP echo (ping) request/reply message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_echo_hdr : icmphdr
|
||||
{
|
||||
/** the echo (ping) request identifier */
|
||||
uint16_t id;
|
||||
/** the echo (ping) request sequence number */
|
||||
uint16_t sequence;
|
||||
/** a timestamp of when the message was sent */
|
||||
uint64_t timestamp;
|
||||
} icmp_echo_hdr;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_echo_request
|
||||
* ICMP echo (ping) request/reply message structure
|
||||
*/
|
||||
typedef struct icmp_echo_request
|
||||
{
|
||||
/** a pointer to the header data */
|
||||
icmp_echo_hdr* header;
|
||||
/** most echo requests/replies contain some payload data. This is the data length */
|
||||
size_t dataLength;
|
||||
/** most echo requests/replies contain some payload data. This is a pointer to this data */
|
||||
uint8_t* data;
|
||||
} icmp_echo_request;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef icmp_echo_reply
|
||||
* ICMP echo (ping) reply message structure, same as icmp_echo_request
|
||||
*/
|
||||
typedef icmp_echo_request icmp_echo_reply;
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_timestamp_request
|
||||
* ICMP timestamp request message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_timestamp_request : icmphdr
|
||||
{
|
||||
/** the timestamp request identifier */
|
||||
uint16_t id;
|
||||
/** the timestamp request sequence number */
|
||||
uint16_t sequence;
|
||||
/** the time (in milliseconds since midnight) the sender last touched the packet */
|
||||
uint32_t originateTimestamp;
|
||||
/** relevant for timestamp reply only - the time the echoer first touched it on receipt */
|
||||
uint32_t receiveTimestamp;
|
||||
/** relevant for timestamp reply only - the time the echoer last touched the message on sending it */
|
||||
uint32_t transmitTimestamp;
|
||||
} icmp_timestamp_request;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @typedef icmp_timestamp_reply
|
||||
* ICMP timestamp reply message structure, same as icmp_timestamp_request
|
||||
*/
|
||||
typedef icmp_timestamp_request icmp_timestamp_reply;
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_destination_unreachable
|
||||
* ICMP destination unreachable message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_destination_unreachable : icmphdr
|
||||
{
|
||||
/** unused 2 bytes */
|
||||
uint16_t unused;
|
||||
/** contains the MTU of the next-hop network if a code 4 error occurs */
|
||||
uint16_t nextHopMTU;
|
||||
} icmp_destination_unreachable;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_time_exceeded
|
||||
* ICMP time-to-live exceeded message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_time_exceeded : icmphdr
|
||||
{
|
||||
/** unused 4 bytes */
|
||||
uint32_t unused;
|
||||
} icmp_time_exceeded;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @typedef icmp_source_quench
|
||||
* ICMP source quence message structure, same as icmp_time_exceeded
|
||||
*/
|
||||
typedef icmp_time_exceeded icmp_source_quench;
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_param_problem
|
||||
* ICMP parameter problem message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_param_problem : icmphdr
|
||||
{
|
||||
/** in the case of an invalid IP header (Code 0), this field indicates the byte offset of the error in the header */
|
||||
uint8_t pointer;
|
||||
/** unused 1 byte */
|
||||
uint8_t unused1;
|
||||
/** unused 2 bytes */
|
||||
uint16_t unused2;
|
||||
} icmp_param_problem;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @typedef icmp_router_solicitation
|
||||
* ICMP router solicitation message structure, same as icmphdr
|
||||
*/
|
||||
typedef icmphdr icmp_router_solicitation;
|
||||
|
||||
/**
|
||||
* @struct icmp_redirect
|
||||
* ICMP redirect message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_redirect : icmphdr
|
||||
{
|
||||
/** an IPv4 address of the gateway to which the redirection should be sent */
|
||||
uint32_t gatewayAddress;
|
||||
} icmp_redirect;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_router_address_structure
|
||||
* Router address structure, relevant for ICMP router advertisement message type (icmp_router_advertisement)
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct icmp_router_address_structure
|
||||
{
|
||||
/** the IPv4 address of the advertised router */
|
||||
uint32_t routerAddress;
|
||||
/** The preferability of the router address as a default router address, relative to other router addresses
|
||||
* on the same subnet. This is a twos-complement value where higher values indicate that the route is
|
||||
* more preferable */
|
||||
uint32_t preferenceLevel;
|
||||
|
||||
/**
|
||||
* Set router address structure from a given IPv4 address and preference level
|
||||
* @param[in] addr IPv4 address to set
|
||||
* @param[in] preference Preference level to set
|
||||
*/
|
||||
void setRouterAddress(IPv4Address addr, uint32_t preference);
|
||||
|
||||
/**
|
||||
* @return The IPv4 address extracted from icmp_router_address_structure#routerAddress field
|
||||
*/
|
||||
IPv4Address getAddress() const { return routerAddress; }
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_router_advertisement_hdr
|
||||
* ICMP router advertisement message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_router_advertisement_hdr : icmphdr
|
||||
{
|
||||
/** the number of router advertisements in this message. Each advertisement contains one router address/preference level pair */
|
||||
uint8_t advertisementCount;
|
||||
/** the number of 32-bit words of information for each router address entry in the list. The value is normally set to 2
|
||||
* (router address + preference level) */
|
||||
uint8_t addressEntrySize;
|
||||
/** the maximum number of seconds that the router addresses in this list may be considered valid */
|
||||
uint16_t lifetime;
|
||||
} icmp_router_advertisement_hdr;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_router_advertisement
|
||||
* ICMP router advertisement message structure
|
||||
*/
|
||||
struct icmp_router_advertisement
|
||||
{
|
||||
/** a pointer to the header data on the packet */
|
||||
icmp_router_advertisement_hdr* header;
|
||||
|
||||
/**
|
||||
* Extract router advertisement at a given index
|
||||
* @param[in] index The index of the router advertisement
|
||||
* @return A pointer to the router advertisement on the packet or null if index is out of range (less than zero or
|
||||
* greater than the number of router advertisement records on this message, determined by advertisementCount field)
|
||||
*/
|
||||
icmp_router_address_structure* getRouterAddress(int index) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_address_mask_request
|
||||
* ICMP address mask request message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_address_mask_request : icmphdr
|
||||
{
|
||||
/** the address mask request identifier */
|
||||
uint16_t id;
|
||||
/** the address mask request sequence */
|
||||
uint16_t sequence;
|
||||
/** the subnet mask of the requesting host */
|
||||
uint32_t addressMask;
|
||||
} icmp_address_mask_request;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @typedef icmp_address_mask_reply
|
||||
* ICMP address mask reply message structure, same as icmp_address_mask_request
|
||||
*/
|
||||
typedef icmp_address_mask_request icmp_address_mask_reply;
|
||||
|
||||
|
||||
/**
|
||||
* @struct icmp_info_request
|
||||
* ICMP information request message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct icmp_info_request : icmphdr
|
||||
{
|
||||
/** the information request identifier */
|
||||
uint16_t id;
|
||||
/** the information request sequence */
|
||||
uint16_t sequence;
|
||||
} icmp_info_request;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @typedef icmp_info_reply
|
||||
* ICMP information reply message structure, same as icmp_info_request
|
||||
*/
|
||||
typedef icmp_info_request icmp_info_reply;
|
||||
|
||||
|
||||
/**
|
||||
* @class IcmpLayer
|
||||
* Represents an ICMP protocol layer (for IPv4 only)
|
||||
*/
|
||||
class IcmpLayer : public Layer
|
||||
{
|
||||
private:
|
||||
icmp_echo_request m_EchoData;
|
||||
mutable icmp_router_advertisement m_RouterAdvData;
|
||||
|
||||
bool cleanIcmpLayer();
|
||||
|
||||
bool setEchoData(IcmpMessageType echoType, uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen);
|
||||
|
||||
bool setIpAndL4Layers(IPv4Layer* ipLayer, Layer* l4Layer);
|
||||
|
||||
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 arphdr)
|
||||
* @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
|
||||
*/
|
||||
IcmpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ICMP; }
|
||||
|
||||
/**
|
||||
* An empty constructor that creates a new layer with an empty ICMP header without setting the ICMP type or ICMP data.
|
||||
* Call the set*Data() methods to set ICMP type and data
|
||||
*/
|
||||
IcmpLayer();
|
||||
|
||||
virtual ~IcmpLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the basic ICMP header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref icmphdr
|
||||
*/
|
||||
icmphdr* getIcmpHeader() const { return (icmphdr*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The ICMP message type
|
||||
*/
|
||||
IcmpMessageType getMessageType() const;
|
||||
|
||||
/**
|
||||
* @param[in] type Type to check
|
||||
* @return True if the layer if of the given type, false otherwise
|
||||
*/
|
||||
bool isMessageOfType(IcmpMessageType type) const { return getMessageType() == type; }
|
||||
|
||||
/**
|
||||
* @return ICMP echo (ping) request data. If the layer isn't of type ICMP echo request NULL is returned
|
||||
*/
|
||||
icmp_echo_request* getEchoRequestData();
|
||||
|
||||
/**
|
||||
* Set echo (ping) request message data
|
||||
* @param[in] id Echo (ping) request identifier
|
||||
* @param[in] sequence Echo (ping) request sequence
|
||||
* @param[in] timestamp Echo (ping) request timestamp
|
||||
* @param[in] data A pointer to echo (ping) request payload to set
|
||||
* @param[in] dataLen The length of the echo (ping) request payload
|
||||
* @return A pointer to the echo (ping) request data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_echo_request* setEchoRequestData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* @return ICMP echo reply data. If the layer isn't of type ICMP echo reply NULL is returned
|
||||
*/
|
||||
icmp_echo_reply* getEchoReplyData();
|
||||
|
||||
/**
|
||||
* Set echo (ping) reply message data
|
||||
* @param[in] id Echo (ping) reply identifier
|
||||
* @param[in] sequence Echo (ping) reply sequence
|
||||
* @param[in] timestamp Echo (ping) reply timestamp
|
||||
* @param[in] data A pointer to echo (ping) reply payload to set
|
||||
* @param[in] dataLen The length of the echo (ping) reply payload
|
||||
* @return A pointer to the echo (ping) reply data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_echo_reply* setEchoReplyData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* @return ICMP timestamp request data. If the layer isn't of type ICMP timestamp request NULL is returned
|
||||
*/
|
||||
icmp_timestamp_request* getTimestampRequestData();
|
||||
|
||||
/**
|
||||
* Set timestamp request message data
|
||||
* @param[in] id Timestamp request identifier
|
||||
* @param[in] sequence Timestamp request sequence
|
||||
* @param[in] originateTimestamp Time (in milliseconds since midnight) the sender last touched the packet
|
||||
* @return A pointer to the timestamp request data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_timestamp_request* setTimestampRequestData(uint16_t id, uint16_t sequence, timeval originateTimestamp);
|
||||
|
||||
/**
|
||||
* @return ICMP timestamp reply data. If the layer isn't of type ICMP timestamp reply NULL is returned
|
||||
*/
|
||||
icmp_timestamp_reply* getTimestampReplyData();
|
||||
|
||||
/**
|
||||
* Set timestamp reply message data
|
||||
* @param[in] id Timestamp reply identifier
|
||||
* @param[in] sequence Timestamp reply sequence
|
||||
* @param[in] originateTimestamp Time (in milliseconds since midnight) the sender last touched the packet
|
||||
* @param[in] receiveTimestamp The time the echoer first touched it on receipt
|
||||
* @param[in] transmitTimestamp The time the echoer last touched the message on sending it
|
||||
* @return A pointer to the timestamp reply data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_timestamp_reply* setTimestampReplyData(uint16_t id, uint16_t sequence,
|
||||
timeval originateTimestamp, timeval receiveTimestamp, timeval transmitTimestamp);
|
||||
|
||||
/**
|
||||
* @return ICMP destination unreachable data. If the layer isn't of type ICMP destination unreachable NULL is returned.
|
||||
* The IP and L4 (ICMP/TCP/UDP) headers of the destination unreachable data are parsed as separate layers and can be
|
||||
* retrieved via this->getNextLayer()
|
||||
*/
|
||||
icmp_destination_unreachable* getDestUnreachableData();
|
||||
|
||||
/**
|
||||
* Set destination unreachable message data. This method only works if IcmpLayer is already part of a packet (not
|
||||
* a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers
|
||||
* and need a packet to be added to
|
||||
* @param[in] code Destination unreachable code
|
||||
* @param[in] nextHopMTU The MTU of the next-hop network if a code 4 error occurs
|
||||
* @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet
|
||||
* @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet
|
||||
* @return A pointer to the destination unreachable data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_destination_unreachable* setDestUnreachableData(IcmpDestUnreachableCodes code, uint16_t nextHopMTU, IPv4Layer* ipHeader, Layer* l4Header);
|
||||
|
||||
/**
|
||||
* @return ICMP source quench data. If the layer isn't of type ICMP source quench NULL is returned.
|
||||
* The IP and L4 (ICMP/TCP/UDP) headers of the source quench data are parsed as separate layers and can be
|
||||
* retrieved via this->getNextLayer()
|
||||
*/
|
||||
icmp_source_quench* getSourceQuenchdata();
|
||||
|
||||
/**
|
||||
* Set source quench message data. This method only works if IcmpLayer is already part of a packet (not
|
||||
* a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers
|
||||
* and need a packet to be added to
|
||||
* @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet
|
||||
* @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet
|
||||
* @return A pointer to the source quench data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_source_quench* setSourceQuenchdata(IPv4Layer* ipHeader, Layer* l4Header);
|
||||
|
||||
/**
|
||||
* @return ICMP redirect data. If the layer isn't of type ICMP redirect NULL is returned.
|
||||
* The IP and L4 (ICMP/TCP/UDP) headers of the redirect data are parsed as separate layers and can be
|
||||
* retrieved via this->getNextLayer()
|
||||
*/
|
||||
icmp_redirect* getRedirectData();
|
||||
|
||||
/**
|
||||
* Set redirect message data. This method only works if IcmpLayer is already part of a packet (not
|
||||
* a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers
|
||||
* and need a packet to be added to
|
||||
* @param[in] code The redirect message code. Only values between 0 and 3 are legal, the rest will cause the method to fail
|
||||
* @param[in] gatewayAddress An IPv4 address of the gateway to which the redirection should be sent
|
||||
* @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet
|
||||
* @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet
|
||||
* @return A pointer to the redirect data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_redirect* setRedirectData(uint8_t code, IPv4Address gatewayAddress, IPv4Layer* ipHeader, Layer* l4Header);
|
||||
|
||||
/**
|
||||
* @return ICMP router advertisement data. If the layer isn't of type ICMP router advertisement NULL is returned
|
||||
*/
|
||||
icmp_router_advertisement* getRouterAdvertisementData() const;
|
||||
|
||||
/**
|
||||
* Set router advertisement message data
|
||||
* @param[in] code The router advertisement message code. Only codes 0 or 16 are legal, the rest will fail the method
|
||||
* @param[in] lifetimeInSeconds The maximum number of seconds that the router addresses in this list may be considered valid
|
||||
* @param[in] routerAddresses A vector of router advertisements to set
|
||||
* @return A pointer to the router advertisement data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_router_advertisement* setRouterAdvertisementData(uint8_t code, uint16_t lifetimeInSeconds, const std::vector<icmp_router_address_structure>& routerAddresses);
|
||||
|
||||
/**
|
||||
* @return ICMP router solicitation data. If the layer isn't of type ICMP router solicitation NULL is returned
|
||||
*/
|
||||
icmp_router_solicitation* getRouterSolicitationData();
|
||||
|
||||
/**
|
||||
* Set router solicitation message data. This message accepts no parameters as there are no parameters to this
|
||||
* type of message (code is always zero)
|
||||
* @return A pointer to the router solicitation data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_router_solicitation* setRouterSolicitationData();
|
||||
|
||||
/**
|
||||
* @return ICMP time-to-live exceeded data. If the layer isn't of type ICMP time-to-live exceeded NULL is returned.
|
||||
* The IP and L4 (ICMP/TCP/UDP) headers of the time exceeded data are parsed as separate layers and can be
|
||||
* retrieved via this->getNextLayer()
|
||||
*/
|
||||
icmp_time_exceeded* getTimeExceededData();
|
||||
|
||||
/**
|
||||
* Set time-to-live exceeded message data. This method only works if IcmpLayer is already part of a packet (not
|
||||
* a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers
|
||||
* and need a packet to be added to
|
||||
* @param[in] code Time-to-live exceeded message code. Only codes 0 or 1 are legal, the rest will fail the method
|
||||
* @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet
|
||||
* @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet
|
||||
* @return A pointer to the time-to-live exceeded data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_time_exceeded* setTimeExceededData(uint8_t code, IPv4Layer* ipHeader, Layer* l4Header);
|
||||
|
||||
/**
|
||||
* @return ICMP parameter problem data. If the layer isn't of type ICMP parameter problem NULL is returned
|
||||
*/
|
||||
icmp_param_problem* getParamProblemData();
|
||||
|
||||
/**
|
||||
* Set parameter problem message data. This method only works if IcmpLayer is already part of a packet (not
|
||||
* a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers
|
||||
* and need a packet to be added to
|
||||
* @param[in] code Parameter problem message code. Only code between 0 and 2 are legal, the rest will fail the method
|
||||
* @param[in] errorOctetPointer In the case of an invalid IP header (Code 0), indicate the byte offset of the error in the header
|
||||
* @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet
|
||||
* @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet
|
||||
* @return A pointer to the parameter problem data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_param_problem* setParamProblemData(uint8_t code, uint8_t errorOctetPointer, IPv4Layer* ipHeader, Layer* l4Header);
|
||||
|
||||
/**
|
||||
* @return ICMP address mask request data. If the layer isn't of type ICMP address mask request NULL is returned
|
||||
*/
|
||||
icmp_address_mask_request* getAddressMaskRequestData();
|
||||
|
||||
/**
|
||||
* Set address mask request message data
|
||||
* @param[in] id Address mask request identifier
|
||||
* @param[in] sequence Address mask request sequence
|
||||
* @param[in] mask The subnet mask of the requesting host
|
||||
* @return A pointer to the address mask request data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_address_mask_request* setAddressMaskRequestData(uint16_t id, uint16_t sequence, IPv4Address mask);
|
||||
|
||||
/**
|
||||
* @return ICMP address mask reply data. If the layer isn't of type ICMP address mask reply NULL is returned
|
||||
*/
|
||||
icmp_address_mask_reply* getAddressMaskReplyData();
|
||||
|
||||
/**
|
||||
* Set address mask reply message data
|
||||
* @param[in] id Address mask reply identifier
|
||||
* @param[in] sequence Address mask reply sequence
|
||||
* @param[in] mask The subnet mask of the requesting host
|
||||
* @return A pointer to the address mask reply data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_address_mask_reply* setAddressMaskReplyData(uint16_t id, uint16_t sequence, IPv4Address mask);
|
||||
|
||||
/**
|
||||
* @return ICMP address information request data. If the layer isn't of type ICMP information request NULL is returned
|
||||
*/
|
||||
icmp_info_request* getInfoRequestData();
|
||||
|
||||
/**
|
||||
* Set information request message data
|
||||
* @param[in] id Information request identifier
|
||||
* @param[in] sequence Information request sequence
|
||||
* @return A pointer to the information request data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_info_request* setInfoRequestData(uint16_t id, uint16_t sequence);
|
||||
|
||||
/**
|
||||
* @return ICMP address information reply data. If the layer isn't of type ICMP information reply NULL is returned
|
||||
*/
|
||||
icmp_info_reply* getInfoReplyData();
|
||||
|
||||
/**
|
||||
* Set information reply message data
|
||||
* @param[in] id Information reply identifier
|
||||
* @param[in] sequence Information reply sequence
|
||||
* @return A pointer to the information reply data that have been set or NULL if something went wrong
|
||||
* (an appropriate error log is printed in such cases)
|
||||
*/
|
||||
icmp_info_reply* setInfoReplyData(uint16_t id, uint16_t sequence);
|
||||
|
||||
/**
|
||||
* The static method makes validation of input data
|
||||
* @param[in] data The pointer to the beginning of byte stream of ICMP packet
|
||||
* @param[in] dataLen The length of byte stream
|
||||
* @return True if the data is valid and can represent an ICMP packet
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* ICMP messages of types: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, ICMP_REDIRECT, ICMP_PARAM_PROBLEM
|
||||
* have data that contains IPv4 header and some L4 header (TCP/UDP/ICMP). This method parses these headers as separate
|
||||
* layers on top of the ICMP layer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return The ICMP header length. This length varies according to the ICMP message type. This length doesn't include
|
||||
* IPv4 and L4 headers in case ICMP message type are: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED,
|
||||
* ICMP_REDIRECT, ICMP_PARAM_PROBLEM
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
/**
|
||||
* Calculate ICMP checksum field
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
||||
};
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool IcmpLayer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
if (dataLen < sizeof(icmphdr))
|
||||
return false;
|
||||
|
||||
uint8_t type = data[0];
|
||||
|
||||
// ICMP_ECHO_REQUEST, ICMP_ECHO_REPLY, ICMP_ROUTER_SOL, ICMP_INFO_REQUEST, ICMP_INFO_REPLY
|
||||
if (type == 8 || type == 0 || type == 10 || type == 15 || type == 16)
|
||||
return true;
|
||||
|
||||
// ICMP_TIMESTAMP_REQUEST, ICMP_TIMESTAMP_REPLY
|
||||
if (type == 13 || type == 14)
|
||||
return dataLen >= sizeof(icmp_timestamp_request);
|
||||
|
||||
// ICMP_ADDRESS_MASK_REPLY, ICMP_ADDRESS_MASK_REQUEST
|
||||
if (type == 17 || type == 18)
|
||||
return dataLen >= sizeof(icmp_address_mask_request);
|
||||
|
||||
// ICMP_DEST_UNREACHABLE
|
||||
if (type == 3)
|
||||
return dataLen >= sizeof(icmp_destination_unreachable);
|
||||
|
||||
// ICMP_REDIRECT
|
||||
if (type == 5)
|
||||
return dataLen >= sizeof(icmp_redirect);
|
||||
|
||||
// ICMP_TIME_EXCEEDED, ICMP_SOURCE_QUENCH
|
||||
if (type == 4 || type == 11)
|
||||
return dataLen >= sizeof(icmp_time_exceeded);
|
||||
|
||||
// ICMP_PARAM_PROBLEM
|
||||
if (type == 12)
|
||||
return dataLen >= sizeof(icmp_param_problem);
|
||||
|
||||
// ICMP_ROUTER_ADV
|
||||
if (type == 9)
|
||||
return dataLen >= sizeof(icmp_router_advertisement_hdr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_ICMP_LAYER */
|
||||
514
pcappp/include/pcapplusplus/IgmpLayer.h
Normal file
514
pcappp/include/pcapplusplus/IgmpLayer.h
Normal file
@@ -0,0 +1,514 @@
|
||||
#ifndef PACKETPP_IGMP_LAYER
|
||||
#define PACKETPP_IGMP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "IpAddress.h"
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct igmp_header
|
||||
* IGMPv1 and IGMPv2 basic protocol header
|
||||
*/
|
||||
struct igmp_header
|
||||
{
|
||||
/** Indicates the message type. The enum for message type is pcpp::IgmpType */
|
||||
uint8_t type;
|
||||
/** Specifies the time limit for the corresponding report. The field has a resolution of 100 milliseconds */
|
||||
uint8_t maxResponseTime;
|
||||
/** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */
|
||||
uint16_t checksum;
|
||||
/** This is the multicast address being queried when sending a Group-Specific or Group-and-Source-Specific Query */
|
||||
uint32_t groupAddress;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct igmpv3_query_header
|
||||
* IGMPv3 membership query basic header
|
||||
*/
|
||||
struct igmpv3_query_header
|
||||
{
|
||||
/** IGMP message type. Should always have value of membership query (::IgmpType_MembershipQuery) */
|
||||
uint8_t type;
|
||||
/** This field specifies the maximum time (in 1/10 second) allowed before sending a responding report */
|
||||
uint8_t maxResponseTime;
|
||||
/** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */
|
||||
uint16_t checksum;
|
||||
/** This is the multicast address being queried when sending a Group-Specific or Group-and-Source-Specific Query */
|
||||
uint32_t groupAddress;
|
||||
/** Suppress Router-side Processing Flag + Querier's Robustness Variable */
|
||||
uint8_t s_qrv;
|
||||
/** Querier's Query Interval Code */
|
||||
uint8_t qqic;
|
||||
/** This field specifies the number of source addresses present in the Query */
|
||||
uint16_t numOfSources;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct igmpv3_report_header
|
||||
* IGMPv3 membership report basic header
|
||||
*/
|
||||
struct igmpv3_report_header
|
||||
{
|
||||
/** IGMP message type. Should always have value of IGMPv3 membership report (::IgmpType_MembershipReportV3) */
|
||||
uint8_t type;
|
||||
/** Unused byte */
|
||||
uint8_t reserved1;
|
||||
/** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */
|
||||
uint16_t checksum;
|
||||
/** Unused bytes */
|
||||
uint16_t reserved2;
|
||||
/** This field specifies the number of group records present in the Report */
|
||||
uint16_t numOfGroupRecords;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct igmpv3_group_record
|
||||
* A block of fields containing information pertaining to the sender's membership in a single multicast group on the interface
|
||||
* from which the Report is sent. Relevant only for IGMPv3 membership report messages
|
||||
*/
|
||||
struct igmpv3_group_record
|
||||
{
|
||||
/** Group record type */
|
||||
uint8_t recordType;
|
||||
/** Contains the length of the Auxiliary Data field in this Group Record. A value other than 0 isn't supported */
|
||||
uint8_t auxDataLen;
|
||||
/** Specifies how many source addresses are present in this Group Record */
|
||||
uint16_t numOfSources;
|
||||
/** Contains the IP multicast address to which this Group Record pertains */
|
||||
uint32_t multicastAddress;
|
||||
/** A vector of n IP unicast addresses, where n is the value in this record's Number of Sources field */
|
||||
uint8_t sourceAddresses[];
|
||||
|
||||
/**
|
||||
* @return The multicast address in igmpv3_group_record#multicastAddress as IPv4Address instance
|
||||
*/
|
||||
IPv4Address getMulticastAddress() const { return multicastAddress; }
|
||||
|
||||
/**
|
||||
* @return The number of source addresses in this group record
|
||||
*/
|
||||
uint16_t getSourceAddressCount() const;
|
||||
|
||||
/**
|
||||
* Get the source address at a certain index
|
||||
* @param[in] index The index of the source address in the group record
|
||||
* @return The source address in the requested index. If index is negative or higher than the number of source addresses in this
|
||||
* group record the value if IPv4Address#Zero is returned
|
||||
*/
|
||||
IPv4Address getSourceAddressAtIndex(int index) const;
|
||||
|
||||
/**
|
||||
* @return The total size in bytes of the group record
|
||||
*/
|
||||
size_t getRecordLen() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* IGMP message types
|
||||
*/
|
||||
enum IgmpType
|
||||
{
|
||||
/** Unknown message type */
|
||||
IgmpType_Unknown = 0,
|
||||
/** IGMP Membership Query */
|
||||
IgmpType_MembershipQuery = 0x11,
|
||||
/** IGMPv1 Membership Report */
|
||||
IgmpType_MembershipReportV1 = 0x12,
|
||||
/** DVMRP */
|
||||
IgmpType_DVMRP = 0x13,
|
||||
/** PIM version 1 */
|
||||
IgmpType_P1Mv1 = 0x14,
|
||||
/** Cisco Trace Messages */
|
||||
IgmpType_CiscoTrace = 0x15,
|
||||
/** IGMPv2 Membership Report */
|
||||
IgmpType_MembershipReportV2 = 0x16,
|
||||
/** IGMPv2 Leave Group */
|
||||
IgmpType_LeaveGroup = 0x17,
|
||||
/** Multicast Traceroute Response */
|
||||
IgmpType_MulticastTracerouteResponse = 0x1e,
|
||||
/** Multicast Traceroute */
|
||||
IgmpType_MulticastTraceroute = 0x1f,
|
||||
/** IGMPv3 Membership Report */
|
||||
IgmpType_MembershipReportV3 = 0x22,
|
||||
/** MRD, Multicast Router Advertisement */
|
||||
IgmpType_MulticastRouterAdvertisement = 0x30,
|
||||
/** MRD, Multicast Router Solicitation */
|
||||
IgmpType_MulticastRouterSolicitation = 0x31,
|
||||
/** MRD, Multicast Router Termination */
|
||||
IgmpType_MulticastRouterTermination = 0x32,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IgmpLayer
|
||||
* A base class for all IGMP (Internet Group Management Protocol) protocol classes. This is an abstract class and cannot be instantiated,
|
||||
* only its child classes can be instantiated. The inherited classes represent the different versions of the protocol:
|
||||
* IGMPv1, IGMPv2 and IGMPv3
|
||||
*/
|
||||
class IgmpLayer : public Layer
|
||||
{
|
||||
protected:
|
||||
|
||||
IgmpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType igmpVer) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = igmpVer; }
|
||||
|
||||
IgmpLayer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime, ProtocolType igmpVer);
|
||||
|
||||
uint16_t calculateChecksum();
|
||||
|
||||
size_t getHeaderSizeByVerAndType(ProtocolType igmpVer, IgmpType igmpType) const;
|
||||
public:
|
||||
|
||||
virtual ~IgmpLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the raw IGMPv1/IGMPv2 header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref igmp_header
|
||||
*/
|
||||
igmp_header* getIgmpHeader() const { return (igmp_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The IPv4 multicast address stored igmp_header#groupAddress
|
||||
*/
|
||||
IPv4Address getGroupAddress() const { return getIgmpHeader()->groupAddress; }
|
||||
|
||||
/**
|
||||
* Set the IPv4 multicast address
|
||||
* @param[in] groupAddr The IPv4 address to set
|
||||
*/
|
||||
void setGroupAddress(const IPv4Address& groupAddr);
|
||||
|
||||
/**
|
||||
* @return IGMP type set in igmp_header#type as ::IgmpType enum. Notice that if igmp_header#type contains a value
|
||||
* that doesn't appear in the ::IgmpType enum, ::IgmpType_Unknown will be returned
|
||||
*/
|
||||
IgmpType getType() const;
|
||||
|
||||
/**
|
||||
* Set IGMP type (will be written to igmp_header#type field)
|
||||
* @param[in] type The type to set
|
||||
*/
|
||||
void setType(IgmpType type);
|
||||
|
||||
/**
|
||||
* A static method that gets raw IGMP data (byte stream) and returns the IGMP version of this IGMP message
|
||||
* @param[in] data The IGMP raw data (byte stream)
|
||||
* @param[in] dataLen Raw data length
|
||||
* @param[out] isQuery Return true if IGMP message type is ::IgmpType_MembershipQuery and false otherwise
|
||||
* @return One of the values ::IGMPv1, ::IGMPv2, ::IGMPv3 according to detected IGMP version or ::UnknownProtocol if couldn't detect
|
||||
* IGMP version
|
||||
*/
|
||||
static ProtocolType getIGMPVerFromData(uint8_t* data, size_t dataLen, bool& isQuery);
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (IGMP layer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return Size of IGMP header = 8B
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(igmp_header); }
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IgmpV1Layer
|
||||
* Represents IGMPv1 (Internet Group Management Protocol ver 1) layer. This class represents all the different messages of IGMPv1
|
||||
*/
|
||||
class IgmpV1Layer : public IgmpLayer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
IgmpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: IgmpLayer(data, dataLen, prevLayer, packet, IGMPv1) {}
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new IGMPv1 header
|
||||
* @param[in] type The message type to set
|
||||
* @param[in] groupAddr The multicast address to set. This is an optional parameter and has a default value of IPv4Address#Zero
|
||||
* if not provided
|
||||
*/
|
||||
IgmpV1Layer(IgmpType type, const IPv4Address& groupAddr = IPv4Address())
|
||||
: IgmpLayer(type, groupAddr, 0, IGMPv1) {}
|
||||
|
||||
/**
|
||||
* A destructor for this layer (does nothing)
|
||||
*/
|
||||
~IgmpV1Layer() {}
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Calculate the IGMP checksum and set igmp_header#maxResponseTime to 0 (this field is unused in IGMPv1)
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IgmpV2Layer
|
||||
* Represents IGMPv2 (Internet Group Management Protocol ver 2) layer. This class represents all the different messages of IGMPv2
|
||||
*/
|
||||
class IgmpV2Layer : public IgmpLayer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
IgmpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: IgmpLayer(data, dataLen, prevLayer, packet, IGMPv2) {}
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new IGMPv2 header
|
||||
* @param[in] type The message type to set
|
||||
* @param[in] groupAddr The multicast address to set. This is an optional parameter and has a default value of unspecified/zero IPv4 address
|
||||
* @param[in] maxResponseTime The max response time to set. This is an optional parameter and has a default value of 0 if not provided
|
||||
*/
|
||||
IgmpV2Layer(IgmpType type, const IPv4Address& groupAddr = IPv4Address(), uint8_t maxResponseTime = 0)
|
||||
: IgmpLayer(type, groupAddr, maxResponseTime, IGMPv2) {}
|
||||
|
||||
/**
|
||||
* A destructor for this layer (does nothing)
|
||||
*/
|
||||
~IgmpV2Layer() {}
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Calculate the IGMP checksum
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IgmpV3QueryLayer
|
||||
* Represents an IGMPv3 (Internet Group Management Protocol ver 3) membership query message
|
||||
*/
|
||||
class IgmpV3QueryLayer : public IgmpLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
IgmpV3QueryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new IGMPv3 membership query
|
||||
* @param[in] multicastAddr The multicast address to set. This is an optional parameter and has a default value of unspecified/zero IPv4 address
|
||||
* if not provided
|
||||
* @param[in] maxResponseTime The max response time to set. This is an optional parameter and has a default value of 0 if not provided
|
||||
* @param[in] s_qrv A 1-byte value representing the value in Suppress Router-side Processing Flag + Querier's Robustness Variable
|
||||
* (igmpv3_query_header#s_qrv field). This is an optional parameter and has a default value of 0 if not provided
|
||||
*/
|
||||
IgmpV3QueryLayer(const IPv4Address& multicastAddr = IPv4Address(), uint8_t maxResponseTime = 0, uint8_t s_qrv = 0);
|
||||
|
||||
/**
|
||||
* Get a pointer to the raw IGMPv3 membership query header. Notice this points directly to the data, so every change will change the
|
||||
* actual packet data
|
||||
* @return A pointer to the @ref igmpv3_query_header
|
||||
*/
|
||||
igmpv3_query_header* getIgmpV3QueryHeader() const { return (igmpv3_query_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The number of source addresses in this message (as extracted from the igmpv3_query_header#numOfSources field)
|
||||
*/
|
||||
uint16_t getSourceAddressCount() const;
|
||||
|
||||
/**
|
||||
* Get the IPV4 source address in a certain index
|
||||
* @param[in] index The requested index of the source address
|
||||
* @return The IPv4 source address, or IPv4Address#Zero if index is out of bounds (of the message or of the layer)
|
||||
*/
|
||||
IPv4Address getSourceAddressAtIndex(int index) const;
|
||||
|
||||
/**
|
||||
* Add a new source address at the end of the source address list. The igmpv3_query_header#numOfSources field will be incremented accordingly
|
||||
* @param[in] addr The IPv4 source address to add
|
||||
* @return True if source address was added successfully or false otherwise. If false is returned an appropriate error message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool addSourceAddress(const IPv4Address& addr);
|
||||
|
||||
/**
|
||||
* Add a new source address at a certain index of the source address list. The igmpv3_query_header#numOfSources field will be incremented accordingly
|
||||
* @param[in] addr The IPv4 source address to add
|
||||
* @param[in] index The index to add the new source address at
|
||||
* @return True if source address was added successfully or false otherwise. If false is returned an appropriate error message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool addSourceAddressAtIndex(const IPv4Address& addr, int index);
|
||||
|
||||
/**
|
||||
* Remove a source address at a certain index. The igmpv3_query_header#numOfSources field will be decremented accordingly
|
||||
* @param[in] index The index of the source address to be removed
|
||||
* @return True if source address was removed successfully or false otherwise. If false is returned an appropriate error message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool removeSourceAddressAtIndex(int index);
|
||||
|
||||
/**
|
||||
* Remove all source addresses in the message. The igmpv3_query_header#numOfSources field will be set to 0
|
||||
* @return True if all source addresses were cleared successfully or false otherwise. If false is returned an appropriate error message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool removeAllSourceAddresses();
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Calculate the IGMP checksum
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
/**
|
||||
* @return The message size in bytes which include the size of the basic header + the size of the source address list
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IgmpV3ReportLayer
|
||||
* Represents an IGMPv3 (Internet Group Management Protocol ver 3) membership report message
|
||||
*/
|
||||
class IgmpV3ReportLayer : public IgmpLayer
|
||||
{
|
||||
private:
|
||||
igmpv3_group_record* addGroupRecordAt(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector<IPv4Address>& sourceAddresses, int offset);
|
||||
|
||||
public:
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
IgmpV3ReportLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3) {}
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new IGMPv3 membership report with 0 group addresses
|
||||
*/
|
||||
IgmpV3ReportLayer() : IgmpLayer(IgmpType_MembershipReportV3, IPv4Address(), 0, IGMPv3) {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the raw IGMPv3 membership report header. Notice this points directly to the data, so every change will change the
|
||||
* actual packet data
|
||||
* @return A pointer to the @ref igmpv3_report_header
|
||||
*/
|
||||
igmpv3_report_header* getReportHeader() const { return (igmpv3_report_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The number of group records in this message (as extracted from the igmpv3_report_header#numOfGroupRecords field)
|
||||
*/
|
||||
uint16_t getGroupRecordCount() const;
|
||||
|
||||
/**
|
||||
* @return A pointer to the first group record or NULL if no group records exist. Notice the return value is a pointer to the real data,
|
||||
* so changes in the return value will affect the packet data
|
||||
*/
|
||||
igmpv3_group_record* getFirstGroupRecord() const;
|
||||
|
||||
/**
|
||||
* Get the group record that comes next to a given group record. If "groupRecord" is NULL then NULL will be returned.
|
||||
* If "groupRecord" is the last group record or if it is out of layer bounds NULL will be returned also. Notice the return value is a
|
||||
* pointer to the real data casted to igmpv3_group_record type (as opposed to a copy of the option data). So changes in the return
|
||||
* value will affect the packet data
|
||||
* @param[in] groupRecord The group record to start searching from
|
||||
* @return The next group record or NULL if "groupRecord" is NULL, last or out of layer bounds
|
||||
*/
|
||||
igmpv3_group_record* getNextGroupRecord(igmpv3_group_record* groupRecord) const;
|
||||
|
||||
/**
|
||||
* Add a new group record at a the end of the group record list. The igmpv3_report_header#numOfGroupRecords field will be
|
||||
* incremented accordingly
|
||||
* @param[in] recordType The type of the new group record
|
||||
* @param[in] multicastAddress The multicast address of the new group record
|
||||
* @param[in] sourceAddresses A vector containing all the source addresses of the new group record
|
||||
* @return The method constructs a new group record, adds it to the end of the group record list of IGMPv3 report message and
|
||||
* returns a pointer to the new message. If something went wrong in creating or adding the new group record a NULL value is returned
|
||||
* and an appropriate error message is printed to log
|
||||
*/
|
||||
igmpv3_group_record* addGroupRecord(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector<IPv4Address>& sourceAddresses);
|
||||
|
||||
/**
|
||||
* Add a new group record at a certain index of the group record list. The igmpv3_report_header#numOfGroupRecords field will be
|
||||
* incremented accordingly
|
||||
* @param[in] recordType The type of the new group record
|
||||
* @param[in] multicastAddress The multicast address of the new group record
|
||||
* @param[in] sourceAddresses A vector containing all the source addresses of the new group record
|
||||
* @param[in] index The index to add the new group address at
|
||||
* @return The method constructs a new group record, adds it to the IGMPv3 report message and returns a pointer to the new message.
|
||||
* If something went wrong in creating or adding the new group record a NULL value is returned and an appropriate error message is
|
||||
* printed to log
|
||||
*/
|
||||
igmpv3_group_record* addGroupRecordAtIndex(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector<IPv4Address>& sourceAddresses, int index);
|
||||
|
||||
/**
|
||||
* Remove a group record at a certain index. The igmpv3_report_header#numOfGroupRecords field will be decremented accordingly
|
||||
* @param[in] index The index of the group record to be removed
|
||||
* @return True if group record was removed successfully or false otherwise. If false is returned an appropriate error message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool removeGroupRecordAtIndex(int index);
|
||||
|
||||
/**
|
||||
* Remove all group records in the message. The igmpv3_report_header#numOfGroupRecords field will be set to 0
|
||||
* @return True if all group records were cleared successfully or false otherwise. If false is returned an appropriate error message
|
||||
* will be printed to log
|
||||
*/
|
||||
bool removeAllGroupRecords();
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Calculate the IGMP checksum
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
/**
|
||||
* @return The message size in bytes which include the size of the basic header + the size of the group record list
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_IGMP_LAYER
|
||||
462
pcappp/include/pcapplusplus/IpAddress.h
Normal file
462
pcappp/include/pcapplusplus/IpAddress.h
Normal file
@@ -0,0 +1,462 @@
|
||||
#ifndef PCAPPP_IP_ADDRESSES
|
||||
#define PCAPPP_IP_ADDRESSES
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
|
||||
/// @file
|
||||
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
// The implementation of the classes is based on document N4771 "Working Draft, C++ Extensions for Networking"
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
|
||||
|
||||
/**
|
||||
* @class IPv4Address
|
||||
* Represents an IPv4 address (of type XXX.XXX.XXX.XXX)
|
||||
*/
|
||||
class IPv4Address
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A default constructor that creates an instance of the class with unspecified/zero address
|
||||
*/
|
||||
IPv4Address() { memset(m_Bytes, 0, sizeof(m_Bytes)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of 4-byte integer value.
|
||||
* @param[in] addrAsInt The address as 4-byte integer in network byte order
|
||||
*/
|
||||
IPv4Address(uint32_t addrAsInt) { memcpy(m_Bytes, &addrAsInt, sizeof(m_Bytes)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of 4-byte array.
|
||||
* @param[in] bytes The address as 4-byte array in network byte order
|
||||
*/
|
||||
IPv4Address(const uint8_t bytes[4]) { memcpy(m_Bytes, bytes, sizeof(m_Bytes)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of std::string value
|
||||
* If the string doesn't represent a valid IPv4 address, an instance will store an unspecified address
|
||||
* @param[in] addrAsString The std::string representation of the address
|
||||
*/
|
||||
IPv4Address(const std::string& addrAsString);
|
||||
|
||||
/**
|
||||
* Converts the IPv4 address into a 4B integer
|
||||
* @return a 4B integer in network byte order representing the IPv4 address
|
||||
*/
|
||||
inline uint32_t toInt() const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to 4-byte array representing the IPv4 address
|
||||
*/
|
||||
const uint8_t* toBytes() const { return m_Bytes; }
|
||||
|
||||
/**
|
||||
* Returns a std::string representation of the address
|
||||
* @return A string representation of the address
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Determine whether the address is a multicast address
|
||||
* @return True if an address is multicast
|
||||
*/
|
||||
bool isMulticast() const;
|
||||
|
||||
/**
|
||||
* Determine whether the address is valid (it's not an unspecified/zero)
|
||||
* @return True if an address is not unspecified/zero
|
||||
*/
|
||||
bool isValid() const { return toInt() != 0; }
|
||||
|
||||
/**
|
||||
* Overload of the equal-to operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the addresses are equal, false otherwise
|
||||
*/
|
||||
bool operator==(const IPv4Address& rhs) const { return toInt() == rhs.toInt(); }
|
||||
|
||||
/**
|
||||
* Overload of the less-than operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the address value is lower than the other address value, false otherwise
|
||||
*/
|
||||
bool operator<(const IPv4Address& rhs) const
|
||||
{
|
||||
uint32_t intVal = toInt();
|
||||
std::reverse((uint8_t*)(&intVal), (uint8_t*)(&intVal) + sizeof(intVal));
|
||||
|
||||
uint32_t rhsIntVal = rhs.toInt();
|
||||
std::reverse((uint8_t*)(&rhsIntVal), (uint8_t*)(&rhsIntVal) + sizeof(rhsIntVal));
|
||||
|
||||
return intVal < rhsIntVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of the not-equal-to operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the addresses are not equal, false otherwise
|
||||
*/
|
||||
bool operator!=(const IPv4Address& rhs) const { return !(*this == rhs); }
|
||||
|
||||
/**
|
||||
* Checks whether the address matches a subnet.
|
||||
* For example: if subnet is 10.1.1.X, subnet mask is 255.255.255.0 and address is 10.1.1.9 then the method will return true
|
||||
* Another example: if subnet is 10.1.X.X, subnet mask is 255.0.0.0 and address is 11.1.1.9 then the method will return false
|
||||
* @param[in] subnet The subnet to be verified. Notice it's an IPv4Address type, so subnets with don't-cares (like 10.0.0.X) must have some number
|
||||
* (it'll be ignored if subnet mask is correct)
|
||||
* @param[in] subnetMask A string representing the subnet mask to compare the address with the subnet
|
||||
*/
|
||||
bool matchSubnet(const IPv4Address& subnet, const std::string& subnetMask) const;
|
||||
|
||||
/**
|
||||
* Checks whether the address matches a subnet.
|
||||
* For example: if subnet is 10.1.1.X, subnet mask is 255.255.255.0 and address is 10.1.1.9 then the method will return true
|
||||
* Another example: if subnet is 10.1.X.X, subnet mask is 255.0.0.0 and address is 11.1.1.9 then the method will return false
|
||||
* @param[in] subnet The subnet to be verified. Notice it's an IPv4Address type, so subnets with don't-cares (like 10.0.0.X) must have some number
|
||||
* (it'll be ignored if subnet mask is correct)
|
||||
* @param[in] subnetMask The subnet mask to compare the address with the subnet
|
||||
*/
|
||||
bool matchSubnet(const IPv4Address& subnet, const IPv4Address& subnetMask) const;
|
||||
|
||||
/**
|
||||
* A static value representing a zero value of IPv4 address, meaning address of value "0.0.0.0"
|
||||
* Notice this value can be omitted in the user code because the default constructor creates an instance with an unspecified/zero address.
|
||||
* In order to check whether the address is zero the method isValid can be used
|
||||
*/
|
||||
static const IPv4Address Zero;
|
||||
|
||||
/**
|
||||
* A static values representing the lower and upper bound of IPv4 multicast ranges. The bounds are inclusive.
|
||||
* MulticastRangeLowerBound is initialized to "224.0.0.0".
|
||||
* MulticastRangeUpperBound is initialized to "239.255.255.255".
|
||||
* In order to check whether the address is a multicast address the isMulticast method can be used.
|
||||
*/
|
||||
static const IPv4Address MulticastRangeLowerBound;
|
||||
static const IPv4Address MulticastRangeUpperBound;
|
||||
|
||||
private:
|
||||
uint8_t m_Bytes[4];
|
||||
}; // class IPv4Address
|
||||
|
||||
|
||||
// Implementation of inline methods
|
||||
|
||||
uint32_t IPv4Address::toInt() const
|
||||
{
|
||||
uint32_t addr;
|
||||
memcpy(&addr, m_Bytes, sizeof(m_Bytes));
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class IPv6Address
|
||||
* Represents an IPv6 address (of type xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx).
|
||||
*/
|
||||
class IPv6Address
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A default constructor that creates an instance of the class with unspecified/zero address
|
||||
*/
|
||||
IPv6Address() { memset(m_Bytes, 0, sizeof(m_Bytes)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of 16-byte array.
|
||||
* @param[in] bytes The address as 16-byte array in network byte order
|
||||
*/
|
||||
IPv6Address(const uint8_t bytes[16]) { memcpy(m_Bytes, bytes, sizeof(m_Bytes)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of std::string value
|
||||
* If the string doesn't represent a valid IPv6 address, an instance will store an unspecified address
|
||||
* @param[in] addrAsString The std::string representation of the address
|
||||
*/
|
||||
IPv6Address(const std::string& addrAsString);
|
||||
|
||||
/**
|
||||
* Returns a pointer to 16-byte array representing the IPv6 address
|
||||
*/
|
||||
const uint8_t* toBytes() const { return m_Bytes; }
|
||||
|
||||
/**
|
||||
* Returns a std::string representation of the address
|
||||
* @return A string representation of the address
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Determine whether the address is a multicast address
|
||||
* @return True if an address is multicast
|
||||
*/
|
||||
bool isMulticast() const;
|
||||
|
||||
/**
|
||||
* Determine whether the address is unspecified
|
||||
*/
|
||||
bool isValid() const { return *this != Zero; }
|
||||
|
||||
/**
|
||||
* Overload of the equal-to operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the addresses are equal, false otherwise
|
||||
*/
|
||||
bool operator==(const IPv6Address& rhs) const { return memcmp(toBytes(), rhs.toBytes(), sizeof(m_Bytes)) == 0; }
|
||||
|
||||
/**
|
||||
* Overload of the less-than operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the address value is lower than the other address value, false otherwise
|
||||
*/
|
||||
bool operator<(const IPv6Address& rhs) const { return memcmp(toBytes(), rhs.toBytes(), sizeof(m_Bytes)) < 0; }
|
||||
|
||||
/**
|
||||
* Overload of the not-equal-to operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the addresses are not equal, false otherwise
|
||||
*/
|
||||
bool operator!=(const IPv6Address &rhs) const { return !(*this == rhs); }
|
||||
|
||||
|
||||
/**
|
||||
* Allocates a byte array and copies address value into it. Array deallocation is user responsibility
|
||||
* @param[in] arr A pointer to where array will be allocated
|
||||
* @param[out] length Returns the length in bytes of the array that was allocated
|
||||
*/
|
||||
void copyTo(uint8_t** arr, size_t& length) const;
|
||||
|
||||
/**
|
||||
* Gets a pointer to an already allocated byte array and copies the address value to it.
|
||||
* This method assumes array allocated size is at least 16 (the size of an IPv6 address)
|
||||
* @param[in] arr A pointer to the array which address will be copied to
|
||||
*/
|
||||
void copyTo(uint8_t* arr) const { memcpy(arr, m_Bytes, sizeof(m_Bytes)); }
|
||||
|
||||
/**
|
||||
* Checks whether the address matches a subnet.
|
||||
* For example: if subnet is 2001:3CA1:010F:001A::, prefixLength is 64, and address is 2001:3CA1:010F:001A:121B:0000:0000:0010, then the method will return true
|
||||
* Another example: if subnet is 2001:3CA1:010F:001A::, prefixLength is 70 and address is 2001:3CA1:010F:001A:121B:0000:0000:0010 then the method will return false
|
||||
* @param[in] subnet The subnet to be verified
|
||||
* @param[in] prefixLength How many bits to use in the mask
|
||||
*/
|
||||
bool matchSubnet(const IPv6Address& subnet, uint8_t prefixLength) const;
|
||||
|
||||
/**
|
||||
* A static value representing a zero value of IPv6 address, meaning address of value "0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
|
||||
* Notice this value can be omitted in the user code because the default constructor creates an instance with an unspecified/zero address.
|
||||
* In order to check whether the address is zero the method isValid can be used
|
||||
*/
|
||||
static const IPv6Address Zero;
|
||||
|
||||
/**
|
||||
* A static value representing the lower bound of IPv6 multicast ranges. The bound is inclusive.
|
||||
* MulticastRangeLowerBound is initialized to "ff00:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0".
|
||||
* In order to check whether the address is a multicast address the isMulticast method can be used.
|
||||
*/
|
||||
static const IPv6Address MulticastRangeLowerBound;
|
||||
|
||||
private:
|
||||
uint8_t m_Bytes[16];
|
||||
}; // class IPv6Address
|
||||
|
||||
|
||||
///**
|
||||
// * @class IPAddress
|
||||
// * The class is a version-independent representation for an IP address
|
||||
// */
|
||||
class IPAddress
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* An enum representing the address type: IPv4 or IPv6
|
||||
*/
|
||||
enum AddressType
|
||||
{
|
||||
/**
|
||||
* IPv4 address type
|
||||
*/
|
||||
IPv4AddressType,
|
||||
/**
|
||||
* IPv6 address type
|
||||
*/
|
||||
IPv6AddressType
|
||||
};
|
||||
|
||||
/**
|
||||
* A default constructor that creates an instance of the class with unspecified IPv4 address
|
||||
*/
|
||||
IPAddress() : m_Type(IPv4AddressType) {}
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of IPv4Address.
|
||||
* @param[in] addr A const reference to instance of IPv4Address
|
||||
*/
|
||||
IPAddress(const IPv4Address& addr) : m_Type(IPv4AddressType), m_IPv4(addr) {}
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of IPv6Address.
|
||||
* @param[in] addr A const reference to instance of IPv6Address
|
||||
*/
|
||||
IPAddress(const IPv6Address& addr) : m_Type(IPv6AddressType), m_IPv6(addr) {}
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of std::string value
|
||||
* If the string doesn't represent a valid IPv4 or IPv6 address, an instance will store an unspecified address
|
||||
* @param[in] addrAsString The std::string representation of the address
|
||||
*/
|
||||
IPAddress(const std::string& addrAsString);
|
||||
|
||||
/**
|
||||
* Overload of an assignment operator.
|
||||
* @param[in] addr A const reference to instance of IPv4Address
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
inline IPAddress& operator=(const IPv4Address& addr);
|
||||
|
||||
/**
|
||||
* Overload of an assignment operator.
|
||||
* @param[in] addr A const reference to instance of IPv6Address
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
inline IPAddress& operator=(const IPv6Address& addr);
|
||||
|
||||
/**
|
||||
* Gets the address type: IPv4 or IPv6
|
||||
* @return The address type
|
||||
*/
|
||||
AddressType getType() const { return static_cast<AddressType>(m_Type); }
|
||||
|
||||
/**
|
||||
* Returns a std::string representation of the address
|
||||
* @return A string representation of the address
|
||||
*/
|
||||
std::string toString() const { return (getType() == IPv4AddressType) ? m_IPv4.toString() : m_IPv6.toString(); }
|
||||
|
||||
/**
|
||||
* @return Determine whether the address is unspecified
|
||||
*/
|
||||
bool isValid() const { return (getType() == IPv4AddressType) ? m_IPv4.isValid() : m_IPv6.isValid(); }
|
||||
|
||||
/**
|
||||
* @return Determine whether the object contains an IP version 4 address
|
||||
*/
|
||||
bool isIPv4() const { return getType() == IPv4AddressType; }
|
||||
|
||||
/**
|
||||
* @return Determine whether the object contains an IP version 6 address
|
||||
*/
|
||||
bool isIPv6() const { return getType() == IPv6AddressType; }
|
||||
|
||||
/**
|
||||
* Determine whether the address is a multicast address
|
||||
* @return True if an address is multicast
|
||||
*/
|
||||
bool isMulticast() const { return (getType() == IPv4AddressType) ? m_IPv4.isMulticast() : m_IPv6.isMulticast(); }
|
||||
|
||||
/**
|
||||
* Get a reference to IPv4 address instance
|
||||
* @return The const reference to IPv4Address instance
|
||||
*/
|
||||
const IPv4Address& getIPv4() const { return m_IPv4; }
|
||||
|
||||
/**
|
||||
* Get a reference to IPv6 address instance
|
||||
* @return The const reference to IPv6Address instance
|
||||
*/
|
||||
const IPv6Address& getIPv6() const { return m_IPv6; }
|
||||
|
||||
/**
|
||||
* Overload of the equal-to operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the addresses are equal, false otherwise
|
||||
*/
|
||||
inline bool operator==(const IPAddress& rhs) const;
|
||||
|
||||
/**
|
||||
* Overload of the less-than operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the address value is lower than the other address value, false otherwise
|
||||
*/
|
||||
inline bool operator<(const IPAddress& rhs) const;
|
||||
|
||||
/**
|
||||
* Overload of the not-equal-to operator
|
||||
* @param[in] rhs The object to compare with
|
||||
* @return True if the addresses are not equal, false otherwise
|
||||
*/
|
||||
bool operator!=(const IPAddress& rhs) const { return !(*this == rhs); }
|
||||
|
||||
private:
|
||||
uint8_t m_Type;
|
||||
IPv4Address m_IPv4;
|
||||
IPv6Address m_IPv6;
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool IPAddress::operator==(const IPAddress& rhs) const
|
||||
{
|
||||
if (isIPv4())
|
||||
return rhs.isIPv4() ? (m_IPv4 == rhs.m_IPv4) : false;
|
||||
|
||||
return rhs.isIPv6() ? m_IPv6 == rhs.m_IPv6 : false;
|
||||
}
|
||||
|
||||
bool IPAddress::operator<(const IPAddress& rhs) const
|
||||
{
|
||||
if(isIPv4())
|
||||
{
|
||||
// treat IPv4 as less than IPv6
|
||||
// If current obj is IPv4 and other is IPv6 return true
|
||||
return rhs.isIPv4() ? (m_IPv4 < rhs.m_IPv4) : true;
|
||||
}
|
||||
return rhs.isIPv6() ? m_IPv6 < rhs.m_IPv6 : false;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const IPv4Address& addr)
|
||||
{
|
||||
m_Type = IPv4AddressType;
|
||||
m_IPv4 = addr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const IPv6Address& addr)
|
||||
{
|
||||
m_Type = IPv6AddressType;
|
||||
m_IPv6 = addr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv4Address& ipv4Address)
|
||||
{
|
||||
os << ipv4Address.toString();
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv6Address& ipv6Address)
|
||||
{
|
||||
os << ipv6Address.toString();
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPAddress& ipAddress)
|
||||
{
|
||||
os << ipAddress.toString();
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif /* PCAPPP_IPADDRESS */
|
||||
91
pcappp/include/pcapplusplus/IpUtils.h
Normal file
91
pcappp/include/pcapplusplus/IpUtils.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef PCAPPP_IP_UTILS
|
||||
#define PCAPPP_IP_UTILS
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef __linux__
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
/// @file
|
||||
|
||||
// Both Visual C++ Compiler and MinGW-w64 define inet_ntop() and inet_pton()
|
||||
// Add compatibility functions for old MinGW (aka MinGW32)
|
||||
// We use "__MINGW64_VERSION_MAJOR" and not __MINGW64__ to detect MinGW-w64 compiler
|
||||
// because the second one is not defined for MinGW-w64 in 32bits mode
|
||||
#if defined(_WIN32) && !defined(_MSC_VER) && (!defined(__MINGW64_VERSION_MAJOR) || (__MINGW64_VERSION_MAJOR < 8))
|
||||
/**
|
||||
* Convert a network format address to presentation format.
|
||||
* @param[in] af Address family, can be either AF_INET (IPv4) or AF_INET6 (IPv6)
|
||||
* @param[in] src Network address structure, can be either in_addr (IPv4) or in6_addr (IPv6)
|
||||
* @param[out] dst Network address string representation
|
||||
* @param[in] size 'dst' Maximum size
|
||||
* @return pointer to presentation format address ('dst'), or NULL (see errno).
|
||||
*/
|
||||
const char* inet_ntop(int af, const void* src, char* dst, size_t size);
|
||||
|
||||
/**
|
||||
* Convert from presentation format (which usually means ASCII printable)
|
||||
* to network format (which is usually some kind of binary format).
|
||||
* @param[in] af Address family, can be either AF_INET (IPv4) or AF_INET6 (IPv6)
|
||||
* @param[in] src Network address string representation
|
||||
* @param[out] dst Network address structure result, can be either in_addr (IPv4) or in6_addr (IPv6)
|
||||
* @return
|
||||
* 1 if the address was valid for the specified address family;
|
||||
* 0 if the address wasn't valid ('dst' is untouched in this case);
|
||||
* -1 if some other error occurred ('dst' is untouched in this case, too)
|
||||
*/
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* Extract IPv4 address from sockaddr
|
||||
* @param[in] sa - input sockaddr
|
||||
* @return Address in in_addr format
|
||||
*/
|
||||
in_addr* sockaddr2in_addr(struct sockaddr *sa);
|
||||
|
||||
/**
|
||||
* Extract IPv6 address from sockaddr
|
||||
* @param[in] sa - input sockaddr
|
||||
* @return Address in in6_addr format
|
||||
*/
|
||||
in6_addr* sockaddr2in6_addr(struct sockaddr *sa);
|
||||
|
||||
/**
|
||||
* Converts a sockaddr format address to its string representation
|
||||
* @param[in] sa Address in sockaddr format
|
||||
* @param[out] resultString String representation of the address
|
||||
*/
|
||||
void sockaddr2string(struct sockaddr *sa, char* resultString);
|
||||
|
||||
/**
|
||||
* Convert a in_addr format address to 32bit representation
|
||||
* @param[in] inAddr Address in in_addr format
|
||||
* @return Address in 32bit format
|
||||
*/
|
||||
uint32_t in_addr2int(in_addr inAddr);
|
||||
} // namespace internal
|
||||
} // namespace pcpp
|
||||
#endif
|
||||
651
pcappp/include/pcapplusplus/KniDevice.h
Normal file
651
pcappp/include/pcapplusplus/KniDevice.h
Normal file
@@ -0,0 +1,651 @@
|
||||
#ifndef PCAPPP_KNI_DEVICE
|
||||
#define PCAPPP_KNI_DEVICE
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Device.h"
|
||||
#include "MacAddress.h"
|
||||
#include "MBufRawPacket.h"
|
||||
#include "LinuxNicInformationSocket.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief This file and KniDeviceList.h provide PcapPlusPlus C++ wrapper
|
||||
* for DPDK KNI (Kernel Network Interface) library (librte_kni).
|
||||
* The main propose of the rte_kni library is to provide a way to forward
|
||||
* packets received by DPDK application to Linux kernel (a.e. to processes that
|
||||
* have opened some kind of a net socket) for further processing and to obtain
|
||||
* packets from Linux kernel. The KNI device is the bridge that accomplish the
|
||||
* translation between DPDK packets (mbuf) and Linux kernel/socket packets
|
||||
* (skbuf). Currently KNI devices report speeds up to 10 GBit/s.<BR>
|
||||
* KNI device is a virtual network interface so it can be created and destroyed
|
||||
* programmatically at will. As a real network interface KNI deivice must
|
||||
* be managed appropriately like other interfaces. To start operate it MUST be
|
||||
* given an IP address for example by the means of <B>ip a</B> command and
|
||||
* MUST be put up for example by <B>ip l set [interface] up</B>.<BR>
|
||||
* Additionally KNI interfaces support 4 other settings (depends on DPDK
|
||||
* version used):
|
||||
* - change link state: <B>ip l set [interface] up/down</B>
|
||||
* - change MTU: <B>ip l set dev [interface] mtu [mtu_count]</B>
|
||||
* - change MAC address: <B>ip l set [interface] address [new_mac]</B>
|
||||
* - change promiscuous mode: <B>ip l set [interface] promisc on/off</B>
|
||||
*
|
||||
* Changes of each of this settings generates an event/request that must be
|
||||
* handled by an application that have created the KNI device in 3 second
|
||||
* period or it will be rejected and Linux kernel will not apply the change.
|
||||
* The way that this requests MUST be handled is defined by DPDK and so for
|
||||
* each type of request the application that creates the KNI device must provide
|
||||
* the callback function to call. This callbacks are set in time of KNI device
|
||||
* creation via KniIoctlCallbacks or KniOldIoctlCallbacks structures (the
|
||||
* structure used is dependent on DPDK version).<BR>
|
||||
* There is a way to enable <B>ethtool</B> on KNI devices that include
|
||||
* recompilation of DPDK and strict correspondence between KNI port id and DPDK
|
||||
* port id, but it is not currently supported by PcapPlusPlus.<BR>
|
||||
*
|
||||
* Known issues:
|
||||
* - KNI device may not be able to set/update it's link status up
|
||||
* (LINK_ERROR returned):
|
||||
* The problem is laying in DPDK in rte_kni_update_link function
|
||||
* (it is DPDK BUG if rte_kni_update_link is __rte_experimental).
|
||||
* It is recommended to load rte_kni.ko module with "carrier=on" DPDK
|
||||
* default is "carrier=off", provided setup-dpdk.sh by default loads with
|
||||
* "carrier=on" if Your DPDK version supports it. The good indication of
|
||||
* this issue are "DPDK KNI Failed to update links state for device"
|
||||
* messages when Pcap++Test application is being run.
|
||||
* - Packets may not be seen by applications that have open sockets on KNI
|
||||
* device:
|
||||
* Check your <B>iptables</B> settings and other packet filters - KNI device
|
||||
* is traditional network device so all caveats apply;
|
||||
* - I see a lot of unknown traffic - what is it?
|
||||
* This must be Linux kernel trying to communicate with other devices from
|
||||
* KNI device and it will do so as long as You give the KNI device any IP
|
||||
* address via ip command or by record in /etc/networking/interfaces;
|
||||
* - On old versions of DPDK only 4 KNI devices may be created:
|
||||
* Yep this is a limitation. You can change MAX_KNI_DEVICES constant in
|
||||
* KniDeviceList.cpp to unlock this limit;
|
||||
* - Any set* method never succeeds:
|
||||
* You may forgot that they generate KNI requests that Your application MUST
|
||||
* handle. Just use KniDevice#startRequestHandlerThread to handle all
|
||||
* requests automatically. Or user running the application don't have
|
||||
* suitable access rights (must have CAP_NET_ADMIN).
|
||||
*
|
||||
* Useful links:
|
||||
* - <a href="https://doc.dpdk.org/guides/prog_guide/kernel_nic_interface.html">KNI interface concept DPDK documentation</a>
|
||||
* - <a href="https://doc.dpdk.org/guides/nics/kni.html">KNI PMD</a>
|
||||
* - <a href="https://doc.dpdk.org/guides/sample_app_ug/kernel_nic_interface.html">KNI DPDK sample application</a>
|
||||
* - <a href="https://doc.dpdk.org/dts/test_plans/kni_test_plan.html">KNI DPDK test plan</a>
|
||||
*/
|
||||
|
||||
struct rte_kni;
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
class KniDevice;
|
||||
class KniDeviceList;
|
||||
|
||||
/**
|
||||
* Defines the signature callback used by capturing API on KNI device
|
||||
*/
|
||||
typedef bool (*OnKniPacketArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, KniDevice* device, void* userCookie);
|
||||
|
||||
/**
|
||||
* @class KniDevice
|
||||
* This class represents special kind of DPDK devices called KNI - Kernel Network Interface
|
||||
* that are used to exchange DPDK mbuf packets with Linux kernel network stack.
|
||||
* This devices have only one RX and one TX queue so MT receiving or MT sending is not
|
||||
* safe but simultaneous receiving and sending packets is MT safe.
|
||||
* The RX queue of KNI device is pointed from kernel to application and TX queue is
|
||||
* pointed in opposite direction - from application to kernel. So receive* methods will
|
||||
* obtain packets from kernel and send* methods will send them to kernel.<BR>
|
||||
* The lifecycle of the KNI device is as follows:
|
||||
* - KniDeviceConfiguration structure is created by user and filled with device settings;
|
||||
* - The KniDeviceList#getInstance method is called to initialize the KNI module and
|
||||
* obtain the KniDeviceList singleton;
|
||||
* - KniDeviceList#createDevice method of the singleton is called to allocate new KNI device;
|
||||
* - Device then must be opened by calling KniDevice#open;
|
||||
* - During lifetime the application must handle the requests from kernel either by calling
|
||||
* KniDevice#handleRequests to handle them synchronously or by starting separate thread
|
||||
* to do this by calling KniDevice#startRequestHandlerThread;
|
||||
* - During lifetime the packets may be send to/received from KNI device via
|
||||
* calls to synchronous API (send/receive methods) or asynchronously by
|
||||
* running capturing thread using KniDevice#startCapture;
|
||||
* - KNI device will be destroyed or implicitly on application exit. User must assure
|
||||
* that NO OTHER linux application is using KNI device when and after it is being
|
||||
* destroyed otherwise Linux kernel may crush dramatically.
|
||||
*/
|
||||
class KniDevice : public IDevice
|
||||
{
|
||||
friend class KniDeviceList;
|
||||
friend class MBufRawPacket;
|
||||
public:
|
||||
/**
|
||||
* Various link related constants for KNI device
|
||||
*/
|
||||
enum KniLinkState
|
||||
{
|
||||
/** Returned by KNI functions if DPDK version used don't support link setup capability */
|
||||
LINK_NOT_SUPPORTED = -2,
|
||||
/** Returned by KNI functions if link changing function meets an error */
|
||||
LINK_ERROR = -1,
|
||||
/** Used to put link status on KNI device DOWN */
|
||||
LINK_DOWN = 0,
|
||||
/** Used to put link status on KNI device UP */
|
||||
LINK_UP = 1
|
||||
};
|
||||
/**
|
||||
* Various information related constants for KNI device
|
||||
*/
|
||||
enum KniInfoState
|
||||
{
|
||||
/** Used to identify intent to obtain cached version of KNI device information */
|
||||
INFO_CACHED = 0,
|
||||
/** Used to identify intent to renew/update KNI device information */
|
||||
INFO_RENEW = 1
|
||||
};
|
||||
/**
|
||||
* Promiscuous mode related constants for KNI device
|
||||
*/
|
||||
enum KniPromiscuousMode
|
||||
{
|
||||
/** Used to DISABLE promiscuous mode on KNI device */
|
||||
PROMISC_DISABLE = 0,
|
||||
/** Used to ENABLE promiscuous mode on KNI device */
|
||||
PROMISC_ENABLE = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief New callbacks for KNI device events.
|
||||
* This structure MUST be used ONLY when KniDeviceList#callbackVersion returns
|
||||
* KniDeviceList#KniCallbackVersion#CALLBACKS_NEW.
|
||||
* Or if You are sure that DPDK version used is 17.11 or higher.
|
||||
* If some callback is not provided (NULL) the request will always succeeds
|
||||
* if other is not specified in callback description.
|
||||
* @note This callbacks are direct copy of one defined in rte_kni_ops. Future
|
||||
* maintainers of KNI device feature MUST refer to rte_kni_ops structure in
|
||||
* rte_kni.h header file of DPDK to track the difference in signatures
|
||||
*/
|
||||
struct KniIoctlCallbacks
|
||||
{
|
||||
/**
|
||||
* Pointer to function of changing MTU.
|
||||
* Must return 0 in case of success or negative error code
|
||||
*/
|
||||
int (*change_mtu)(uint16_t port_id, unsigned int new_mtu);
|
||||
/**
|
||||
* Pointer to function of configuring network interface.
|
||||
* Must return 0 in case of success or negative error code
|
||||
*/
|
||||
int (*config_network_if)(uint16_t port_id, uint8_t if_up);
|
||||
/**
|
||||
* Pointer to function of configuring mac address.
|
||||
* If callback is not provided and port_id of KNI device is not UINT16_MAX
|
||||
* then DPDK will use predefined callback witch sets MAC address of
|
||||
* DPDK port port_id via rte_eth_dev_default_mac_addr_set.
|
||||
* Must return 0 in case of success or negative error code
|
||||
*/
|
||||
int (*config_mac_address)(uint16_t port_id, uint8_t mac_addr[]);
|
||||
/**
|
||||
* Pointer to function of configuring promiscuous mode.
|
||||
* If callback is not provided and port_id of KNI device is not UINT16_MAX
|
||||
* then DPDK will use predefined callback witch sets promiscuous mode of
|
||||
* DPDK port port_id via rte_eth_promiscuous_enable/rte_eth_promiscuous_disable.
|
||||
* Must return 0 in case of success or negative error code
|
||||
*/
|
||||
int (*config_promiscusity)(uint16_t port_id, uint8_t to_on);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Old callbacks for KNI device events.
|
||||
* This structure MUST be used ONLY when KniDeviceList#callbackVersion returns
|
||||
* KniDeviceList#KniCallbackVersion#CALLBACKS_OLD.
|
||||
* Or if You are sure that DPDK version used is lower than 17.11.
|
||||
* If some callback is not provided (NULL) the request will always succeeds.
|
||||
*/
|
||||
struct KniOldIoctlCallbacks
|
||||
{
|
||||
/**
|
||||
* Pointer to function of changing MTU.
|
||||
* Must return 0 in case of success or negative error code
|
||||
*/
|
||||
int (*change_mtu)(uint8_t port_id, unsigned int new_mtu);
|
||||
/**
|
||||
* Pointer to function of configuring network interface.
|
||||
* Must return 0 in case of success or negative error code
|
||||
*/
|
||||
int (*config_network_if)(uint8_t port_id, uint8_t if_up);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief KNI device initialization data.
|
||||
* Used to create new KNI device.
|
||||
* Usage of callbacks member or oldCallbacks member is defined by
|
||||
* result of KniDeviceList#callbackVersion
|
||||
*/
|
||||
struct KniDeviceConfiguration
|
||||
{
|
||||
/**
|
||||
* Name used to display device in system.
|
||||
* Must not interfere with already existing network interfaces.
|
||||
* Must be less than or equal to IFNAMSIZ (16 chars including \0 on most systems)
|
||||
*/
|
||||
std::string name;
|
||||
union
|
||||
{
|
||||
KniIoctlCallbacks* callbacks;
|
||||
KniOldIoctlCallbacks* oldCallbacks;
|
||||
};
|
||||
/**
|
||||
* MAC (ETHERNET) address of new KNI device.
|
||||
* If MacAddress::Zero is provided then
|
||||
* some valid address will be automatically generated.
|
||||
* If provided (not MacAddress::Zero) will be cached by new KNI device info structure.
|
||||
*/
|
||||
MacAddress mac;
|
||||
/**
|
||||
* Used in same way as DPDK port id.
|
||||
* If some new callbacks are omitted then have separate meaning
|
||||
* (see KniIoctlCallbacks#config_mac_address and KniIoctlCallbacks#config_promiscusity).
|
||||
* Can be set to UINT16_MAX.
|
||||
*/
|
||||
uint16_t portId;
|
||||
/** MTU of new KNI device. Will be cached by new KNI device info structure */
|
||||
uint16_t mtu;
|
||||
/**
|
||||
* If set forces to bind KNI Linux kernel thread (NOT userspace thread) to specific core.
|
||||
* If rte_kni kernel module is loaded with "kthread_mode=single" then -
|
||||
* rebinds kernel thread used for all KNI devices to specified core.
|
||||
* If rte_kni kernel module is loaded with "kthread_mode=multiple" then -
|
||||
* binds new kernel thread for this device to specified core.
|
||||
*/
|
||||
bool bindKthread;
|
||||
/** ID of core to bind Linux kernel thread to (same as DPDK cores IDs) */
|
||||
uint32_t kthreadCoreId;
|
||||
};
|
||||
|
||||
private:
|
||||
/** All instances of this class MUST be produced by KniDeviceList class */
|
||||
KniDevice(const KniDeviceConfiguration& conf, size_t mempoolSize, int unique);
|
||||
/** This class is not copyable */
|
||||
KniDevice(const KniDevice&);
|
||||
/** This class is not copyable */
|
||||
KniDevice& operator=(const KniDevice&);
|
||||
/** All instances of this class MUST be destroyed by KniDeviceList class */
|
||||
~KniDevice();
|
||||
|
||||
public:
|
||||
/* Information getters */
|
||||
|
||||
/**
|
||||
* Indicates whether the KNI device was initialized successfully
|
||||
*/
|
||||
inline bool isInitialized() const { return !(m_Device == NULL || m_MBufMempool == NULL); }
|
||||
/**
|
||||
* Obtains name of KNI device in form of C++ string
|
||||
*/
|
||||
inline std::string getName() const { return std::string(m_DeviceInfo.name); }
|
||||
/**
|
||||
* Obtains port ID of KNI device
|
||||
*/
|
||||
inline uint16_t getPort() const { return m_DeviceInfo.portId; }
|
||||
/**
|
||||
* @brief Obtains link status of KNI device.
|
||||
* If called with INFO_CACHED - returns cached data about link state (SUPER FAST may be INACCURATE).
|
||||
* If called with INFO_RENEW - makes system call to Linux to obtain
|
||||
* link information and caches it (VERY SLOW but ACCURATE).
|
||||
* @param[in] state Defines information relevance level
|
||||
* @return LINK_UP, LINK_DOWN, LINK_NOT_SUPPORTED if device is not initialized, some times LINK_ERROR
|
||||
*/
|
||||
KniLinkState getLinkState(KniInfoState state = INFO_CACHED);
|
||||
/**
|
||||
* @brief Obtains MAC address of KNI device.
|
||||
* If called with INFO_CACHED - returns cached data about MAC address (SUPER FAST may be INACCURATE).
|
||||
* If called with INFO_RENEW - makes system call to Linux to obtain
|
||||
* MAC address and caches it (VERY SLOW but ACCURATE).
|
||||
* @param[in] state Defines information relevance level
|
||||
* @return Known MAC address of KNI interface
|
||||
*/
|
||||
MacAddress getMacAddress(KniInfoState state = INFO_CACHED);
|
||||
/**
|
||||
* @brief Obtains MTU of KNI device.
|
||||
* If called with INFO_CACHED - returns cached data about MTU (SUPER FAST may be INACCURATE).
|
||||
* If called with INFO_RENEW - makes system call to Linux to obtain
|
||||
* MTU and caches it (VERY SLOW but ACCURATE).
|
||||
* @param[in] state Defines information relevance level
|
||||
* @return Known MTU of KNI interface
|
||||
*/
|
||||
uint16_t getMtu(KniInfoState state = INFO_CACHED);
|
||||
/**
|
||||
* @brief Obtains information about promiscuous mode of KNI device.
|
||||
* If called with INFO_CACHED - returns cached data about promiscuous mode (SUPER FAST may be INACCURATE).
|
||||
* If called with INFO_RENEW - makes system call to Linux to obtain
|
||||
* promiscuous mode and caches it (VERY SLOW but ACCURATE).
|
||||
* @param[in] state Defines information relevance level
|
||||
* @return Known promiscuous mode of KNI interface
|
||||
*/
|
||||
KniPromiscuousMode getPromiscuous(KniInfoState state = INFO_CACHED);
|
||||
|
||||
/* Information setters */
|
||||
|
||||
/**
|
||||
* @brief Sets link state of KNI device.
|
||||
* Firstly the link information is updated as by call to getLinkState(INFO_RENEW).
|
||||
* Then link state is set only if obtained state differs from provided.
|
||||
* New link state of KNI device is cached.
|
||||
* @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function
|
||||
* @note Generates change link state request
|
||||
* @param[in] state Must be LINK_UP or LINK_DOWN
|
||||
* @return true if desired link state of KNI device is set (was as provided or set successfully),
|
||||
* false if some error occurred (debug info is printed)
|
||||
*/
|
||||
bool setLinkState(KniLinkState state);
|
||||
/**
|
||||
* @brief Sets MAC address of KNI device.
|
||||
* Unconditionally changes MAC of KNI device.
|
||||
* If MAC is updated successfully then it is cached.
|
||||
* @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function
|
||||
* @note Generates change mac request
|
||||
* @param[in] mac New MAC address of KNI device
|
||||
* @return true if desired MAC address is set, false if not and some error occurred (debug info is printed)
|
||||
*/
|
||||
bool setMacAddress(MacAddress mac);
|
||||
/**
|
||||
* @brief Sets MTU of KNI device.
|
||||
* Unconditionally changes MTU of KNI device.
|
||||
* If MTU is updated successfully then it is cached.
|
||||
* @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function
|
||||
* @note Generates change mtu request
|
||||
* @warning Low MTU values may crush Linux kernel. Follow Your kernel version documentation for details
|
||||
* @param[in] mtu New MTU address of KNI device
|
||||
* @return true if desired MTU is set, false if not and some error occurred (debug info is printed)
|
||||
*/
|
||||
bool setMtu(uint16_t mtu);
|
||||
/**
|
||||
* @brief Sets promiscuous mode of KNI device.
|
||||
* Firstly the promiscuous mode information is updated as by call to getPromiscuous(INFO_RENEW).
|
||||
* Then promiscuous mode is set only if obtained mode differs from provided.
|
||||
* New promiscuous mode of KNI device is cached.
|
||||
* @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function
|
||||
* @note Generates promiscuous mode request
|
||||
* @param[in] mode Must be PROMISC_DISABLE or PROMISC_ENABLE
|
||||
* @return true if desired promiscuous mode of KNI device is set (was as provided or set successfully),
|
||||
* false if some error occurred (debug info is printed)
|
||||
*/
|
||||
bool setPromiscuous(KniPromiscuousMode mode);
|
||||
/**
|
||||
* @brief Updates link state of KNI device.
|
||||
* Unconditionally updates link state of KNI device via call to DPDK librte_kni API.
|
||||
* FASTER THAN setLinkState(state) but may not be supported or may fail.
|
||||
* If link state is updated successfully then it is cached.
|
||||
* @param[in] state New link state of KNI device
|
||||
* @return LINK_NOT_SUPPORTED if this capability is not supported by DPDK version used (DPDK ver < 18.11),
|
||||
* LINK_ERROR if attempt to set link state failed (may always fail on some systems see class description)
|
||||
* LINK_DOWN - previous link state was DOWN, state is successfully updated to provided one
|
||||
* LINK_UP - previous link state was UP, state is successfully updated to provided one
|
||||
*/
|
||||
KniLinkState updateLinkState(KniLinkState state);
|
||||
|
||||
/* Requests */
|
||||
|
||||
/**
|
||||
* @brief Handle requests from Linux kernel synchronously in calling thread.
|
||||
* When one of events which is needed application attention occurres it must be handled by calling this
|
||||
* function (or by running RequestHandlerThread for this device).
|
||||
* Until the request is handled the Linux kernel thread that manages this KNI is blocked.
|
||||
* If it is not handled by application in 3 seconds the request is reported to kernel as failed one.
|
||||
* Current known requests are:
|
||||
* - change link state: ip l set [interface] up/down
|
||||
* - change mtu: ip l set dev [interface] mtu [mtu_count]
|
||||
* - change mac: ip l set [interface] address [new_mac]
|
||||
* - change promiscuous mode: ip l set [interface] promisc on/off
|
||||
* @warning Functions setLinkState, setMacAddress, setMtu and setPromiscuous will generate this requests.
|
||||
* @note Callbacks provided for this KNI device will be called synchronously in calling thread during execution of this function
|
||||
* @return true if no error happened during request handling false otherwise
|
||||
*/
|
||||
bool handleRequests();
|
||||
/**
|
||||
* @brief Starts new thread (using pthread) to asynchronously handle KNI device requests.
|
||||
* See description of handleRequests() about requests.
|
||||
* New thread is detached using pthread_detach.
|
||||
* This thread can be stopped explicitly by calling stopRequestHandlerThread() or
|
||||
* implicitly on KNI device destruction.
|
||||
* Linux <a href="http://man7.org/linux/man-pages/man2/nanosleep.2.html">nanosleep()</a> function is used for sleeping.
|
||||
* @note Callbacks provided for this KNI device will be called asynchronously in new thread
|
||||
* @param[in] sleepSeconds Sleeping time in seconds
|
||||
* @param[in] sleepNanoSeconds Sleeping time in nanoseconds
|
||||
* @return true if new thread is started successfully false otherwise
|
||||
*/
|
||||
bool startRequestHandlerThread(long sleepSeconds, long sleepNanoSeconds = 0);
|
||||
/**
|
||||
* @brief Explicitly stops request thread for this device if it was running.
|
||||
* See description of handleRequests() about requests.
|
||||
* @warning There may be a rare error when request thread handles requests on already
|
||||
* destroyed device. It occurres only because request thread is detached one but it is really really rare.
|
||||
* In case of this error occurring (must be SIGSEGV) change type of created thread in startRequestHandlerThread
|
||||
* function from DETACHED to JOINABLE.
|
||||
*/
|
||||
void stopRequestHandlerThread();
|
||||
|
||||
/* Packet receive */
|
||||
|
||||
/**
|
||||
* @brief Receive raw packets from kernel.
|
||||
* @param[out] rawPacketsArr A vector where all received packets will be written into
|
||||
* @return The number of packets received. If an error occurred 0 will be returned and the error will be printed to log
|
||||
*/
|
||||
uint16_t receivePackets(MBufRawPacketVector& rawPacketsArr);
|
||||
/**
|
||||
* @brief Receive raw packets from kernel.
|
||||
* Please notice that in terms of performance, this is the best method to use
|
||||
* for receiving packets because out of all receivePackets overloads this method requires the least overhead and is
|
||||
* almost as efficient as receiving packets directly through DPDK. So if performance is a critical factor in your
|
||||
* application, please use this method
|
||||
* @param[out] rawPacketsArr A pointer to an array of MBufRawPacket pointers where all received packets will be written into. The array is expected to
|
||||
* be allocated by the user and its length should be provided in rawPacketArrLength. Number of packets received will be returned.
|
||||
* Notice it's the user responsibility to free the array and its content when done using it
|
||||
* @param[out] rawPacketArrLength The length of MBufRawPacket pointers array
|
||||
* @return The number of packets received. If an error occurred 0 will be returned and the error will be printed to log
|
||||
*/
|
||||
uint16_t receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength);
|
||||
/**
|
||||
* @brief Receive parsed packets from kernel.
|
||||
* @param[out] packetsArr A pointer to an allocated array of Packet pointers where all received packets will be written into. The array is expected to
|
||||
* be allocated by the user and its length should be provided in packetsArrLength. Number of packets received will be returned.
|
||||
* Notice it's the user responsibility to free the array and its content when done using it
|
||||
* @param[out] packetsArrLength The length of Packet pointers array
|
||||
* @return The number of packets received. If an error occurred 0 will be returned and the error will be printed to log
|
||||
*/
|
||||
uint16_t receivePackets(Packet** packetsArr, uint16_t packetsArrLength);
|
||||
|
||||
/* Packet send */
|
||||
|
||||
/**
|
||||
* @brief Send an array of MBufRawPacket to kernel.
|
||||
* Please notice the following:<BR>
|
||||
* - In terms of performance, this is the best method to use for sending packets because out of all sendPackets overloads
|
||||
* this method requires the least overhead and is almost as efficient as sending the packets directly through DPDK. So if performance
|
||||
* is a critical factor in your application, please use this method
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] rawPacketsArr A pointer to an array of MBufRawPacket
|
||||
* @param[in] arrLength The length of the array
|
||||
* @return The number of packets actually and successfully sent
|
||||
*/
|
||||
uint16_t sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength);
|
||||
/**
|
||||
* @brief Send an array of parsed packets to kernel.
|
||||
* Please notice the following:<BR>
|
||||
* - If some or all of the packets contain raw packets which aren't of type MBufRawPacket, a new temp MBufRawPacket instances
|
||||
* will be created and packet data will be copied to them. This is necessary to allocate mbufs which will store the data to be sent.
|
||||
* If performance is a critical factor please make sure you send parsed packets
|
||||
* that contain only raw packets of type MBufRawPacket
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] packetsArr A pointer to an array of parsed packet pointers
|
||||
* @param[in] arrLength The length of the array
|
||||
* @return The number of packets actually and successfully sent
|
||||
*/
|
||||
uint16_t sendPackets(Packet** packetsArr, uint16_t arrLength);
|
||||
/**
|
||||
* @brief Send a vector of MBufRawPacket pointers to kernel.
|
||||
* Please notice the following:<BR>
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] rawPacketsVec The vector of raw packet
|
||||
* @return The number of packets actually and successfully sent
|
||||
*/
|
||||
uint16_t sendPackets(MBufRawPacketVector& rawPacketsVec);
|
||||
/**
|
||||
* @brief Send a vector of RawPacket pointers to kernel.
|
||||
* Please notice the following:<BR>
|
||||
* - If some or all of the raw packets aren't of type MBufRawPacket, a new temp MBufRawPacket instances will be created
|
||||
* and packet data will be copied to them. This is necessary to allocate mbufs which will store the data to be sent. If
|
||||
* performance is a critical factor please make sure you send only raw packets of type MBufRawPacket
|
||||
* (or use the sendPackets overload that sends MBufRawPacketVector)
|
||||
* - If the number of packets to send is higher than 64 this method will run multiple iterations of sending packets to DPDK, each
|
||||
* iteration of 64 packets
|
||||
* - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by DPDK
|
||||
* <BR><BR>
|
||||
* @param[in] rawPacketsVec The vector of raw packet
|
||||
* @return The number of packets actually and successfully sent
|
||||
*/
|
||||
uint16_t sendPackets(RawPacketVector& rawPacketsVec);
|
||||
/**
|
||||
* @brief Send a raw packet to kernel.
|
||||
* Please notice that if the raw packet isn't of type MBufRawPacket, a new temp MBufRawPacket
|
||||
* will be created and the data will be copied to it. This is necessary to allocate an mbuf which will store the data to be sent.
|
||||
* If performance is a critical factor please make sure you send a raw packet of type MBufRawPacket.
|
||||
* Please also notice that the mbuf used or allocated in this method isn't freed by this method, it will be transparently freed by DPDK
|
||||
* @param[in] rawPacket The raw packet to send
|
||||
* @return True if packet was sent successfully or false if the packet wasn't sent for any other reason
|
||||
*/
|
||||
bool sendPacket(RawPacket& rawPacket);
|
||||
/**
|
||||
* @brief Send a MBufRawPacket to kernel.
|
||||
* Please notice that the mbuf used in this method isn't freed by this method, it will be transparently freed by DPDK
|
||||
* @param[in] rawPacket The MBufRawPacket to send
|
||||
* @return True if packet was sent successfully or false if device is not opened or if the packet wasn't sent for any other reason
|
||||
*/
|
||||
bool sendPacket(MBufRawPacket& rawPacket);
|
||||
/**
|
||||
* @brief Send a parsed packet to kernel.
|
||||
* Please notice that the mbuf used or allocated in this method isn't freed by this method, it will be transparently freed by DPDK
|
||||
* @param[in] packet The parsed packet to send. Please notice that if the packet contains a raw packet which isn't of type
|
||||
* MBufRawPacket, a new temp MBufRawPacket will be created and the data will be copied to it. This is necessary to
|
||||
* allocate an mbuf which will store the data to be sent. If performance is a critical factor please make sure you send a
|
||||
* parsed packet that contains a raw packet of type MBufRawPacket
|
||||
* @return True if packet was sent successfully or false if device is not opened or if the packet wasn't sent for any other reason
|
||||
*/
|
||||
bool sendPacket(Packet& packet);
|
||||
|
||||
/* Packet capture */
|
||||
|
||||
/**
|
||||
* @brief Start capturing packets asynchronously on this KNI interface.
|
||||
* Each time a burst of packets is captured the onPacketArrives callback is called.
|
||||
* The capture is done on a new thread created by this method, meaning all callback
|
||||
* calls are done in a thread other than the caller thread.
|
||||
* Capture process will stop and this capture thread will be terminated when calling stopCapture().
|
||||
* This method must be called after the device is opened (i.e the open() method was called), otherwise an error will be returned.
|
||||
* Capturing thread will be terminated automatically on KNI device destruction or when close() is called.
|
||||
* @param[in] onPacketArrives A callback that is called each time a burst of packets is captured
|
||||
* @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to the onPacketArrives callback
|
||||
* each time it is called. This cookie is very useful for transferring objects that give context to the capture callback, for example:
|
||||
* objects that counts packets, manages flow state or manages the application state according to the packet that was captured
|
||||
* @return True if capture started successfully, false if (relevant log error is printed in any case):
|
||||
* - Capture is already running
|
||||
* - Device is not opened
|
||||
* - Capture thread could not be created
|
||||
*/
|
||||
bool startCapture(OnKniPacketArriveCallback onPacketArrives, void* onPacketArrivesUserCookie);
|
||||
/**
|
||||
* @brief Start capturing packets synchronously on this KNI interface in blocking mode.
|
||||
* Blocking mode means that this method block and won't return until the user frees the blocking
|
||||
* (via onPacketArrives callback) or until a user defined timeout expires.
|
||||
* Whenever a burst of packets is captured the onPacketArrives callback is called and lets the user handle the packet.
|
||||
* In each callback call the user should return true if he wants to release the block or false if it wants it to keep blocking.
|
||||
* Regardless of this callback a timeout is defined when stop capturing.
|
||||
* When this timeout expires the method will return.<BR>
|
||||
* Please notice that stopCapture() isn't needed here because when the method returns (after timeout or per user decision) capturing
|
||||
* on the device is stopped.
|
||||
* @param[in] onPacketArrives A callback given by the user for handling incoming packets. After handling each burst of packets
|
||||
* the user needs to return a boolean value. True value indicates stop capturing and stop blocking and
|
||||
* false value indicates continue capturing and blocking
|
||||
* @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to the onPacketArrives callback
|
||||
* each time it is called. This cookie is very useful for transferring objects that give context to the capture callback, for example:
|
||||
* objects that counts packets, manages flow state or manages the application state according to the packet that was captured
|
||||
* @param[in] timeout A timeout in seconds for the blocking to stop even if the user didn't return "true" in the onPacketArrives callback
|
||||
* If this timeout is set to 0 or less the timeout will be ignored, meaning the method will keep blocking until the user frees it via
|
||||
* the onPacketArrives callback
|
||||
* @return -1 if timeout expired, 1 if blocking was stopped via onPacketArrives callback or 0 if an error occurred (such as device
|
||||
* not open etc.). When returning 0 an appropriate error message is printed to log
|
||||
*/
|
||||
int startCaptureBlockingMode(OnKniPacketArriveCallback onPacketArrives, void* onPacketArrivesUserCookie, int timeout);
|
||||
/**
|
||||
* Stop a currently running asynchronous packet capture.
|
||||
*/
|
||||
void stopCapture();
|
||||
|
||||
/* Device control */
|
||||
|
||||
/**
|
||||
* Takes appropriate actions for opening KNI device.
|
||||
* @return true if the device was opened successfully, false if device is already opened,
|
||||
* or KNI device configuration and startup failed
|
||||
*/
|
||||
bool open();
|
||||
/**
|
||||
* @brief Close the KNI device.
|
||||
* When device is closed it's not possible to work with it.
|
||||
* Stops asynchronous packet capture if it is running.
|
||||
*/
|
||||
void close();
|
||||
|
||||
private:
|
||||
struct rte_kni* m_Device;
|
||||
struct rte_mempool* m_MBufMempool;
|
||||
struct KniDeviceInfo
|
||||
{
|
||||
LinuxNicInformationSocket soc;
|
||||
KniLinkState link;
|
||||
KniPromiscuousMode promisc;
|
||||
uint16_t portId;
|
||||
uint16_t mtu;
|
||||
MacAddress mac;
|
||||
std::string name;
|
||||
|
||||
bool init(const KniDeviceConfiguration& conf);
|
||||
} m_DeviceInfo;
|
||||
struct KniThread;
|
||||
struct KniCapturing
|
||||
{
|
||||
OnKniPacketArriveCallback callback;
|
||||
void* userCookie;
|
||||
KniThread* thread;
|
||||
|
||||
static void* runCapture(void* devicePointer);
|
||||
inline bool isRunning() const { return thread != NULL; }
|
||||
void cleanup();
|
||||
} m_Capturing;
|
||||
struct KniRequests
|
||||
{
|
||||
long sleepS;
|
||||
long sleepNs;
|
||||
KniThread* thread;
|
||||
|
||||
static void* runRequests(void* devicePointer);
|
||||
void cleanup();
|
||||
} m_Requests;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
#endif /* PCAPPP_KNI_DEVICE */
|
||||
127
pcappp/include/pcapplusplus/KniDeviceList.h
Normal file
127
pcappp/include/pcapplusplus/KniDeviceList.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef PCAPPP_KNI_DEVICE_LIST
|
||||
#define PCAPPP_KNI_DEVICE_LIST
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "KniDevice.h"
|
||||
#include "DpdkDeviceList.h"
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class KniDeviceList
|
||||
* A singleton class that encapsulates DPDK KNI module initialization
|
||||
* and holds the list of KniDevice instances.
|
||||
* As it's a singleton, it has only one active instance doesn't have a public c'tor.
|
||||
*/
|
||||
class KniDeviceList
|
||||
{
|
||||
KniDeviceList();
|
||||
|
||||
/**
|
||||
* @brief Explicit destruction of KNI device.
|
||||
* After this call device is no longer available for external (by Linux)
|
||||
* or internal (by application) usage.
|
||||
* All threads running on this device are stopped (request and/or capturing).
|
||||
* The device can no longer be found by it's name or id.
|
||||
* @warning NOT MT SAFE
|
||||
* @warning This method is forbidden as the result of discussion about packet memory pool
|
||||
* lifetime made <a href="https://github.com/seladb/PcapPlusPlus/pull/196#discussion_r286649704">here</a>.
|
||||
* If You feel safe to use it please do, but no guarantee is provided.
|
||||
* @param[in] kniDevice KNI device to be destroyed explicitly
|
||||
*/
|
||||
void destroyDevice(KniDevice* kniDevice);
|
||||
public:
|
||||
/**
|
||||
* Callback related constants for KNI device
|
||||
*/
|
||||
enum KniCallbackVersion
|
||||
{
|
||||
/** Reports that DPDK supports only KniDevice#KniIoctlCallbacks callback structure */
|
||||
CALLBACKS_NEW = 0,
|
||||
/** Reports that DPDK supports only KniDevice#KniOldIoctlCallbacks callback structure */
|
||||
CALLBACKS_OLD = 1
|
||||
};
|
||||
/**
|
||||
* Various callback types supported by KNI device
|
||||
*/
|
||||
enum KniCallbackType
|
||||
{
|
||||
/** KniDevice#KniIoctlCallbacks#change_mtu and KniDevice#KniOldIoctlCallbacks#change_mtu callback */
|
||||
CALLBACK_MTU,
|
||||
/** KniDevice#KniIoctlCallbacks#config_network_if and KniDevice#KniOldIoctlCallbacks#config_network_if callback */
|
||||
CALLBACK_LINK,
|
||||
/** KniDevice#KniIoctlCallbacks#config_mac_address callback */
|
||||
CALLBACK_MAC,
|
||||
/** KniDevice#KniIoctlCallbacks#config_promiscusity callback */
|
||||
CALLBACK_PROMISC
|
||||
};
|
||||
|
||||
~KniDeviceList();
|
||||
|
||||
/**
|
||||
* @brief Getter for singleton
|
||||
* @warning Initialization of Kni module depends on initialization of DPDK made by DpdkDeviceList
|
||||
* @return The singleton instance of KniDeviceList
|
||||
*/
|
||||
static KniDeviceList& getInstance();
|
||||
|
||||
/**
|
||||
* @return true if KNI module was initialized successfully false otherwise
|
||||
*/
|
||||
inline bool isInitialized() { return m_Initialized; }
|
||||
|
||||
/* Device manipulation */
|
||||
|
||||
/**
|
||||
* @brief Factory method for KNI devices.
|
||||
* Newly created device is remembered under portId and name provided in config and can be found later by them.
|
||||
* If KNI device is not destroyed explicitly thru KniDeviceList#destroyDevice
|
||||
* then it will be destroyed implicitly by the time application exits.
|
||||
* @warning NOT MT SAFE
|
||||
* @param[in] config KNI device configuration structure
|
||||
* @param[in] mempoolSize Size of packet mempool used by this device
|
||||
* @return Pointer to new KNI device or NULL in case of error
|
||||
*/
|
||||
KniDevice* createDevice(const KniDevice::KniDeviceConfiguration& config, const size_t mempoolSize);
|
||||
/**
|
||||
* @brief Returns KNI device with specified portId.
|
||||
* @note MT SAFE if createDevice or destroyDevice is not called concurrently
|
||||
* @param[in] portId ID of KNI device to find
|
||||
* @return Pointer to KNI device or NULL if device not found
|
||||
*/
|
||||
KniDevice* getDeviceByPort(const uint16_t portId);
|
||||
/**
|
||||
* @brief Returns KNI device with specified name.
|
||||
* @note MT SAFE if createDevice or destroyDevice is not called concurrently
|
||||
* @param[in] name Name of KNI device to find
|
||||
* @return Pointer to KNI device or NULL if device not found
|
||||
*/
|
||||
KniDevice* getDeviceByName(const std::string& name);
|
||||
|
||||
/* Static information */
|
||||
|
||||
/**
|
||||
* Returns KniCallbackVersion#CALLBACKS_NEW or
|
||||
* KniCallbackVersion#CALLBACKS_OLD based on DPDK version used
|
||||
* @note MT SAFE
|
||||
*/
|
||||
static KniCallbackVersion callbackVersion();
|
||||
/**
|
||||
* Returns true if provided callback type is supported by used DPDK version
|
||||
* @note MT SAFE
|
||||
* @param[in] cbType One of KniCallbackType enum values
|
||||
*/
|
||||
static bool isCallbackSupported(const KniCallbackType cbType);
|
||||
private:
|
||||
std::vector<KniDevice*> m_Devices;
|
||||
bool m_Initialized;
|
||||
int m_KniUniqueId;
|
||||
};
|
||||
} // namespace pcpp
|
||||
#endif /* PCAPPP_KNI_DEVICE_LIST */
|
||||
135
pcappp/include/pcapplusplus/LRUList.h
Normal file
135
pcappp/include/pcapplusplus/LRUList.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#ifndef PCAPPP_LRU_LIST
|
||||
#define PCAPPP_LRU_LIST
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#if __cplusplus > 199711L || _MSC_VER >= 1800
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class LRUList
|
||||
* A template class that implements a LRU cache with limited size. Each time the user puts an element it goes to head of the
|
||||
* list as the most recently used element (if the element was already in the list it advances to the head of the list).
|
||||
* The last element in the list is the one least recently used and will be pulled out of the list if it reaches its max size
|
||||
* and a new element comes in. All actions on this LRU list are O(1)
|
||||
*/
|
||||
template<typename T>
|
||||
class LRUList
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename std::list<T>::iterator ListIterator;
|
||||
typedef typename std::map<T, ListIterator>::iterator MapIterator;
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] maxSize The max size this list can go
|
||||
*/
|
||||
LRUList(size_t maxSize)
|
||||
{
|
||||
m_MaxSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an element in the list. This element will be inserted (or advanced if it already exists) to the head of the
|
||||
* list as the most recently used element. If the list already reached its max size and the element is new this method
|
||||
* will remove the least recently used element and return a value in deletedValue. Method complexity is O(log(getSize())).
|
||||
* This is a optimized version of the method T* put(const T&).
|
||||
* @param[in] element The element to insert or to advance to the head of the list (if already exists)
|
||||
* @param[out] deletedValue The value of deleted element if a pointer is not NULL. This parameter is optional.
|
||||
* @return 0 if the list didn't reach its max size, 1 otherwise. In case the list already reached its max size
|
||||
* and deletedValue is not NULL the value of deleted element is copied into the place the deletedValue points to.
|
||||
*/
|
||||
int put(const T& element, T* deletedValue = NULL)
|
||||
{
|
||||
m_CacheItemsList.push_front(element);
|
||||
|
||||
// Inserting a new element. If an element with an equivalent key already exists the method returns an iterator to the element that prevented the insertion
|
||||
std::pair<MapIterator, bool> pair = m_CacheItemsMap.insert(std::make_pair(element, m_CacheItemsList.begin()));
|
||||
if (pair.second == false) // already exists
|
||||
{
|
||||
m_CacheItemsList.erase(pair.first->second);
|
||||
pair.first->second = m_CacheItemsList.begin();
|
||||
}
|
||||
|
||||
if (m_CacheItemsMap.size() > m_MaxSize)
|
||||
{
|
||||
ListIterator lruIter = m_CacheItemsList.end();
|
||||
lruIter--;
|
||||
|
||||
if (deletedValue != NULL)
|
||||
#if __cplusplus > 199711L || _MSC_VER >= 1800
|
||||
*deletedValue = std::move(*lruIter);
|
||||
#else
|
||||
*deletedValue = *lruIter;
|
||||
#endif
|
||||
m_CacheItemsMap.erase(*lruIter);
|
||||
m_CacheItemsList.erase(lruIter);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most recently used element (the one at the beginning of the list)
|
||||
* @return The most recently used element
|
||||
*/
|
||||
const T& getMRUElement() const
|
||||
{
|
||||
return m_CacheItemsList.front();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the least recently used element (the one at the end of the list)
|
||||
* @return The least recently used element
|
||||
*/
|
||||
const T& getLRUElement() const
|
||||
{
|
||||
return m_CacheItemsList.back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase an element from the list. If element isn't found in the list nothing happens
|
||||
* @param[in] element The element to erase
|
||||
*/
|
||||
void eraseElement(const T& element)
|
||||
{
|
||||
MapIterator iter = m_CacheItemsMap.find(element);
|
||||
if (iter == m_CacheItemsMap.end())
|
||||
return;
|
||||
|
||||
m_CacheItemsList.erase(iter->second);
|
||||
m_CacheItemsMap.erase(iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The max size of this list as determined in the c'tor
|
||||
*/
|
||||
size_t getMaxSize() const { return m_MaxSize; }
|
||||
|
||||
/**
|
||||
* @return The number of elements currently in this list
|
||||
*/
|
||||
size_t getSize() const { return m_CacheItemsMap.size(); }
|
||||
|
||||
private:
|
||||
std::list<T> m_CacheItemsList;
|
||||
std::map<T, ListIterator> m_CacheItemsMap;
|
||||
size_t m_MaxSize;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_LRU_LIST */
|
||||
197
pcappp/include/pcapplusplus/Layer.h
Normal file
197
pcappp/include/pcapplusplus/Layer.h
Normal file
@@ -0,0 +1,197 @@
|
||||
#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 */
|
||||
74
pcappp/include/pcapplusplus/LinuxNicInformationSocket.h
Normal file
74
pcappp/include/pcapplusplus/LinuxNicInformationSocket.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef PCAPPP_LINUX_NIC_INFORMATION_SOCKET
|
||||
#define PCAPPP_LINUX_NIC_INFORMATION_SOCKET
|
||||
|
||||
struct ifreq;
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @class LinuxNicInformationSocket
|
||||
* Simple wrapper over Linux socket for making the information
|
||||
* requests about NICs or making some changes in NICs setup.
|
||||
* All possible requests are described in
|
||||
* <a href="http://man7.org/linux/man-pages/man7/netdevice.7.html">netdevice(7)</a>.
|
||||
* The instance of this class handles underlying socket during its lifetime
|
||||
* and takes an appropriate actions to close socket on destruction.
|
||||
* The user must call LinuxNicInformationSocket#makeRequest method with
|
||||
* known ioctl type and properly filled ifreq structure for this ioctl type.
|
||||
* Filling of ifr_name may be omitted as it will be done automatically from
|
||||
* provided NIC name.
|
||||
* @note Usage of this class requires the inclusion of <sys/ioctl.h> and <net/if.h> Linux headers
|
||||
*/
|
||||
class LinuxNicInformationSocket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Simple type rename for convenience
|
||||
*/
|
||||
typedef int LinuxSocket;
|
||||
/**
|
||||
* Simple type rename for convenience
|
||||
*/
|
||||
typedef unsigned long IoctlType;
|
||||
|
||||
/**
|
||||
* Tries to open handled socket on construction.
|
||||
* If fails prints the debug message
|
||||
*/
|
||||
LinuxNicInformationSocket();
|
||||
/**
|
||||
* Closes handled socket on destruction.
|
||||
* If no socket was opened prints the debug message
|
||||
*/
|
||||
~LinuxNicInformationSocket();
|
||||
|
||||
/**
|
||||
* @brief Makes request to socket.
|
||||
* Firstly tries to open socket if it is not opened.
|
||||
* Then makes an ioctl(2) request to handled socket with provided request structure.
|
||||
* See: <a href="http://man7.org/linux/man-pages/man7/netdevice.7.html">netdevice(7)</a>
|
||||
* for description of possible values of ioctlType and content of request.
|
||||
* @note User have no need to fill ifr_name field of request. It will be filled
|
||||
* automatically from provided nicName argument.
|
||||
* @param[in] nicName Name of internet controller as displayed by Linux
|
||||
* @param[in] ioctlType Value of ioctl to make
|
||||
* @param[in,out] request Pointer to ifreq structure that contains some information
|
||||
* or will be used for obtaining the information (depends on ioctlType)
|
||||
* @return false if request was not made or socket can't be opened otherwise true
|
||||
* @warning For some types of requests to succeed You need to be a root
|
||||
* or have the CAP_NET_ADMIN capability.
|
||||
*/
|
||||
bool makeRequest(const char* nicName, const IoctlType ioctlType, ifreq* request);
|
||||
private:
|
||||
/* Hidden copy constructor. This structure is not copyable */
|
||||
LinuxNicInformationSocket(const LinuxNicInformationSocket&);
|
||||
/* Hidden copy assignment operator. This structure is not copyable */
|
||||
LinuxNicInformationSocket operator=(const LinuxNicInformationSocket&);
|
||||
LinuxSocket m_Socket;
|
||||
};
|
||||
} // namespace pcpp
|
||||
#endif /* PCAPPP_LINUX_NIC_INFORMATION_SOCKET */
|
||||
240
pcappp/include/pcapplusplus/Logger.h
Normal file
240
pcappp/include/pcapplusplus/Logger.h
Normal file
@@ -0,0 +1,240 @@
|
||||
#ifndef PCAPPP_LOGGER
|
||||
#define PCAPPP_LOGGER
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef LOG_MODULE
|
||||
#define LOG_MODULE UndefinedLogModule
|
||||
#endif
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* An enum representing all PcapPlusPlus modules
|
||||
*/
|
||||
enum LogModule
|
||||
{
|
||||
UndefinedLogModule,
|
||||
CommonLogModuleIpUtils, ///< IP Utils module (Common++)
|
||||
CommonLogModuleTablePrinter, ///< Table printer module (Common++)
|
||||
CommonLogModuleGenericUtils, ///< Generic Utils (Common++)
|
||||
PacketLogModuleRawPacket, ///< RawPacket module (Packet++)
|
||||
PacketLogModulePacket, ///< Packet module (Packet++)
|
||||
PacketLogModuleLayer, ///< Layer module (Packet++)
|
||||
PacketLogModuleArpLayer, ///< ArpLayer module (Packet++)
|
||||
PacketLogModuleEthLayer, ///< EthLayer module (Packet++)
|
||||
PacketLogModuleIPv4Layer, ///< IPv4Layer module (Packet++)
|
||||
PacketLogModuleIPv6Layer, ///< IPv6Layer module (Packet++)
|
||||
PacketLogModulePayloadLayer, ///< PayloadLayer module (Packet++)
|
||||
PacketLogModuleTcpLayer, ///< TcpLayer module (Packet++)
|
||||
PacketLogModuleUdpLayer, ///< UdpLayer module (Packet++)
|
||||
PacketLogModuleVlanLayer, ///< VlanLayer module (Packet++)
|
||||
PacketLogModuleHttpLayer, ///< HttpLayer module (Packet++)
|
||||
PacketLogModulePPPoELayer, ///< PPPoELayer module (Packet++)
|
||||
PacketLogModuleDnsLayer, ///< DnsLayer module (Packet++)
|
||||
PacketLogModuleMplsLayer, ///< MplsLayer module (Packet++)
|
||||
PacketLogModuleIcmpLayer, ///< IcmpLayer module (Packet++)
|
||||
PacketLogModuleGreLayer, ///< GreLayer module (Packet++)
|
||||
PacketLogModuleSSLLayer, ///< SSLLayer module (Packet++)
|
||||
PacketLogModuleSllLayer, ///< SllLayer module (Packet++)
|
||||
PacketLogModuleDhcpLayer, ///< DhcpLayer module (Packet++)
|
||||
PacketLogModuleDhcpV6Layer, ///< DhcpV6Layer module (Packet++)
|
||||
PacketLogModuleIgmpLayer, ///< IgmpLayer module (Packet++)
|
||||
PacketLogModuleSipLayer, ///< SipLayer module (Packet++)
|
||||
PacketLogModuleSdpLayer, ///< SdpLayer module (Packet++)
|
||||
PacketLogModuleRadiusLayer, ///< RadiusLayer module (Packet++)
|
||||
PacketLogModuleGtpLayer, ///< GtpLayer module (Packet++)
|
||||
PacketLogModuleBgpLayer, ///< GtpLayer module (Packet++)
|
||||
PacketLogModuleSSHLayer, ///< SSHLayer module (Packet++)
|
||||
PacketLogModuleTcpReassembly, ///< TcpReassembly module (Packet++)
|
||||
PacketLogModuleIPReassembly, ///< IPReassembly module (Packet++)
|
||||
PacketLogModuleIPSecLayer, ///< IPSecLayers module (Packet++)
|
||||
PacketLogModuleNtpLayer, ///< NtpLayer module (Packet++)
|
||||
PcapLogModuleWinPcapLiveDevice, ///< WinPcapLiveDevice module (Pcap++)
|
||||
PcapLogModuleRemoteDevice, ///< WinPcapRemoteDevice module (Pcap++)
|
||||
PcapLogModuleLiveDevice, ///< PcapLiveDevice module (Pcap++)
|
||||
PcapLogModuleFileDevice, ///< FileDevice module (Pcap++)
|
||||
PcapLogModulePfRingDevice, ///< PfRingDevice module (Pcap++)
|
||||
PcapLogModuleMBufRawPacket, ///< MBufRawPacket module (Pcap++)
|
||||
PcapLogModuleDpdkDevice, ///< DpdkDevice module (Pcap++)
|
||||
PcapLogModuleKniDevice, ///< KniDevice module (Pcap++)
|
||||
NetworkUtils, ///< NetworkUtils module (Pcap++)
|
||||
NumOfLogModules
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Logger
|
||||
* PcapPlusPlus logger manager.
|
||||
* PcapPlusPlus uses this logger to output both error and debug logs.
|
||||
* There are currently 3 log levels: Logger#Error, Logger#Info and Logger#Debug.
|
||||
*
|
||||
* PcapPlusPlus is divided into modules (described in #LogModule enum). The user can set the log level got each module or to all modules at once.
|
||||
* The default is Logger#Info which outputs only error messages. Changing log level for modules can be done dynamically while the application is running.
|
||||
*
|
||||
* The logger also exposes a method to retrieve the last error log message.
|
||||
*
|
||||
* Logs are printed to console by default in a certain format. The user can set a different print function to change the format or to print to
|
||||
* other media (such as files, etc.).
|
||||
*
|
||||
* PcapPlusPlus logger is a singleton which can be reached from anywhere in the code.
|
||||
*
|
||||
* Note: Logger#Info level logs are currently only used in DPDK devices to set DPDK log level to RTE_LOG_NOTICE.
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* An enum representing the log level. Currently 3 log levels are supported: Error, Info and Debug. Info is the default log level
|
||||
*/
|
||||
enum LogLevel
|
||||
{
|
||||
Error, ///< Error log level
|
||||
Info, ///< Info log level
|
||||
Debug ///< Debug log level
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef LogPrinter
|
||||
* Log printer callback. Used for printing the logs in a custom way.
|
||||
* @param[in] logLevel The log level for this log message
|
||||
* @param[in] logMessage The log message
|
||||
* @param[in] file The source file in PcapPlusPlus code the log message is coming from
|
||||
* @param[in] method The method in PcapPlusPlus code the log message is coming from
|
||||
* @param[in] line The line in PcapPlusPlus code the log message is coming from
|
||||
*/
|
||||
typedef void (*LogPrinter)(LogLevel logLevel, const std::string& logMessage, const std::string& file, const std::string& method, const int line);
|
||||
|
||||
/**
|
||||
* A static method for converting the log level enum to a string.
|
||||
* @param[in] logLevel A log level enum
|
||||
* @return The log level as a string
|
||||
*/
|
||||
static std::string logLevelAsString(LogLevel logLevel);
|
||||
|
||||
/**
|
||||
* Get the log level for a certain module
|
||||
* @param[in] module PcapPlusPlus module
|
||||
* @return The log level set for this module
|
||||
*/
|
||||
LogLevel getLogLevel(LogModule module) { return m_LogModulesArray[module]; }
|
||||
|
||||
/**
|
||||
* Set the log level for a certain PcapPlusPlus module
|
||||
* @param[in] module PcapPlusPlus module
|
||||
* @param[in] level The log level to set the module to
|
||||
*/
|
||||
void setLogLevel(LogModule module, LogLevel level) { m_LogModulesArray[module] = level; }
|
||||
|
||||
/**
|
||||
* Check whether a certain module is set to debug log level
|
||||
* @param[in] module PcapPlusPlus module
|
||||
* @return True if this module log level is "debug". False otherwise
|
||||
*/
|
||||
bool isDebugEnabled(LogModule module) const { return m_LogModulesArray[module] == Debug; }
|
||||
|
||||
/**
|
||||
* Set all PcapPlusPlus modules to a certain log level
|
||||
* @param[in] level The log level to set all modules to
|
||||
*/
|
||||
void setAllModlesToLogLevel(LogLevel level) { for (int i=1; i<NumOfLogModules; i++) m_LogModulesArray[i] = level; }
|
||||
|
||||
/**
|
||||
* Set a custom log printer.
|
||||
* @param[in] printer A log printer function that will be called for every log message
|
||||
*/
|
||||
void setLogPrinter(LogPrinter printer) { m_LogPrinter = printer; }
|
||||
|
||||
/**
|
||||
* Set the log printer back to the default printer
|
||||
*/
|
||||
void resetLogPrinter() { m_LogPrinter = &defaultLogPrinter; }
|
||||
|
||||
/**
|
||||
* @return Get the last error message
|
||||
*/
|
||||
std::string getLastError() { return m_LastError; }
|
||||
|
||||
/**
|
||||
* Suppress logs in all PcapPlusPlus modules
|
||||
*/
|
||||
void suppressLogs() { m_LogsEnabled = false; }
|
||||
|
||||
/**
|
||||
* Enable logs in all PcapPlusPlus modules
|
||||
*/
|
||||
void enableLogs() { m_LogsEnabled = true; }
|
||||
|
||||
/**
|
||||
* Get an indication if logs are currently enabled.
|
||||
* @return True if logs are currently enabled, false otherwise
|
||||
*/
|
||||
bool logsEnabled() const { return m_LogsEnabled; }
|
||||
|
||||
template<class T>
|
||||
Logger& operator<<(const T& msg)
|
||||
{
|
||||
(*m_LogStream) << msg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::ostringstream * internalCreateLogStream();
|
||||
|
||||
/**
|
||||
* An internal method to print log messages. Shouldn't be used externally.
|
||||
*/
|
||||
void internalPrintLogMessage(std::ostringstream* logStream, Logger::LogLevel logLevel, const char* file, const char* method, int line);
|
||||
|
||||
/**
|
||||
* Get access to Logger singleton
|
||||
* @todo: make this singleton thread-safe/
|
||||
* @return a pointer to the Logger singleton
|
||||
**/
|
||||
static Logger& getInstance()
|
||||
{
|
||||
static Logger instance;
|
||||
return instance;
|
||||
}
|
||||
private:
|
||||
bool m_LogsEnabled;
|
||||
Logger::LogLevel m_LogModulesArray[NumOfLogModules];
|
||||
LogPrinter m_LogPrinter;
|
||||
std::string m_LastError;
|
||||
std::ostringstream* m_LogStream;
|
||||
|
||||
// private c'tor - this class is a singleton
|
||||
Logger();
|
||||
|
||||
static void defaultLogPrinter(LogLevel logLevel, const std::string& logMessage, const std::string& file, const std::string& method, const int line);
|
||||
};
|
||||
|
||||
#define PCPP_LOG_DEBUG(message) do \
|
||||
{ \
|
||||
if (pcpp::Logger::getInstance().logsEnabled() && pcpp::Logger::getInstance().isDebugEnabled(LOG_MODULE)) \
|
||||
{ \
|
||||
std::ostringstream* sstream = pcpp::Logger::getInstance().internalCreateLogStream(); \
|
||||
(*sstream) << message; \
|
||||
pcpp::Logger::getInstance().internalPrintLogMessage(sstream, pcpp::Logger::Debug, __FILE__, __FUNCTION__, __LINE__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define PCPP_LOG_ERROR(message) do \
|
||||
{ \
|
||||
std::ostringstream* sstream = pcpp::Logger::getInstance().internalCreateLogStream(); \
|
||||
(*sstream) << message; \
|
||||
pcpp::Logger::getInstance().internalPrintLogMessage(sstream, pcpp::Logger::Error, __FILE__, __FUNCTION__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_LOGGER */
|
||||
218
pcappp/include/pcapplusplus/MBufRawPacket.h
Normal file
218
pcappp/include/pcapplusplus/MBufRawPacket.h
Normal file
@@ -0,0 +1,218 @@
|
||||
#ifndef PCAPPP_MBUF_RAW_PACKET
|
||||
#define PCAPPP_MBUF_RAW_PACKET
|
||||
|
||||
#include <time.h>
|
||||
#include "Packet.h"
|
||||
#include "PointerVector.h"
|
||||
|
||||
struct rte_mbuf;
|
||||
struct rte_mempool;
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
class DpdkDevice;
|
||||
class KniDevice;
|
||||
|
||||
#define MBUFRAWPACKET_OBJECT_TYPE 1
|
||||
|
||||
/**
|
||||
* @class MBufRawPacket
|
||||
* A class that inherits RawPacket and wraps DPDK's mbuf object (see some info about mbuf in DpdkDevice.h) but is
|
||||
* compatible with PcapPlusPlus framework. Using MBufRawPacket is be almost similar to using RawPacket, the implementation
|
||||
* differences are encapsulated in the class implementation. For example: user can create and manipulate a Packet object from
|
||||
* MBufRawPacket the same way it is done with RawPacket; User can use PcapFileWriterDevice to save MBufRawPacket to pcap the
|
||||
* same way it's used with RawPacket; etc.<BR>
|
||||
* The main difference is that RawPacket contains a pointer to the data itself and MBufRawPacket is holding a pointer to an mbuf
|
||||
* object which contains a pointer to the data. This implies that MBufRawPacket without an mbuf allocated to it is not usable.
|
||||
* Getting instances of MBufRawPacket can be done in one to the following ways:
|
||||
* - Receiving packets from DpdkDevice. In this case DpdkDevice takes care of getting the mbuf from DPDK and wrapping it with
|
||||
* MBufRawPacket
|
||||
* - Creating MBufRawPacket from scratch (in order to send it with DpdkDevice, for example). In this case the user should call
|
||||
* the init() method after constructing the object in order to allocate a new mbuf from DPDK port pool (encapsulated by DpdkDevice)
|
||||
*
|
||||
* Limitations of this class:
|
||||
* - Currently chained mbufs are not supported. An mbuf has the capability to be linked to another mbuf and create a linked list
|
||||
* of mbufs. This is good for Jumbo packets or other uses. MBufRawPacket doesn't support this capability so there is no way to
|
||||
* access the mbufs linked to the mbuf wrapped by MBufRawPacket instance. I hope I'll be able to add this support in the future
|
||||
*/
|
||||
class MBufRawPacket : public RawPacket
|
||||
{
|
||||
friend class DpdkDevice;
|
||||
friend class KniDevice;
|
||||
static const int MBUF_DATA_SIZE;
|
||||
|
||||
protected:
|
||||
struct rte_mbuf* m_MBuf;
|
||||
struct rte_mempool* m_Mempool;
|
||||
bool m_FreeMbuf;
|
||||
|
||||
void setMBuf(struct rte_mbuf* mBuf, timespec timestamp);
|
||||
bool init(struct rte_mempool* mempool);
|
||||
bool initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool);
|
||||
public:
|
||||
|
||||
/**
|
||||
* A default c'tor for this class. Constructs an instance of this class without an mbuf attached to it. In order to allocate
|
||||
* an mbuf the user should call the init() method. Without calling init() the instance of this class is not usable.
|
||||
* This c'tor can be used for initializing an array of MBufRawPacket (which requires an empty c'tor)
|
||||
*/
|
||||
MBufRawPacket() : RawPacket(), m_MBuf(NULL), m_Mempool(NULL), m_FreeMbuf(true) { m_DeleteRawDataAtDestructor = false; }
|
||||
|
||||
/**
|
||||
* A d'tor for this class. Once called it frees the mbuf attached to it (returning it back to the mbuf pool it was allocated from)
|
||||
*/
|
||||
virtual ~MBufRawPacket();
|
||||
|
||||
/**
|
||||
* A copy c'tor for this class. The copy c'tor allocates a new mbuf from the same pool the original mbuf was
|
||||
* allocated from, attaches the new mbuf to this instance of MBufRawPacket and copies the data from the original mbuf
|
||||
* to the new mbuf
|
||||
* @param[in] other The MBufRawPacket instance to copy from
|
||||
*/
|
||||
MBufRawPacket(const MBufRawPacket& other);
|
||||
|
||||
/**
|
||||
* @brief Initialize an instance of this class from DpdkDevice.
|
||||
* Initialization includes allocating an mbuf from the pool that resides in DpdkDevice.
|
||||
* The user should call this method only once per instance.
|
||||
* Calling it more than once will result with an error
|
||||
* @param[in] device The DpdkDevice which has the pool to allocate the mbuf from
|
||||
* @return True if initialization succeeded and false if this method was already called for this instance (and an mbuf is
|
||||
* already attached) or if allocating an mbuf from the pool failed for some reason
|
||||
*/
|
||||
bool init(DpdkDevice* device);
|
||||
/**
|
||||
* @brief Initialize an instance of this class from KniDevice.
|
||||
* Initialization includes allocating an mbuf from the pool that resides in KniDevice.
|
||||
* The user should call this method only once per instance.
|
||||
* Calling it more than once will result with an error
|
||||
* @param[in] device The KniDevice which has the pool to allocate the mbuf from
|
||||
* @return True if initialization succeeded and false if this method was already called for this instance (and an mbuf is
|
||||
* already attached) or if allocating an mbuf from the pool failed for some reason
|
||||
*/
|
||||
bool init(KniDevice* device);
|
||||
|
||||
/**
|
||||
* @brief Initialize an instance of this class and copies the content of a RawPacket object.
|
||||
* Initialization includes allocating an mbuf from the pool that resides in provided DpdkDevice,
|
||||
* and copying the data from the input RawPacket object into this mBuf.
|
||||
* The user should call this method only once per instance.
|
||||
* Calling it more than once will result with an error
|
||||
* @param[in] rawPacket A pointer to a RawPacket object from which data will be copied
|
||||
* @param[in] device The DpdkDevice which has the pool to allocate the mbuf from
|
||||
* @return True if initialization succeeded and false if this method was already called for this instance (and an mbuf is
|
||||
* already attached) or if allocating an mbuf from the pool failed for some reason
|
||||
*/
|
||||
bool initFromRawPacket(const RawPacket* rawPacket, DpdkDevice* device);
|
||||
/**
|
||||
* @brief Initialize an instance of this class and copies the content of a RawPacket object.
|
||||
* Initialization includes allocating an mbuf from the pool that resides in provided KniDevice,
|
||||
* and copying the data from the input RawPacket object into this mBuf.
|
||||
* The user should call this method only once per instance.
|
||||
* Calling it more than once will result with an error
|
||||
* @param[in] rawPacket A pointer to a RawPacket object from which data will be copied
|
||||
* @param[in] device The KniDevice which has the pool to allocate the mbuf from
|
||||
* @return True if initialization succeeded and false if this method was already called for this instance (and an mbuf is
|
||||
* already attached) or if allocating an mbuf from the pool failed for some reason
|
||||
*/
|
||||
bool initFromRawPacket(const RawPacket* rawPacket, KniDevice* device);
|
||||
|
||||
/**
|
||||
* @return A pointer to the DPDK mbuf stored in this object
|
||||
*/
|
||||
inline rte_mbuf* getMBuf() { return m_MBuf; }
|
||||
|
||||
// overridden methods
|
||||
|
||||
/**
|
||||
* @return MBufRawPacket object type
|
||||
*/
|
||||
virtual inline uint8_t getObjectType() const { return MBUFRAWPACKET_OBJECT_TYPE; }
|
||||
|
||||
/**
|
||||
* An assignment operator for this class. Copies the data from the mbuf attached to the other MBufRawPacket to the mbuf
|
||||
* attached to this instance. If instance is not initialized (meaning no mbuf is attached) nothing will be copied and
|
||||
* instance will remain uninitialized (also, an error will be printed)
|
||||
* @param[in] other The MBufRawPacket to assign data from
|
||||
*/
|
||||
MBufRawPacket& operator=(const MBufRawPacket& other);
|
||||
|
||||
/**
|
||||
* Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method
|
||||
* which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this pointer right away after
|
||||
* data is copied to the mbuf. So when using this method please notice that after it's called pRawData memory is free, don't
|
||||
* use this pointer again. In addition, if raw packet isn't initialized (mbuf is NULL), this method will call the init() method
|
||||
* @param[in] pRawData A pointer to the new raw data
|
||||
* @param[in] rawDataLen The new raw data length in bytes
|
||||
* @param[in] timestamp The timestamp packet was received by the NIC
|
||||
* @param[in] layerType The link layer type for this raw data. Default is Ethernet
|
||||
* @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the actual packet length. This parameter represents the packet
|
||||
* length. This parameter is optional, if not set or set to -1 it is assumed both lengths are equal
|
||||
* @return True if raw data was copied to the mbuf successfully, false if rawDataLen is larger than mbuf max size, if initialization
|
||||
* failed or if copying the data to the mbuf failed. In all of these cases an error will be printed to log
|
||||
*/
|
||||
bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
|
||||
|
||||
/**
|
||||
* Clears the object and frees the mbuf
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Append packet data at the end of current data. This method uses the same mbuf already allocated and tries to append more space and
|
||||
* copy the data to it. If MBufRawPacket is not initialize (mbuf is NULL) or mbuf append failed an error is printed to log
|
||||
* @param[in] dataToAppend A pointer to the data to append
|
||||
* @param[in] dataToAppendLen Length in bytes of dataToAppend
|
||||
*/
|
||||
void appendData(const uint8_t* dataToAppend, size_t dataToAppendLen);
|
||||
|
||||
/**
|
||||
* Insert raw data at some index of the current data and shift the remaining data to the end. This method uses the
|
||||
* same mbuf already allocated and tries to append more space to it. Then it just copies dataToAppend at the relevant index and shifts
|
||||
* the remaining data to the end. If MBufRawPacket is not initialize (mbuf is NULL) or mbuf append failed an error is printed to log
|
||||
* @param[in] atIndex The index to insert the new data to
|
||||
* @param[in] dataToInsert A pointer to the new data to insert
|
||||
* @param[in] dataToInsertLen Length in bytes of dataToInsert
|
||||
*/
|
||||
void insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen);
|
||||
|
||||
/**
|
||||
* Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be shifted back. This method
|
||||
* uses the mbuf already allocated and tries to trim space from it
|
||||
* @param[in] atIndex The index to start removing bytes from
|
||||
* @param[in] numOfBytesToRemove Number of bytes to remove
|
||||
* @return True if all bytes were removed successfully, or false if MBufRawPacket is not initialize (mbuf is NULL), mbuf trim
|
||||
* failed or logatIndex+numOfBytesToRemove is out-of-bounds of the raw data buffer. In all of these cases an error is printed to log
|
||||
*/
|
||||
bool removeData(int atIndex, size_t numOfBytesToRemove);
|
||||
|
||||
/**
|
||||
* This overridden method,in contrast to its ancestor RawPacket#reallocateData() doesn't need to do anything because mbuf is already
|
||||
* allocated to its maximum extent. So it only performs a check to verify the size after re-allocation doesn't exceed mbuf max size
|
||||
* @param[in] newBufferLength The new buffer length as required by the user
|
||||
* @return True if new size is larger than current size but smaller than mbuf max size, false otherwise
|
||||
*/
|
||||
bool reallocateData(size_t newBufferLength);
|
||||
|
||||
/**
|
||||
* Set an indication whether to free the mbuf when done using it or not ("done using it" means setting another mbuf or class d'tor).
|
||||
* Default value is true.
|
||||
* @param[in] val The value to set. True means free the mbuf when done using it. Default it True
|
||||
*/
|
||||
inline void setFreeMbuf(bool val = true) { m_FreeMbuf = val; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef MBufRawPacketVector
|
||||
* A vector of pointers to MBufRawPacket
|
||||
*/
|
||||
typedef PointerVector<MBufRawPacket> MBufRawPacketVector;
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_MBUF_RAW_PACKET */
|
||||
189
pcappp/include/pcapplusplus/MacAddress.h
Normal file
189
pcappp/include/pcapplusplus/MacAddress.h
Normal file
@@ -0,0 +1,189 @@
|
||||
#ifndef PCAPPP_MACADDRESS
|
||||
#define PCAPPP_MACADDRESS
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#if __cplusplus > 199711L || _MSC_VER >= 1800
|
||||
#include <initializer_list>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class MacAddress
|
||||
* Represents L2 MAC addresses. Can be constructed from string or a series of 6 byte octets
|
||||
*/
|
||||
class MacAddress
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default constructor for this class.
|
||||
* Initializes object to me MacAddress::Zero
|
||||
*/
|
||||
MacAddress() : m_IsValid(true) { memset(m_Address, 0, sizeof(m_Address)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of a byte array. The byte array length must be equal or greater to 6
|
||||
* (as MAC address is 6-byte long)
|
||||
* @todo there is no verification array length >= 6. If this is not the case, address will read uninitialized memory
|
||||
* @param[in] addr A pointer to the byte array containing 6 bytes representing the MAC address
|
||||
*/
|
||||
MacAddress(const uint8_t* addr) : m_IsValid(true) { memcpy(m_Address, addr, sizeof(m_Address)); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of a (char*) string.
|
||||
* If the string doesn't represent a valid MAC address, instance will be invalid, meaning isValid() will return false
|
||||
* @param[in] addr A pointer to the (char*) string
|
||||
*/
|
||||
MacAddress(const char* addr) { init(addr); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of the class out of a std::string.
|
||||
* If the string doesn't represent a valid MAC address, instance will be invalid, meaning isValid() will return false
|
||||
* @param[in] addr A pointer to the string
|
||||
*/
|
||||
MacAddress(const std::string& addr) { init(addr.c_str()); }
|
||||
|
||||
/**
|
||||
* A constructor that creates an instance of 6 bytes representing the MAC address
|
||||
* @param[in] firstOctest Represent the first octet in the address
|
||||
* @param[in] secondOctet Represent the second octet in the address
|
||||
* @param[in] thirdOctet Represent the third octet in the address
|
||||
* @param[in] fourthOctet Represent the fourth octet in the address
|
||||
* @param[in] fifthOctet Represent the fifth octet in the address
|
||||
* @param[in] sixthOctet Represent the sixth octet in the address
|
||||
*/
|
||||
inline MacAddress(uint8_t firstOctest, uint8_t secondOctet, uint8_t thirdOctet, uint8_t fourthOctet, uint8_t fifthOctet, uint8_t sixthOctet);
|
||||
|
||||
#if __cplusplus > 199711L || _MSC_VER >= 1800
|
||||
/**
|
||||
* A constructor that creates an instance out of the initializer list. The length of the list must be equal to 6 (as MAC address is 6-byte long)
|
||||
* @param[in] addr An initializer list containing the values of type uint8_t representing the MAC address
|
||||
*/
|
||||
MacAddress(std::initializer_list<uint8_t> octets) : m_IsValid { octets.size() == sizeof(m_Address) }
|
||||
{
|
||||
if(m_IsValid)
|
||||
{
|
||||
#if _MSC_VER >= 1800
|
||||
std::copy(octets.begin(), octets.end(), stdext::checked_array_iterator<uint8_t*>(m_Address, 6));
|
||||
#else
|
||||
std::copy(octets.begin(), octets.end(), std::begin(m_Address));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
memset(m_Address, 0, sizeof(m_Address));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Overload of the comparison operator
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if addresses are equal, false otherwise
|
||||
*/
|
||||
bool operator==(const MacAddress& other) const { return memcmp(m_Address, other.m_Address, sizeof(m_Address)) == 0; }
|
||||
|
||||
/**
|
||||
* Overload of the not-equal operator
|
||||
* @param[in] other The object to compare with
|
||||
* @return True if addresses are not equal, false otherwise
|
||||
*/
|
||||
bool operator!=(const MacAddress& other) const { return !operator==(other); }
|
||||
|
||||
#if __cplusplus > 199711L || _MSC_VER >= 1800
|
||||
/**
|
||||
* Overload of the assignment operator
|
||||
*/
|
||||
MacAddress& operator=(std::initializer_list<uint8_t> octets)
|
||||
{
|
||||
m_IsValid = (octets.size() == sizeof m_Address);
|
||||
if(m_IsValid)
|
||||
{
|
||||
#if _MSC_VER >= 1800
|
||||
std::copy(octets.begin(), octets.end(), stdext::checked_array_iterator<uint8_t*>(m_Address, sizeof(m_Address)));
|
||||
#else
|
||||
std::copy(octets.begin(), octets.end(), std::begin(m_Address));
|
||||
#endif
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the pointer to raw data
|
||||
* @return The pointer to raw data
|
||||
*/
|
||||
const uint8_t* getRawData() const { return m_Address; }
|
||||
|
||||
/**
|
||||
* Get an indication whether the MAC address is valid. An address can be invalid if it was constructed from illegal input, for example:
|
||||
* invalid string
|
||||
* @return True if the address is valid, false otherwise
|
||||
*/
|
||||
bool isValid() const { return m_IsValid; }
|
||||
|
||||
/**
|
||||
* Returns a std::string representation of the address
|
||||
* @return A string representation of the address
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Allocates a byte array of length 6 and copies address value into it. Array deallocation is user responsibility
|
||||
* @param[in] arr A pointer to where array will be allocated
|
||||
*/
|
||||
void copyTo(uint8_t** arr) const
|
||||
{
|
||||
*arr = new uint8_t[sizeof(m_Address)];
|
||||
memcpy(*arr, m_Address, sizeof(m_Address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a pointer to an already allocated byte array and copies the address value to it.
|
||||
* This method assumes array allocated size is at least 6 (the size of a MAC address)
|
||||
* @param[in] arr A pointer to the array which address will be copied to
|
||||
*/
|
||||
void copyTo(uint8_t* arr) const { memcpy(arr, m_Address, sizeof(m_Address)); }
|
||||
|
||||
/**
|
||||
* A static value representing a zero value of MAC address, meaning address of value "00:00:00:00:00:00"
|
||||
*/
|
||||
static MacAddress Zero;
|
||||
|
||||
private:
|
||||
uint8_t m_Address[6];
|
||||
bool m_IsValid;
|
||||
void init(const char* addr);
|
||||
};
|
||||
|
||||
MacAddress::MacAddress(uint8_t firstOctest, uint8_t secondOctet, uint8_t thirdOctet, uint8_t fourthOctet, uint8_t fifthOctet, uint8_t sixthOctet)
|
||||
: m_IsValid(true)
|
||||
{
|
||||
m_Address[0] = firstOctest;
|
||||
m_Address[1] = secondOctet;
|
||||
m_Address[2] = thirdOctet;
|
||||
m_Address[3] = fourthOctet;
|
||||
m_Address[4] = fifthOctet;
|
||||
m_Address[5] = sixthOctet;
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const pcpp::MacAddress& macAddress)
|
||||
{
|
||||
os << macAddress.toString();
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif /* PCAPPP_MACADDRESS */
|
||||
126
pcappp/include/pcapplusplus/MplsLayer.h
Normal file
126
pcappp/include/pcapplusplus/MplsLayer.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#ifndef PACKETPP_MPLS_LAYER
|
||||
#define PACKETPP_MPLS_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class MplsLayer
|
||||
* Represents a MPLS (Multi-Protocol Label Switching) layer
|
||||
*/
|
||||
class MplsLayer : public Layer
|
||||
{
|
||||
private:
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct mpls_header
|
||||
{
|
||||
uint16_t hiLabel;
|
||||
uint8_t misc;
|
||||
uint8_t ttl;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
mpls_header* getMplsHeader() const { return (mpls_header*)m_Data; }
|
||||
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
MplsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = MPLS; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new MPLS header
|
||||
* @param[in] mplsLabel MPLS label
|
||||
* @param[in] ttl Time-to-leave value
|
||||
* @param[in] experimentalUseValue Experimental use value
|
||||
* @param[in] bottomOfStack Bottom-of-stack value which indicate whether the next layer will also be a MPLS label or not
|
||||
*/
|
||||
MplsLayer(uint32_t mplsLabel, uint8_t ttl, uint8_t experimentalUseValue, bool bottomOfStack);
|
||||
|
||||
virtual ~MplsLayer() {}
|
||||
|
||||
/**
|
||||
* @return TTL value of the MPLS header
|
||||
*/
|
||||
uint8_t getTTL() const { return getMplsHeader()->ttl; }
|
||||
|
||||
/**
|
||||
* Set the TTL value
|
||||
* @param[in] ttl The TTL value to set
|
||||
*/
|
||||
void setTTL(uint8_t ttl) { getMplsHeader()->ttl = ttl; }
|
||||
|
||||
/**
|
||||
* Get an indication whether the next layer is also be a MPLS label or not
|
||||
* @return True if it's the last MPLS layer, false otherwise
|
||||
*/
|
||||
bool isBottomOfStack() const;
|
||||
|
||||
/**
|
||||
* Set the bottom-of-stack bit in the MPLS label
|
||||
* @param[in] val Set or unset the bit
|
||||
*/
|
||||
void setBottomOfStack(bool val);
|
||||
|
||||
/**
|
||||
* @return The exp value (3 bits) of the MPLS label
|
||||
*/
|
||||
uint8_t getExperimentalUseValue() const;
|
||||
|
||||
/**
|
||||
* Set the exp value (3 bits) of the MPLS label
|
||||
* @param[in] val The exp value to set. val must be a valid number meaning between 0 and 7 (inclusive)
|
||||
* @return True if exp value was set successfully or false if val has invalid value
|
||||
*/
|
||||
bool setExperimentalUseValue(uint8_t val);
|
||||
|
||||
/**
|
||||
* @return The MPLS label value (20 bits)
|
||||
*/
|
||||
uint32_t getMplsLabel() const;
|
||||
|
||||
/**
|
||||
* Set the MPLS label (20 bits)
|
||||
* @param[in] label The label to set. label must be a valid number meaning between 0 and 0xFFFFF (inclusive)
|
||||
* @return True if label was set successfully or false if label has invalid value
|
||||
*/
|
||||
bool setMplsLabel(uint32_t label);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: IPv4Layer, IPv6Layer, MplsLayer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of MPLS header (4 bytes)
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(mpls_header); }
|
||||
|
||||
/**
|
||||
* Set/unset the bottom-of-stack bit according to next layer: if it's a MPLS layer then bottom-of-stack will be unset. If it's not a
|
||||
* MPLS layer this bit will be set
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_MPLS_LAYER */
|
||||
90
pcappp/include/pcapplusplus/NetworkUtils.h
Normal file
90
pcappp/include/pcapplusplus/NetworkUtils.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef PCAPPP_NETWORK_UTILS
|
||||
#define PCAPPP_NETWORK_UTILS
|
||||
|
||||
#include "MacAddress.h"
|
||||
#include "IpAddress.h"
|
||||
#include "PcapLiveDevice.h"
|
||||
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class NetworkUtils
|
||||
* This class bundles several network utilities that are very common and useful. These utilities use Pcap++ and Packet++ packet
|
||||
* crafting and processing capabilities. This class is a singleton and can be access by getInstance() only
|
||||
*/
|
||||
class NetworkUtils
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* The access method to the singleton
|
||||
* @return The singleton instance of this class
|
||||
*/
|
||||
static NetworkUtils& getInstance()
|
||||
{
|
||||
static NetworkUtils instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default timeout used for several utilities. Currently set to 5 seconds
|
||||
*/
|
||||
static const int DefaultTimeout;
|
||||
|
||||
/**
|
||||
* Resolve the MAC address for a given IPv4 address. It's done using the ARP protocol: send an ARP request and interpret the response
|
||||
* @param[in] ipAddr The IPv4 address to resolve MAC address to
|
||||
* @param[in] device The interface to send and receive the ARP packets on
|
||||
* @param[out] arpResponseTimeMS An output parameter that will contain the time in milliseconds that took the ARP response to arrive
|
||||
* @param[in] sourceMac An optional parameter to set the source MAC address that will be sent with the ARP request
|
||||
* if this parameter isn't set or set with MacAddress#Zero the MAC address of the interface will be used
|
||||
* @param[in] sourceIP An optional parameter to set the source IPv4 address that will be sent with the ARP request
|
||||
* if this parameter isn't set or set with IPv4Address#Zero the default IPv4 address of the interface will be used
|
||||
* @param[in] arpTimeout An optional parameter to set the timeout to wait for the ARP response to return.
|
||||
* If this parameter isn't set or set with a number smaller than 0, a default timeout of 5 seconds will be set
|
||||
* @return The resolved MAC address or MacAddress#Zero if an error occurred or address could not be resolved. Errors will be printed
|
||||
* to log
|
||||
*/
|
||||
MacAddress getMacAddress(IPv4Address ipAddr, PcapLiveDevice* device, double& arpResponseTimeMS,
|
||||
MacAddress sourceMac = MacAddress::Zero, IPv4Address sourceIP = IPv4Address::Zero, int arpTimeout = -1) const;
|
||||
|
||||
|
||||
/**
|
||||
* Resolve an IPv4 address for a given hostname. Resolving is done in multiple phases: first resolving the LAN gateway MAC address
|
||||
* (or default gateway if a gateway isn't provided) using ARP protocol (by using NetworkUtils#getMacAddress() ). Then a DNS request
|
||||
* is sent to a DNS server (if specified) or to the LAN gateway (if DNS server is not specified). The DNS response is decoded and
|
||||
* the IPv4 address is determined. In addition the method outputs the time it took the DNS response to arrive and the DNS TTL
|
||||
* written on the DNS response. If DNS response doesn't contain an IPv4 address resolving an IPv4Address#Zero will be returned.
|
||||
* @param[in] hostname The hostname to resolve
|
||||
* @param[in] device The interface to send and receive packets on
|
||||
* @param[out] dnsResponseTimeMS When method returns successfully will contain the time it took to receive the DNS response
|
||||
* (in milli-seconds)
|
||||
* @param[out] dnsTTL When method returns successfully will contain The DNS TTL written in the DNS response
|
||||
* @param[in] dnsTimeout An optional parameter to specify the timeout to wait for a DNS response. If not specified the default timeout
|
||||
* is 5 sec
|
||||
* @param[in] dnsServerIP An optional parameter to specify the DNS server IP to send the DNS request to. If not specified
|
||||
* or specified with IPv4Address#Zero the DNS request will be sent to the default DNS server configured in the system
|
||||
* @param[in] gatewayIP An optional parameter to specify the LAN gateway to send the DNS request through. If not specified
|
||||
* or specified with IPv4Address#Zero the interface's default gateway will be used
|
||||
* @return The resolved IPv4 address or IPv4Address#Zero if something went wrong (in this case an error will be printed to log)
|
||||
*/
|
||||
IPv4Address getIPv4Address(std::string hostname, PcapLiveDevice* device, double& dnsResponseTimeMS, uint32_t& dnsTTL,
|
||||
int dnsTimeout = -1, IPv4Address dnsServerIP = IPv4Address::Zero, IPv4Address gatewayIP = IPv4Address::Zero) const;
|
||||
|
||||
private:
|
||||
|
||||
// private c'tor
|
||||
NetworkUtils() {}
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_NETWORK_UTILS */
|
||||
628
pcappp/include/pcapplusplus/NtpLayer.h
Normal file
628
pcappp/include/pcapplusplus/NtpLayer.h
Normal file
@@ -0,0 +1,628 @@
|
||||
#ifndef PACKETPP_NTP_LAYER
|
||||
#define PACKETPP_NTP_LAYER
|
||||
|
||||
#include "Logger.h"
|
||||
#include "Layer.h"
|
||||
#include "IpAddress.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @class NtpLayer
|
||||
* Represents a NTP (Network Time Protocol) layer
|
||||
*
|
||||
* @brief The NTP packet consists of an integral number of 32-bit (4 octet) words in network byte order.
|
||||
* The packet format consists of three components: the header itself, one or more optional extension fields (for v4),
|
||||
* and an optional message authentication code (MAC). Currently the extension fields are not supported. The NTP header is:
|
||||
*
|
||||
* @verbatim
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|LI | VN |Mode | Stratum | Poll | Precision |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Root Delay |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Root Dispersion |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Reference ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
+ Reference Timestamp (64) +
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
+ Origin Timestamp (64) +
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
+ Receive Timestamp (64) +
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
+ Transmit Timestamp (64) +
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
. .
|
||||
. Extension Field 1 (variable, only v4) .
|
||||
. .
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
. .
|
||||
. Extension Field 1 (variable, only v4) .
|
||||
. .
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Key Identifier |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| dgst (128 for v4, 64 for v3) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@endverbatim
|
||||
*
|
||||
*/
|
||||
class NtpLayer : public Layer
|
||||
{
|
||||
private:
|
||||
#pragma pack(push, 1)
|
||||
struct ntp_header
|
||||
{
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/// 3-bit integer representing the mode
|
||||
uint8_t mode:3,
|
||||
/// 3-bit integer representing the NTP version number
|
||||
version:3,
|
||||
/// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in the last minute of the current month
|
||||
leapIndicator:2;
|
||||
#else
|
||||
/// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in the last minute of the current month
|
||||
uint8_t leapIndicator:2,
|
||||
/// 3-bit integer representing the NTP version number
|
||||
version:3,
|
||||
/// 3-bit integer representing the mode
|
||||
mode:3;
|
||||
#endif
|
||||
/// 8-bit integer representing the stratum
|
||||
uint8_t stratum;
|
||||
/// Total round-trip delay to the reference clock, in log2 seconds.
|
||||
int8_t pollInterval,
|
||||
/// 8-bit signed integer representing the precision of the system clock, in log2 seconds.
|
||||
precision;
|
||||
/// Total round-trip delay to the reference clock, in NTP short format.
|
||||
uint32_t rootDelay,
|
||||
/// Total dispersion to the reference clock, in NTP short format.
|
||||
rootDispersion,
|
||||
/// 32-bit code identifying the particular server or reference clock. The interpretation depends on the value in the stratum field.
|
||||
referenceIdentifier;
|
||||
/// Time when the system clock was last set or corrected, in NTP timestamp format.
|
||||
uint64_t referenceTimestamp,
|
||||
/// Time at the client when the request departed for the server, in NTP timestamp format.
|
||||
originTimestamp,
|
||||
/// Time at the client when the request departed for the server, in NTP timestamp format.
|
||||
receiveTimestamp,
|
||||
/// Time at the server when the response left for the client, in NTP timestamp format.
|
||||
transmitTimestamp;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ntp_v3_auth
|
||||
{
|
||||
/// An integer identifying the cryptographic key used to generate the message-authentication code
|
||||
uint32_t keyID;
|
||||
/// This is an integer identifying the cryptographic key used to generate the message-authentication code.
|
||||
uint8_t dgst[8]; // 64 bit DES based
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ntp_v4_auth_md5
|
||||
{
|
||||
/// 32-bit unsigned integer used by the client and server to designate a secret 128-bit MD5 key.
|
||||
uint32_t keyID;
|
||||
/// 128-bit MD5 hash
|
||||
uint8_t dgst[16];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ntp_v4_auth_sha1
|
||||
{
|
||||
/// 32-bit unsigned integer used by the client and server to designate a secret 160-bit SHA1 key.
|
||||
uint32_t keyID;
|
||||
/// 160-bit SHA1 hash
|
||||
uint8_t dgst[20];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
ntp_header *getNtpHeader() const { return (ntp_header *)m_Data; }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Warning of an impending leap second to be inserted or deleted in the last minute of the current month
|
||||
*/
|
||||
enum LeapIndicator
|
||||
{
|
||||
/// Normal, no leap second
|
||||
NoWarning = 0,
|
||||
/// Last minute of the day has 61 seconds
|
||||
Last61Secs,
|
||||
/// Last minute of the day has 59 seconds
|
||||
Last59Secs,
|
||||
/// Unknown (clock unsynchronized)
|
||||
Unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* Representing the NTP association modes
|
||||
*/
|
||||
enum Mode
|
||||
{
|
||||
/// Reserved variable
|
||||
Reserved = 0,
|
||||
/// Symmetrically active
|
||||
SymActive,
|
||||
/// Symmetrically passive
|
||||
SymPassive,
|
||||
/// Client mode
|
||||
Client,
|
||||
/// Server mode
|
||||
Server,
|
||||
/// Broadcasting mode
|
||||
Broadcast,
|
||||
/// NTP control messages
|
||||
Control,
|
||||
/// Reserved for private use
|
||||
PrivateUse
|
||||
};
|
||||
|
||||
/**
|
||||
* 32-bit code identifying the particular server or reference clock.
|
||||
* The interpretation depends on the value in the stratum field.
|
||||
*/
|
||||
enum ClockSource
|
||||
{
|
||||
// NTPv4
|
||||
|
||||
/// Geosynchronous Orbit Environment Satellite
|
||||
GOES = ('G') | ('O' << 8) | ('E' << 16) | ('S' << 24),
|
||||
/// Global Position System
|
||||
GPS = ('G') | ('P' << 8) | ('S' << 16),
|
||||
/// Galileo Positioning System
|
||||
GAL = ('G') | ('A' << 8) | ('L' << 16),
|
||||
/// Generic pulse-per-second
|
||||
PPS = ('P') | ('P' << 8) | ('S' << 16),
|
||||
/// Inter-Range Instrumentation Group
|
||||
IRIG = ('I') | ('R' << 8) | ('I' << 16) | ('G' << 24),
|
||||
/// LF Radio WWVB Ft. Collins, CO 60 kHz
|
||||
WWVB = ('W') | ('W' << 8) | ('V' << 16) | ('B' << 24),
|
||||
/// LF Radio DCF77 Mainflingen, DE 77.5 kHz
|
||||
DCF = ('D') | ('C' << 8) | ('F' << 16),
|
||||
/// LF Radio HBG Prangins, HB 75 kHz
|
||||
HBG = ('H') | ('B' << 8) | ('G' << 16),
|
||||
/// LF Radio MSF Anthorn, UK 60 kHz
|
||||
MSF = ('M') | ('S' << 8) | ('F' << 16),
|
||||
/// LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz
|
||||
JJY = ('J') | ('J' << 8) | ('Y' << 16),
|
||||
/// MF Radio LORAN C station, 100 kHz
|
||||
LORC = ('L') | ('O' << 8) | ('R' << 16) | ('C' << 24),
|
||||
/// MF Radio Allouis, FR 162 kHz
|
||||
TDF = ('T') | ('D' << 8) | ('F' << 16),
|
||||
/// HF Radio CHU Ottawa, Ontario
|
||||
CHU = ('C') | ('H' << 8) | ('U' << 16),
|
||||
/// HF Radio WWV Ft. Collins, CO
|
||||
WWV = ('W') | ('W' << 8) | ('V' << 16),
|
||||
/// HF Radio WWVH Kauai, HI
|
||||
WWVH = ('W') | ('W' << 8) | ('V' << 16) | ('H' << 24),
|
||||
/// NIST telephone modem
|
||||
NIST = ('N') | ('I' << 8) | ('S' << 16) | ('T' << 24),
|
||||
/// NIST telephone modem
|
||||
ACTS = ('A') | ('C' << 8) | ('T' << 16) | ('S' << 24),
|
||||
/// USNO telephone modem
|
||||
USNO = ('U') | ('S' << 8) | ('N' << 16) | ('O' << 24),
|
||||
/// European telephone modem
|
||||
PTB = ('P') | ('T' << 8) | ('B' << 16),
|
||||
/// Meinberg DCF77 with amplitude modulation (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
DCFa = ('D') | ('C' << 8) | ('F' << 16) | ('a' << 24),
|
||||
/// Meinberg DCF77 with phase modulation)/pseudo random phase modulation (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
DCFp = ('D') | ('C' << 8) | ('F' << 16) | ('p' << 24),
|
||||
/// Meinberg GPS (with shared memory access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
GPSs = ('G') | ('P' << 8) | ('S' << 16) | ('s' << 24),
|
||||
/// Meinberg GPS (with interrupt based access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
GPSi = ('G') | ('P' << 8) | ('S' << 16) | ('i' << 24),
|
||||
/// Meinberg GPS/GLONASS (with shared memory access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
GLNs = ('G') | ('L' << 8) | ('N' << 16) | ('s' << 24),
|
||||
/// Meinberg GPS/GLONASS (with interrupt based access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
GLNi = ('G') | ('L' << 8) | ('N' << 16) | ('i' << 24),
|
||||
/// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
LCL = ('L') | ('C' << 8) | ('L' << 16),
|
||||
/// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm)
|
||||
LOCL = ('L') | ('O' << 8) | ('C' << 16) | ('L' << 24),
|
||||
|
||||
// NTPv3
|
||||
|
||||
/// DCN routing protocol
|
||||
DCN = ('D') | ('C' << 8) | ('N' << 16),
|
||||
/// TSP time protocol
|
||||
TSP = ('T') | ('S' << 8) | ('P' << 16),
|
||||
/// Digital Time Service
|
||||
DTS = ('D') | ('T' << 8) | ('S' << 16),
|
||||
/// Atomic clock (calibrated)
|
||||
ATOM = ('A') | ('T' << 8) | ('O' << 16) | ('M' << 24),
|
||||
/// VLF radio (OMEGA, etc.)
|
||||
VLF = ('V') | ('L' << 8) | ('F' << 16)
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
NtpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = NTP; }
|
||||
|
||||
/**
|
||||
* Empty c'tor
|
||||
*/
|
||||
NtpLayer();
|
||||
|
||||
/**
|
||||
* @return The leap indicator
|
||||
*/
|
||||
LeapIndicator getLeapIndicator() const;
|
||||
|
||||
/**
|
||||
* Set the leap indicator
|
||||
*/
|
||||
void setLeapIndicator(LeapIndicator val);
|
||||
|
||||
/**
|
||||
* @return The version of NTP
|
||||
*/
|
||||
uint8_t getVersion() const;
|
||||
|
||||
/**
|
||||
* Set the version of NTP
|
||||
*/
|
||||
void setVersion(uint8_t val);
|
||||
|
||||
/**
|
||||
* @return The mode value
|
||||
*/
|
||||
Mode getMode() const;
|
||||
|
||||
/**
|
||||
* @return The mode as string
|
||||
*/
|
||||
std::string getModeString() const;
|
||||
|
||||
/**
|
||||
* Set the mode
|
||||
*/
|
||||
void setMode(Mode val);
|
||||
|
||||
/**
|
||||
* @return The value of stratum
|
||||
*/
|
||||
uint8_t getStratum() const;
|
||||
|
||||
/**
|
||||
* Set the value of stratum
|
||||
*/
|
||||
void setStratum(uint8_t val);
|
||||
|
||||
/**
|
||||
* @return The value of poll interval in log2 seconds
|
||||
*/
|
||||
int8_t getPollInterval() const;
|
||||
|
||||
/**
|
||||
* Set the value of poll interval
|
||||
* @param[in] val Poll interval in log2 seconds
|
||||
*/
|
||||
void setPollInterval(int8_t val);
|
||||
|
||||
/**
|
||||
* @return The value of poll interval in seconds
|
||||
*/
|
||||
double getPollIntervalInSecs() const;
|
||||
|
||||
/**
|
||||
* @return The value of precision in log2 seconds
|
||||
*/
|
||||
int8_t getPrecision() const;
|
||||
|
||||
/**
|
||||
* Set the value of precision
|
||||
* @param[in] val Precision in log2 seconds
|
||||
*/
|
||||
void setPrecision(int8_t val);
|
||||
|
||||
/**
|
||||
* @return The value of precision in seconds
|
||||
*/
|
||||
double getPrecisionInSecs() const;
|
||||
|
||||
/**
|
||||
* @return The value of root delay in NTP short format
|
||||
*/
|
||||
uint32_t getRootDelay() const;
|
||||
|
||||
/**
|
||||
* Set the value of root delay
|
||||
* @param[in] val Root delay in NTP short format
|
||||
*/
|
||||
void setRootDelay(uint32_t val);
|
||||
|
||||
/**
|
||||
* @return The value of root delay in seconds
|
||||
*/
|
||||
double getRootDelayInSecs() const;
|
||||
|
||||
/**
|
||||
* Set the value of root delay
|
||||
* @param[in] val Root delay in seconds
|
||||
*/
|
||||
void setRootDelayInSecs(double val);
|
||||
|
||||
/**
|
||||
* @return The value of root dispersion in NTP short format
|
||||
*/
|
||||
uint32_t getRootDispersion() const;
|
||||
|
||||
/**
|
||||
* Set the value of root delay
|
||||
* @param[in] val Root dispersion in NTP short format
|
||||
*/
|
||||
void setRootDispersion(uint32_t val);
|
||||
|
||||
/**
|
||||
* @return The value of root dispersion in seconds
|
||||
*/
|
||||
double getRootDispersionInSecs() const;
|
||||
|
||||
/**
|
||||
* Set the value of root dispersion
|
||||
* @param[in] val Root dispersion in seconds
|
||||
*/
|
||||
void setRootDispersionInSecs(double val);
|
||||
|
||||
/**
|
||||
* @return The value of reference identifier
|
||||
*/
|
||||
uint32_t getReferenceIdentifier() const;
|
||||
|
||||
/**
|
||||
* Set the value of reference identifier
|
||||
* @param[in] val Value of the reference identifier as IPv4 address
|
||||
*/
|
||||
void setReferenceIdentifier(IPv4Address val);
|
||||
|
||||
/**
|
||||
* Set the value of reference identifier
|
||||
* @param[in] val Value of the reference identifier as ClockSource
|
||||
*/
|
||||
void setReferenceIdentifier(ClockSource val);
|
||||
|
||||
/**
|
||||
* @return The value of reference identifier as a string. String representation of NTP clock source if stratum is 1,
|
||||
* IPv4 address or MD5 hash of first four octets of IPv6
|
||||
*/
|
||||
std::string getReferenceIdentifierString() const;
|
||||
|
||||
/**
|
||||
* @return The value of reference timestamp in NTP timestamp format
|
||||
*/
|
||||
uint64_t getReferenceTimestamp() const;
|
||||
|
||||
/**
|
||||
* Set the value of reference timestamp
|
||||
* @param[in] val Timestamp in NTP timestamp format
|
||||
*/
|
||||
void setReferenceTimestamp(uint64_t val);
|
||||
|
||||
/**
|
||||
* @return The value of reference timestamp in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
double getReferenceTimestampInSecs() const;
|
||||
|
||||
/**
|
||||
* Set the value of reference timestamp
|
||||
* @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
void setReferenceTimestampInSecs(double val);
|
||||
|
||||
/**
|
||||
* @return The reference timestamp value as readable string in ISO8601 format
|
||||
*/
|
||||
std::string getReferenceTimestampAsString();
|
||||
|
||||
/**
|
||||
* @return The value of origin timestamp in NTP timestamp format
|
||||
*/
|
||||
uint64_t getOriginTimestamp() const;
|
||||
|
||||
/**
|
||||
* Set the value of origin timestamp
|
||||
* @param[in] val Value in NTP timestamp format
|
||||
*/
|
||||
void setOriginTimestamp(uint64_t val);
|
||||
|
||||
/**
|
||||
* @return The value of origin timestamp in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
double getOriginTimestampInSecs() const;
|
||||
|
||||
/**
|
||||
* Set the value of origin timestamp
|
||||
* @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
void setOriginTimestampInSecs(double val);
|
||||
|
||||
/**
|
||||
* @return the origin timestamp value as readable string in ISO8601 format
|
||||
*/
|
||||
std::string getOriginTimestampAsString();
|
||||
|
||||
/**
|
||||
* @return The value of receive timestamp in NTP timestamp format
|
||||
*/
|
||||
uint64_t getReceiveTimestamp() const;
|
||||
|
||||
/**
|
||||
* Set the value of receive timestamp
|
||||
* @param[in] val Value in NTP timestamp format
|
||||
*/
|
||||
void setReceiveTimestamp(uint64_t val);
|
||||
|
||||
/**
|
||||
* @return The value of receive timestampin seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
double getReceiveTimestampInSecs() const;
|
||||
|
||||
/**
|
||||
* Set the value of receive timestamp
|
||||
* @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
void setReceiveTimestampInSecs(double val);
|
||||
|
||||
/**
|
||||
* @return The receive timestamp value as readable string in ISO8601 format
|
||||
*/
|
||||
std::string getReceiveTimestampAsString();
|
||||
|
||||
/**
|
||||
* @return The value of transmit timestamp in NTP timestamp format
|
||||
*/
|
||||
uint64_t getTransmitTimestamp() const;
|
||||
|
||||
/**
|
||||
* Set the value of transmit timestamp
|
||||
* @param[in] val Value in NTP timestamp format
|
||||
*/
|
||||
void setTransmitTimestamp(uint64_t val);
|
||||
|
||||
/**
|
||||
* @return The value of transmit timestamp in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
double getTransmitTimestampInSecs() const;
|
||||
|
||||
/**
|
||||
* Set the value of transmit timestamp
|
||||
* @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
void setTransmitTimestampInSecs(double val);
|
||||
|
||||
/**
|
||||
* @return The transmit timestamp value as readable string in ISO8601 format
|
||||
*/
|
||||
std::string getTransmitTimestampAsString();
|
||||
|
||||
/**
|
||||
* @return Returns the key identifier if exists, returns 0 on unsupported NTP version or key identifier not found
|
||||
*/
|
||||
uint32_t getKeyID() const;
|
||||
|
||||
/**
|
||||
* @return Get the digest value as hexadecimal string, empty string on unsupported version
|
||||
*/
|
||||
std::string getDigest() const;
|
||||
|
||||
/**
|
||||
* Convert NTP short format to seconds from the Unix Epoch
|
||||
*
|
||||
* @param[in] val Value in NTP short format
|
||||
* @return Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
static double convertFromShortFormat(const uint32_t val);
|
||||
|
||||
/**
|
||||
* Convert NTP timestamp format to seconds from the Unix Epoch
|
||||
*
|
||||
* @param[in] val Value in NTP timestamp format
|
||||
* @return Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
*/
|
||||
static double convertFromTimestampFormat(const uint64_t val);
|
||||
|
||||
/**
|
||||
* Convert seconds from the Unix Epoch to NTP short format
|
||||
*
|
||||
* @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
* @return Value in NTP short format
|
||||
*/
|
||||
static uint32_t convertToShortFormat(const double val);
|
||||
|
||||
/**
|
||||
* Convert seconds from the Unix Epoch to NTP timestamp format
|
||||
*
|
||||
* @param[in] val Value in seconds from Unix Epoch (1 Jan 1970)
|
||||
* @return Value in NTP timestamp format
|
||||
*/
|
||||
static uint64_t convertToTimestampFormat(const double val);
|
||||
|
||||
/**
|
||||
* A static method to convert timestamp value to ISO8601 date time format
|
||||
* @param[in] timestamp Value in seconds from the Unix Epoch
|
||||
* @return std::string ISO8601 formatted string
|
||||
*/
|
||||
static std::string convertToIsoFormat(const double timestamp);
|
||||
|
||||
/**
|
||||
* A static method to convert timestamp value to ISO8601 date time format
|
||||
* @param[in] timestampInNTPformat Value in NTP timestamp format
|
||||
* @return std::string ISO8601 formatted string
|
||||
*/
|
||||
static std::string convertToIsoFormat(const uint64_t timestampInNTPformat);
|
||||
|
||||
/**
|
||||
* A static method that takes a byte array and detects whether it is a NTP message
|
||||
* @param[in] data A byte array
|
||||
* @param[in] dataSize The byte array size (in bytes)
|
||||
* @return True if the data is identified as NTP message
|
||||
*/
|
||||
static bool isDataValid(const uint8_t *data, size_t dataSize);
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as NTP
|
||||
* @param[in] port The port number to be checked
|
||||
*/
|
||||
static bool isNTPPort(uint16_t port) { return port == 123; }
|
||||
|
||||
// overridden methods
|
||||
|
||||
/// Parses the next layer. NTP is the always last so does nothing for this layer
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return Get the size of the layer (Including the extension and authentication fields if exists)
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
/// Does nothing for this layer
|
||||
void computeCalculateFields() {}
|
||||
|
||||
/**
|
||||
* @return The OSI layer level of NTP (Application Layer).
|
||||
*/
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
/**
|
||||
* @return Returns the protocol info as readable string
|
||||
*/
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_NTP_LAYER */
|
||||
92
pcappp/include/pcapplusplus/NullLoopbackLayer.h
Normal file
92
pcappp/include/pcapplusplus/NullLoopbackLayer.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef PACKETPP_NULL_LOOPBACK_LAYER
|
||||
#define PACKETPP_NULL_LOOPBACK_LAYER
|
||||
|
||||
/// @file
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/** IPv4 protocol **/
|
||||
#define PCPP_BSD_AF_INET 2
|
||||
/** XEROX NS protocols */
|
||||
#define PCPP_BSD_AF_NS 6
|
||||
/** ISO */
|
||||
#define PCPP_BSD_AF_ISO 7
|
||||
/** AppleTalk */
|
||||
#define PCPP_BSD_AF_APPLETALK 16
|
||||
/** IPX */
|
||||
#define PCPP_BSD_AF_IPX 23
|
||||
/** OpenBSD (and probably NetBSD), BSD/OS IPv6 */
|
||||
#define PCPP_BSD_AF_INET6_BSD 24
|
||||
/** FreeBSD IPv6 */
|
||||
#define PCPP_BSD_AF_INET6_FREEBSD 28
|
||||
/** Darwin IPv6 */
|
||||
#define PCPP_BSD_AF_INET6_DARWIN 30
|
||||
|
||||
/**
|
||||
* @class NullLoopbackLayer
|
||||
* Represents a NULL/Loopback layer
|
||||
*/
|
||||
class NullLoopbackLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @param[in] dataLen Size of the data in bytes
|
||||
* @param[in] packet A pointer to the Packet instance where layer will be stored in
|
||||
*/
|
||||
NullLoopbackLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = NULL_LOOPBACK; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new Null/Loopback header
|
||||
* @param[in] family The family protocol to set
|
||||
*/
|
||||
NullLoopbackLayer(uint32_t family);
|
||||
|
||||
/**
|
||||
* A destructor for this layer (does nothing)
|
||||
*/
|
||||
~NullLoopbackLayer() {}
|
||||
|
||||
/**
|
||||
* @return The protocol family in this layer
|
||||
*/
|
||||
uint32_t getFamily() const;
|
||||
|
||||
/**
|
||||
* Set a protocol family
|
||||
* @param[in] family The family protocol to set
|
||||
*/
|
||||
void setFamily(uint32_t family);
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Identifies the next layers by family:
|
||||
* - for ::PCPP_BSD_AF_INET the next layer is IPv4Layer
|
||||
* - for ::PCPP_BSD_AF_INET6_BSD, ::PCPP_BSD_AF_INET6_FREEBSD, ::PCPP_BSD_AF_INET6_DARWIN the next layer is IPv6Layer
|
||||
* - for other values the next layer in PayloadLayer (unknown protocol)
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of Null/Loopback header = 4B
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(uint32_t); }
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_NULL_LOOPBACK_LAYER */
|
||||
708
pcappp/include/pcapplusplus/PPPoELayer.h
Normal file
708
pcappp/include/pcapplusplus/PPPoELayer.h
Normal file
@@ -0,0 +1,708 @@
|
||||
#ifndef PACKETPP_PPPOE_LAYER
|
||||
#define PACKETPP_PPPOE_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct pppoe_header
|
||||
* Represents an PPPoE protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct pppoe_header
|
||||
{
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/** PPPoE version */
|
||||
uint8_t version:4,
|
||||
/** PPPoE type */
|
||||
type:4;
|
||||
/** PPPoE code */
|
||||
uint8_t code;
|
||||
#else
|
||||
/** PPPoE version */
|
||||
uint16_t version:4,
|
||||
/** PPPoE type */
|
||||
type:4,
|
||||
/** PPPoE code */
|
||||
code:8;
|
||||
#endif
|
||||
/** PPPoE session ID (relevant for PPPoE session packets only) */
|
||||
uint16_t sessionId;
|
||||
/** Length (in bytes) of payload, not including the PPPoE header */
|
||||
uint16_t payloadLength;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @class PPPoELayer
|
||||
* An abstract class that describes the PPPoE protocol. Contains common data and logic of the two types of PPPoE packets: PPPoE session
|
||||
* and PPPoE discovery
|
||||
*/
|
||||
class PPPoELayer : public Layer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* PPPoE possible codes
|
||||
*/
|
||||
enum PPPoECode
|
||||
{
|
||||
/** PPPoE session code */
|
||||
PPPOE_CODE_SESSION = 0x00,
|
||||
/** PPPoE discovery PADO */
|
||||
PPPOE_CODE_PADO = 0x07,
|
||||
/** PPPoE discovery PADI */
|
||||
PPPOE_CODE_PADI = 0x09,
|
||||
/** PPPoE discovery PADG */
|
||||
PPPOE_CODE_PADG = 0x0a,
|
||||
/** PPPoE discovery PADC */
|
||||
PPPOE_CODE_PADC = 0x0b,
|
||||
/** PPPoE discovery PADQ */
|
||||
PPPOE_CODE_PADQ = 0x0c,
|
||||
/** PPPoE discovery PADR */
|
||||
PPPOE_CODE_PADR = 0x19,
|
||||
/** PPPoE discovery PADS */
|
||||
PPPOE_CODE_PADS = 0x65,
|
||||
/** PPPoE discovery PADT */
|
||||
PPPOE_CODE_PADT = 0xa7,
|
||||
/** PPPoE discovery PADM */
|
||||
PPPOE_CODE_PADM = 0xd3,
|
||||
/** PPPoE discovery PADN */
|
||||
PPPOE_CODE_PADN = 0xd4
|
||||
};
|
||||
|
||||
~PPPoELayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the PPPoE header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the pppoe_header
|
||||
*/
|
||||
pppoe_header* getPPPoEHeader() const { return (pppoe_header*)m_Data; }
|
||||
|
||||
// abstract methods implementation
|
||||
|
||||
/**
|
||||
* Calculate @ref pppoe_header#payloadLength field
|
||||
*/
|
||||
virtual void computeCalculateFields();
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
|
||||
protected:
|
||||
|
||||
// protected c'tor as this class shouldn't be instantiated
|
||||
PPPoELayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { }
|
||||
|
||||
// protected c'tor as this class shouldn't be instantiated
|
||||
PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId, size_t additionalBytesToAllocate = 0);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PPPoESessionLayer
|
||||
* Describes the PPPoE session protocol
|
||||
*/
|
||||
class PPPoESessionLayer : public PPPoELayer
|
||||
{
|
||||
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 pppoe_header)
|
||||
* @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
|
||||
*/
|
||||
PPPoESessionLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : PPPoELayer(data, dataLen, prevLayer, packet) { m_Protocol = PPPoESession; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new PPPoE Session header with version, type and session ID
|
||||
* @param[in] version PPPoE version
|
||||
* @param[in] type PPPoE type
|
||||
* @param[in] sessionId PPPoE session ID
|
||||
* @param[in] pppNextProtocol The next protocol to come after the PPPoE session header. Should be one of the PPP_* macros listed below
|
||||
*/
|
||||
PPPoESessionLayer(uint8_t version, uint8_t type, uint16_t sessionId, uint16_t pppNextProtocol) : PPPoELayer(version, type, PPPoELayer::PPPOE_CODE_SESSION, sessionId, sizeof(uint16_t)) { setPPPNextProtocol(pppNextProtocol); }
|
||||
|
||||
virtual ~PPPoESessionLayer() {}
|
||||
|
||||
/**
|
||||
* @return The protocol after the PPPoE session header. The return value is one of the PPP_* macros listed below. This method is also
|
||||
* used when parsing a packet (this way we know which layer comes after the PPPoE session)
|
||||
*/
|
||||
uint16_t getPPPNextProtocol() const;
|
||||
|
||||
/**
|
||||
* Set the field that describes which header comes after the PPPoE session header
|
||||
* @param[in] nextProtocol The protocol value. Should be one of the PPP_* macros listed below
|
||||
*/
|
||||
void setPPPNextProtocol(uint16_t nextProtocol);
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of byte stream of a packet
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @return True if the data is valid and can represent a PPPoES packet
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// abstract methods implementation
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
virtual void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of @ref pppoe_header
|
||||
*/
|
||||
virtual size_t getHeaderLen() const { return sizeof(pppoe_header) + sizeof(uint16_t); }
|
||||
|
||||
virtual std::string toString() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class PPPoEDiscoveryLayer
|
||||
* Describes the PPPoE discovery protocol
|
||||
*/
|
||||
class PPPoEDiscoveryLayer : public PPPoELayer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* PPPoE tag types
|
||||
*/
|
||||
enum PPPoETagTypes
|
||||
{
|
||||
/** End-Of-List tag type*/
|
||||
PPPOE_TAG_EOL = 0x0000,
|
||||
/** Service-Name tag type*/
|
||||
PPPOE_TAG_SVC_NAME = 0x0101,
|
||||
/** AC-Name tag type*/
|
||||
PPPOE_TAG_AC_NAME = 0x0102,
|
||||
/** Host-Uniq tag type*/
|
||||
PPPOE_TAG_HOST_UNIQ = 0x0103,
|
||||
/** AC-Cookie tag type*/
|
||||
PPPOE_TAG_AC_COOKIE = 0x0104,
|
||||
/** Vendor-Specific tag type*/
|
||||
PPPOE_TAG_VENDOR = 0x0105,
|
||||
/** Credits tag type*/
|
||||
PPPOE_TAG_CREDITS = 0x0106,
|
||||
/** Metrics tag type*/
|
||||
PPPOE_TAG_METRICS = 0x0107,
|
||||
/** Sequence Number tag type */
|
||||
PPPOE_TAG_SEQ_NUM = 0x0108,
|
||||
/** Credit Scale Factor tag type */
|
||||
PPPOE_TAG_CRED_SCALE = 0x0109,
|
||||
/** Relay-Session-Id tag type */
|
||||
PPPOE_TAG_RELAY_ID = 0x0110,
|
||||
/** HURL tag type */
|
||||
PPPOE_TAG_HURL = 0x0111,
|
||||
/** MOTM tag type */
|
||||
PPPOE_TAG_MOTM = 0x0112,
|
||||
/** PPP-Max-Payload tag type */
|
||||
PPPOE_TAG_MAX_PAYLD = 0x0120,
|
||||
/** IP_Route_Add tag type */
|
||||
PPPOE_TAG_IP_RT_ADD = 0x0121,
|
||||
/** Service-Name-Error tag type */
|
||||
PPPOE_TAG_SVC_ERR = 0x0201,
|
||||
/** AC-System-Error tag type */
|
||||
PPPOE_TAG_AC_ERR = 0x0202,
|
||||
/** Generic-Error tag type */
|
||||
PPPOE_TAG_GENERIC_ERR= 0x0203
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PPPoETag
|
||||
* Represents a PPPoE tag and its data
|
||||
*/
|
||||
class PPPoETag : public TLVRecord<uint16_t, uint16_t>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A c'tor that gets a pointer to the tag raw data (byte array)
|
||||
* @param[in] tagRawData A pointer to the tag raw data
|
||||
*/
|
||||
PPPoETag(uint8_t* tagRawData) : TLVRecord(tagRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
virtual ~PPPoETag() { }
|
||||
|
||||
/**
|
||||
* @return The tag type converted to PPPoEDiscoveryLayer#PPPoETagTypes enum
|
||||
*/
|
||||
PPPoEDiscoveryLayer::PPPoETagTypes getType() const;
|
||||
|
||||
/**
|
||||
* Retrieve the tag data as string. Relevant only if the tag value is indeed a string
|
||||
* @return The tag data as string
|
||||
*/
|
||||
std::string getValueAsString() const
|
||||
{
|
||||
size_t dataSize = getDataSize();
|
||||
if (dataSize < 1)
|
||||
return "";
|
||||
|
||||
return std::string((const char*)m_Data->recordValue, dataSize);
|
||||
}
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const;
|
||||
|
||||
size_t getDataSize() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PPPoETagBuilder
|
||||
* A class for building PPPoE Tags. This builder receives the tag parameters in its c'tor,
|
||||
* builds the PPPoE Tag raw buffer and provides a build() method to get a PPPoETag object out of it
|
||||
*/
|
||||
class PPPoETagBuilder : public TLVRecordBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for building a PPPoE Tag which has no value (tag len is zero). The PPPoETag object can later
|
||||
* be retrieved by calling build()
|
||||
* @param[in] tagType Tag type
|
||||
*/
|
||||
PPPoETagBuilder(PPPoETagTypes tagType) :
|
||||
TLVRecordBuilder(static_cast<uint16_t>(tagType), NULL, 0) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building a PPPoE Tag which has a 4-byte value. The PPPoETag object can later
|
||||
* be retrieved by calling build()
|
||||
* @param[in] tagType Tag type
|
||||
* @param[in] tagValue The tag's 4-byte value
|
||||
*/
|
||||
PPPoETagBuilder(PPPoETagTypes tagType, uint32_t tagValue) :
|
||||
TLVRecordBuilder(static_cast<uint16_t>(tagType), tagValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building a PPPoE Tag which has some arbitrary value. The PPPoETag object can later
|
||||
* be retrieved by calling build()
|
||||
* @param[in] tagType Tag type
|
||||
* @param[in] tagValue A byte array that contains the tag data
|
||||
* @param[in] tagValueLen The length of the value byte array
|
||||
*/
|
||||
PPPoETagBuilder(PPPoETagTypes tagType, uint8_t* tagValue, uint8_t tagValueLen) :
|
||||
TLVRecordBuilder(static_cast<uint16_t>(tagType), tagValue, tagValueLen) { }
|
||||
|
||||
/**
|
||||
* Build the PPPoETag object out of the parameters defined in the c'tor
|
||||
* @return The PPPoETag object
|
||||
*/
|
||||
PPPoETag build() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 pppoe_header)
|
||||
* @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
|
||||
*/
|
||||
PPPoEDiscoveryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : PPPoELayer(data, dataLen, prevLayer, packet) { m_Protocol = PPPoEDiscovery; m_DataLen = getHeaderLen(); }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new PPPoE Discovery header with version, type, PPPoE code and session ID
|
||||
* @param[in] version PPPoE version
|
||||
* @param[in] type PPPoE type
|
||||
* @param[in] code PPPoE code enum
|
||||
* @param[in] sessionId PPPoE session ID
|
||||
*/
|
||||
PPPoEDiscoveryLayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId) : PPPoELayer(version, type, code, sessionId) { m_Protocol = PPPoEDiscovery; }
|
||||
|
||||
/**
|
||||
* Get a PPPoE Tag by tag type.
|
||||
* @param[in] tagType The type of the tag to search
|
||||
* @return A PPPoETag object that contains the first tag that matches this type, or logical NULL
|
||||
* (PPPoETag#isNull() == true) if no such tag found
|
||||
*/
|
||||
PPPoETag getTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) const;
|
||||
|
||||
/**
|
||||
* @return The first tag in the PPPoE discovery layer. If the current layer contains no tags the returned value will contain
|
||||
* a logical NULL (PPPoETag#isNull() == true)
|
||||
*/
|
||||
PPPoETag getFirstTag() const;
|
||||
|
||||
/**
|
||||
* Get the tag that comes right after the "tag" parameter. If the given tag is the last one, the returned value
|
||||
* will contain a logical NULL (PPPoETag#isNull() == true)
|
||||
* @param[in] tag A given tag
|
||||
* @return A PPPoETag object containing the tag that comes next, or logical NULL if the given
|
||||
* tag: (1) was the last one; (2) contains a logical NULL or (3) doesn't belong to this packet
|
||||
*/
|
||||
PPPoETag getNextTag(const PPPoETag& tag) const;
|
||||
|
||||
/**
|
||||
* @return The number of tags in this layer
|
||||
*/
|
||||
int getTagCount() const;
|
||||
|
||||
/**
|
||||
* Add a new PPPoE Tag at the end of the layer
|
||||
* @param[in] tagBuilder A PPPoETagBuilder object that contains the requested tag data to add
|
||||
* @return A PPPoETag object containing the newly added PPPoE Tag data or logical NULL
|
||||
* (PPPoETag#isNull() == true) if addition failed
|
||||
*/
|
||||
PPPoETag addTag(const PPPoETagBuilder& tagBuilder);
|
||||
|
||||
/**
|
||||
* Add a new PPPoE Tag after an existing one
|
||||
* @param[in] tagBuilder A PPPoETagBuilder object that contains the requested tag data to add
|
||||
* @param[in] prevTagType The PPPoE Tag which the newly added tag will come after
|
||||
* @return A PPPoETag object containing the newly added PPPoE Tag data or logical NULL
|
||||
* (PPPoETag#isNull() == true) if addition failed
|
||||
*/
|
||||
PPPoETag addTagAfter(const PPPoETagBuilder& tagBuilder, PPPoETagTypes prevTagType);
|
||||
|
||||
/**
|
||||
* Remove an existing tag. Tag will be found by the tag type
|
||||
* @param[in] tagType The tag type to remove
|
||||
* @return True if tag was removed or false if tag wasn't found or if tag removal failed (in each case a proper error will be written
|
||||
* to log)
|
||||
*/
|
||||
bool removeTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType);
|
||||
|
||||
/**
|
||||
* Remove all tags in this layer
|
||||
* @return True if all tags were successfully or false if removal failed for some reason (a proper error will be written to log)
|
||||
*/
|
||||
bool removeAllTags();
|
||||
|
||||
/**
|
||||
* A static method that validates the input data
|
||||
* @param[in] data The pointer to the beginning of byte stream of a packet
|
||||
* @param[in] dataLen The length of the byte stream
|
||||
* @return True if the data is valid and can represent a PPPoED packet
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// abstract methods implementation
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (PPPoE discovery is always the last layer)
|
||||
*/
|
||||
virtual void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return The header length which is size of strcut pppoe_header plus the total size of tags
|
||||
*/
|
||||
virtual size_t getHeaderLen() const;
|
||||
|
||||
virtual std::string toString() const { return "PPP-over-Ethernet Discovery (" + codeToString((PPPoELayer::PPPoECode)getPPPoEHeader()->code) + ")"; }
|
||||
|
||||
private:
|
||||
TLVRecordReader<PPPoETag> m_TagReader;
|
||||
|
||||
PPPoETag addTagAt(const PPPoETagBuilder& tagBuilder, int offset);
|
||||
|
||||
uint8_t* getTagBasePtr() const { return m_Data + sizeof(pppoe_header); }
|
||||
|
||||
std::string codeToString(PPPoECode code) const;
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool PPPoESessionLayer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
return dataLen >= sizeof(pppoe_header) + sizeof(uint16_t);
|
||||
}
|
||||
|
||||
bool PPPoEDiscoveryLayer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
return dataLen >= sizeof(pppoe_header);
|
||||
}
|
||||
|
||||
// Copied from Wireshark: ppptypes.h
|
||||
|
||||
/** Padding Protocol */
|
||||
#define PCPP_PPP_PADDING 0x1
|
||||
/** ROHC small-CID */
|
||||
#define PCPP_PPP_ROHC_SCID 0x3
|
||||
/** ROHC large-CID */
|
||||
#define PCPP_PPP_ROHC_LCID 0x5
|
||||
/** Internet Protocol version 4 */
|
||||
#define PCPP_PPP_IP 0x21
|
||||
/** OSI Network Layer */
|
||||
#define PCPP_PPP_OSI 0x23
|
||||
/** Xerox NS IDP */
|
||||
#define PCPP_PPP_XNSIDP 0x25
|
||||
/** DECnet Phase IV */
|
||||
#define PCPP_PPP_DEC4 0x27
|
||||
/** AppleTalk */
|
||||
#define PCPP_PPP_AT 0x29
|
||||
/** Novell IPX */
|
||||
#define PCPP_PPP_IPX 0x2b
|
||||
/** Van Jacobson Compressed TCP/IP */
|
||||
#define PCPP_PPP_VJC_COMP 0x2d
|
||||
/** Van Jacobson Uncompressed TCP/IP */
|
||||
#define PCPP_PPP_VJC_UNCOMP 0x2f
|
||||
/** Bridging PDU */
|
||||
#define PCPP_PPP_BCP 0x31
|
||||
/** Stream Protocol (ST-II) */
|
||||
#define PCPP_PPP_ST 0x33
|
||||
/** Banyan Vines */
|
||||
#define PCPP_PPP_VINES 0x35
|
||||
/** AppleTalk EDDP */
|
||||
#define PCPP_PPP_AT_EDDP 0x39
|
||||
/** AppleTalk SmartBuffered */
|
||||
#define PCPP_PPP_AT_SB 0x3b
|
||||
/** Multi-Link */
|
||||
#define PCPP_PPP_MP 0x3d
|
||||
/** NETBIOS Framing */
|
||||
#define PCPP_PPP_NB 0x3f
|
||||
/** Cisco Systems */
|
||||
#define PCPP_PPP_CISCO 0x41
|
||||
/** Ascom Timeplex */
|
||||
#define PCPP_PPP_ASCOM 0x43
|
||||
/** Fujitsu Link Backup and Load Balancing */
|
||||
#define PCPP_PPP_LBLB 0x45
|
||||
/** DCA Remote Lan */
|
||||
#define PCPP_PPP_RL 0x47
|
||||
/** Serial Data Transport Protocol */
|
||||
#define PCPP_PPP_SDTP 0x49
|
||||
/** SNA over 802.2 */
|
||||
#define PCPP_PPP_LLC 0x4b
|
||||
/** SNA */
|
||||
#define PCPP_PPP_SNA 0x4d
|
||||
/** IPv6 Header Compression */
|
||||
#define PCPP_PPP_IPV6HC 0x4f
|
||||
/** KNX Bridging Data */
|
||||
#define PCPP_PPP_KNX 0x51
|
||||
/** Encryption */
|
||||
#define PCPP_PPP_ENCRYPT 0x53
|
||||
/** Individual Link Encryption */
|
||||
#define PCPP_PPP_ILE 0x55
|
||||
/** Internet Protocol version 6 */
|
||||
#define PCPP_PPP_IPV6 0x57
|
||||
/** PPP Muxing */
|
||||
#define PCPP_PPP_MUX 0x59
|
||||
/** Vendor-Specific Network Protocol (VSNP) */
|
||||
#define PCPP_PPP_VSNP 0x5b
|
||||
/** TRILL Network Protocol (TNP) */
|
||||
#define PCPP_PPP_TNP 0x5d
|
||||
/** RTP IPHC Full Header */
|
||||
#define PCPP_PPP_RTP_FH 0x61
|
||||
/** RTP IPHC Compressed TCP */
|
||||
#define PCPP_PPP_RTP_CTCP 0x63
|
||||
/** RTP IPHC Compressed Non TCP */
|
||||
#define PCPP_PPP_RTP_CNTCP 0x65
|
||||
/** RTP IPHC Compressed UDP 8 */
|
||||
#define PCPP_PPP_RTP_CUDP8 0x67
|
||||
/** RTP IPHC Compressed RTP 8 */
|
||||
#define PCPP_PPP_RTP_CRTP8 0x69
|
||||
/** Stampede Bridging */
|
||||
#define PCPP_PPP_STAMPEDE 0x6f
|
||||
/** MP+ Protocol */
|
||||
#define PCPP_PPP_MPPLUS 0x73
|
||||
/** NTCITS IPI */
|
||||
#define PCPP_PPP_NTCITS_IPI 0xc1
|
||||
/** Single link compression in multilink */
|
||||
#define PCPP_PPP_ML_SLCOMP 0xfb
|
||||
/** Compressed datagram */
|
||||
#define PCPP_PPP_COMP 0xfd
|
||||
/** 802.1d Hello Packets */
|
||||
#define PCPP_PPP_STP_HELLO 0x0201
|
||||
/** IBM Source Routing BPDU */
|
||||
#define PCPP_PPP_IBM_SR 0x0203
|
||||
/** DEC LANBridge100 Spanning Tree */
|
||||
#define PCPP_PPP_DEC_LB 0x0205
|
||||
/** Cisco Discovery Protocol */
|
||||
#define PCPP_PPP_CDP 0x0207
|
||||
/** Netcs Twin Routing */
|
||||
#define PCPP_PPP_NETCS 0x0209
|
||||
/** STP - Scheduled Transfer Protocol */
|
||||
#define PCPP_PPP_STP 0x020b
|
||||
/** EDP - Extreme Discovery Protocol */
|
||||
#define PCPP_PPP_EDP 0x020d
|
||||
/** Optical Supervisory Channel Protocol */
|
||||
#define PCPP_PPP_OSCP 0x0211
|
||||
/** Optical Supervisory Channel Protocol */
|
||||
#define PCPP_PPP_OSCP2 0x0213
|
||||
/** Luxcom */
|
||||
#define PCPP_PPP_LUXCOM 0x0231
|
||||
/** Sigma Network Systems */
|
||||
#define PCPP_PPP_SIGMA 0x0233
|
||||
/** Apple Client Server Protocol */
|
||||
#define PCPP_PPP_ACSP 0x0235
|
||||
/** MPLS Unicast */
|
||||
#define PCPP_PPP_MPLS_UNI 0x0281
|
||||
/** MPLS Multicast */
|
||||
#define PCPP_PPP_MPLS_MULTI 0x0283
|
||||
/** IEEE p1284.4 standard - data packets */
|
||||
#define PCPP_PPP_P12844 0x0285
|
||||
/** ETSI TETRA Network Protocol Type 1 */
|
||||
#define PCPP_PPP_TETRA 0x0287
|
||||
/** Multichannel Flow Treatment Protocol */
|
||||
#define PCPP_PPP_MFTP 0x0289
|
||||
/** RTP IPHC Compressed TCP No Delta */
|
||||
#define PCPP_PPP_RTP_CTCPND 0x2063
|
||||
/** RTP IPHC Context State */
|
||||
#define PCPP_PPP_RTP_CS 0x2065
|
||||
/** RTP IPHC Compressed UDP 16 */
|
||||
#define PCPP_PPP_RTP_CUDP16 0x2067
|
||||
/** RTP IPHC Compressed RTP 16 */
|
||||
#define PCPP_PPP_RTP_CRDP16 0x2069
|
||||
/** Cray Communications Control Protocol */
|
||||
#define PCPP_PPP_CCCP 0x4001
|
||||
/** CDPD Mobile Network Registration Protocol */
|
||||
#define PCPP_PPP_CDPD_MNRP 0x4003
|
||||
/** Expand accelerator protocol */
|
||||
#define PCPP_PPP_EXPANDAP 0x4005
|
||||
/** ODSICP NCP */
|
||||
#define PCPP_PPP_ODSICP 0x4007
|
||||
/** DOCSIS DLL */
|
||||
#define PCPP_PPP_DOCSIS 0x4009
|
||||
/** Cetacean Network Detection Protocol */
|
||||
#define PCPP_PPP_CETACEANNDP 0x400b
|
||||
/** Stacker LZS */
|
||||
#define PCPP_PPP_LZS 0x4021
|
||||
/** RefTek Protocol */
|
||||
#define PCPP_PPP_REFTEK 0x4023
|
||||
/** Fibre Channel */
|
||||
#define PCPP_PPP_FC 0x4025
|
||||
/** EMIT Protocols */
|
||||
#define PCPP_PPP_EMIT 0x4027
|
||||
/** Vendor-Specific Protocol (VSP) */
|
||||
#define PCPP_PPP_VSP 0x405b
|
||||
/** TRILL Link State Protocol (TLSP) */
|
||||
#define PCPP_PPP_TLSP 0x405d
|
||||
/** Internet Protocol Control Protocol */
|
||||
#define PCPP_PPP_IPCP 0x8021
|
||||
/** OSI Network Layer Control Protocol */
|
||||
#define PCPP_PPP_OSINLCP 0x8023
|
||||
/** Xerox NS IDP Control Protocol */
|
||||
#define PCPP_PPP_XNSIDPCP 0x8025
|
||||
/** DECnet Phase IV Control Protocol */
|
||||
#define PCPP_PPP_DECNETCP 0x8027
|
||||
/** AppleTalk Control Protocol */
|
||||
#define PCPP_PPP_ATCP 0x8029
|
||||
/** Novell IPX Control Protocol */
|
||||
#define PCPP_PPP_IPXCP 0x802b
|
||||
/** Bridging NCP */
|
||||
#define PCPP_PPP_BRIDGENCP 0x8031
|
||||
/** Stream Protocol Control Protocol */
|
||||
#define PCPP_PPP_SPCP 0x8033
|
||||
/** Banyan Vines Control Protocol */
|
||||
#define PCPP_PPP_BVCP 0x8035
|
||||
/** Multi-Link Control Protocol */
|
||||
#define PCPP_PPP_MLCP 0x803d
|
||||
/** NETBIOS Framing Control Protocol */
|
||||
#define PCPP_PPP_NBCP 0x803f
|
||||
/** Cisco Systems Control Protocol */
|
||||
#define PCPP_PPP_CISCOCP 0x8041
|
||||
/** Ascom Timeplex Control Protocol (?) */
|
||||
#define PCPP_PPP_ASCOMCP 0x8043
|
||||
/** Fujitsu LBLB Control Protocol */
|
||||
#define PCPP_PPP_LBLBCP 0x8045
|
||||
/** DCA Remote Lan Network Control Protocol */
|
||||
#define PCPP_PPP_RLNCP 0x8047
|
||||
/** Serial Data Control Protocol */
|
||||
#define PCPP_PPP_SDCP 0x8049
|
||||
/** SNA over 802.2 Control Protocol */
|
||||
#define PCPP_PPP_LLCCP 0x804b
|
||||
/** SNA Control Protocol */
|
||||
#define PCPP_PPP_SNACP 0x804d
|
||||
/** IP6 Header Compression Control Protocol */
|
||||
#define PCPP_PPP_IP6HCCP 0x804f
|
||||
/** KNX Bridging Control Protocol */
|
||||
#define PCPP_PPP_KNXCP 0x8051
|
||||
/** Encryption Control Protocol */
|
||||
#define PCPP_PPP_ECP 0x8053
|
||||
/** Individual Link Encryption Control Protocol */
|
||||
#define PCPP_PPP_ILECP 0x8055
|
||||
/** IPv6 Control Protocol */
|
||||
#define PCPP_PPP_IPV6CP 0x8057
|
||||
/** PPP Muxing Control Protocol */
|
||||
#define PCPP_PPP_MUXCP 0x8059
|
||||
/** Vendor-Specific Network Control Protocol (VSNCP) [RFC3772] */
|
||||
#define PCPP_PPP_VSNCP 0x805b
|
||||
/** TRILL Network Control Protocol (TNCP) */
|
||||
#define PCPP_PPP_TNCP 0x805d
|
||||
/** Stampede Bridging Control Protocol */
|
||||
#define PCPP_PPP_STAMPEDECP 0x806f
|
||||
/** MP+ Contorol Protocol */
|
||||
#define PCPP_PPP_MPPCP 0x8073
|
||||
/** NTCITS IPI Control Protocol */
|
||||
#define PCPP_PPP_IPICP 0x80c1
|
||||
/** Single link compression in multilink control */
|
||||
#define PCPP_PPP_SLCC 0x80fb
|
||||
/** Compression Control Protocol */
|
||||
#define PCPP_PPP_CCP 0x80fd
|
||||
/** Cisco Discovery Protocol Control Protocol */
|
||||
#define PCPP_PPP_CDPCP 0x8207
|
||||
/** Netcs Twin Routing */
|
||||
#define PCPP_PPP_NETCSCP 0x8209
|
||||
/** STP - Control Protocol */
|
||||
#define PCPP_PPP_STPCP 0x820b
|
||||
/** EDPCP - Extreme Discovery Protocol Control Protocol */
|
||||
#define PCPP_PPP_EDPCP 0x820d
|
||||
/** Apple Client Server Protocol Control */
|
||||
#define PCPP_PPP_ACSPC 0x8235
|
||||
/** MPLS Control Protocol */
|
||||
#define PCPP_PPP_MPLSCP 0x8281
|
||||
/** IEEE p1284.4 standard - Protocol Control */
|
||||
#define PCPP_PPP_P12844CP 0x8285
|
||||
/** ETSI TETRA TNP1 Control Protocol */
|
||||
#define PCPP_PPP_TETRACP 0x8287
|
||||
/** Multichannel Flow Treatment Protocol */
|
||||
#define PCPP_PPP_MFTPCP 0x8289
|
||||
/** Link Control Protocol */
|
||||
#define PCPP_PPP_LCP 0xc021
|
||||
/** Password Authentication Protocol */
|
||||
#define PCPP_PPP_PAP 0xc023
|
||||
/** Link Quality Report */
|
||||
#define PCPP_PPP_LQR 0xc025
|
||||
/** Shiva Password Authentication Protocol */
|
||||
#define PCPP_PPP_SPAP 0xc027
|
||||
/** CallBack Control Protocol (CBCP) */
|
||||
#define PCPP_PPP_CBCP 0xc029
|
||||
/** BACP Bandwidth Allocation Control Protocol */
|
||||
#define PCPP_PPP_BACP 0xc02b
|
||||
/** BAP Bandwidth Allocation Protocol */
|
||||
#define PCPP_PPP_BAP 0xc02d
|
||||
/** Vendor-Specific Authentication Protocol (VSAP) */
|
||||
#define PCPP_PPP_VSAP 0xc05b
|
||||
/** Container Control Protocol */
|
||||
#define PCPP_PPP_CONTCP 0xc081
|
||||
/** Challenge Handshake Authentication Protocol */
|
||||
#define PCPP_PPP_CHAP 0xc223
|
||||
/** RSA Authentication Protocol */
|
||||
#define PCPP_PPP_RSAAP 0xc225
|
||||
/** Extensible Authentication Protocol */
|
||||
#define PCPP_PPP_EAP 0xc227
|
||||
/** Mitsubishi Security Information Exchange Protocol (SIEP) */
|
||||
#define PCPP_PPP_SIEP 0xc229
|
||||
/** Stampede Bridging Authorization Protocol */
|
||||
#define PCPP_PPP_SBAP 0xc26f
|
||||
/** Proprietary Authentication Protocol */
|
||||
#define PCPP_PPP_PRPAP 0xc281
|
||||
/** Proprietary Authentication Protocol */
|
||||
#define PCPP_PPP_PRPAP2 0xc283
|
||||
/** Proprietary Node ID Authentication Protocol */
|
||||
#define PCPP_PPP_PRPNIAP 0xc481
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_PPPOE_LAYER */
|
||||
392
pcappp/include/pcapplusplus/Packet.h
Normal file
392
pcappp/include/pcapplusplus/Packet.h
Normal file
@@ -0,0 +1,392 @@
|
||||
#ifndef PACKETPP_PACKET
|
||||
#define PACKETPP_PACKET
|
||||
|
||||
#include "RawPacket.h"
|
||||
#include "Layer.h"
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class Packet
|
||||
* This class represents a parsed packet. It contains the raw data (RawPacket instance), and a linked list of layers, each layer is a parsed
|
||||
* protocol that this packet contains. The layers linked list is ordered where the first layer is the lowest in the packet (currently it's always
|
||||
* Ethernet protocol as PcapPlusPlus supports only Ethernet packets), the next layer will be L2.5 or L3 (e.g VLAN, IPv4, IPv6, etc.), and so on.
|
||||
* etc.), etc. The last layer in the linked list will be the highest in the packet.
|
||||
* For example: for a standard HTTP request packet the layer will look like this: EthLayer -> IPv4Layer -> TcpLayer -> HttpRequestLayer <BR>
|
||||
* Packet instance isn't read only. The user can add or remove layers, update current layer, etc.
|
||||
*/
|
||||
class Packet
|
||||
{
|
||||
friend class Layer;
|
||||
private:
|
||||
RawPacket* m_RawPacket;
|
||||
Layer* m_FirstLayer;
|
||||
Layer* m_LastLayer;
|
||||
uint64_t m_ProtocolTypes;
|
||||
size_t m_MaxPacketLen;
|
||||
bool m_FreeRawPacket;
|
||||
bool m_CanReallocateData;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor for creating a new packet (with no layers).
|
||||
* When using this constructor an empty raw buffer is allocated (with the size of maxPacketLen) and a new RawPacket is created
|
||||
* @param[in] maxPacketLen The expected packet length in bytes
|
||||
*/
|
||||
Packet(size_t maxPacketLen = 1);
|
||||
|
||||
/**
|
||||
* A constructor for creating a new packet with a buffer that is pre-allocated by the user.
|
||||
* The packet is created empty (with no layers), which means the constructor doesn't parse the data in the buffer.
|
||||
* Instead, all of the raw data of this packet it written to this buffer: whenever a layer is added, it's data is written to this buffer.
|
||||
* The buffer isn't freed and it's content isn't erased when the packet object is deleted.
|
||||
* This constructor is useful when you already have a memory buffer and you want to create packet data in it.
|
||||
* @param[in] buffer A pointer to a pre-allocated memory buffer
|
||||
* @param[in] bufferSize The size of the buffer
|
||||
*/
|
||||
Packet(uint8_t* buffer, size_t bufferSize);
|
||||
|
||||
/**
|
||||
* A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network.
|
||||
* When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers
|
||||
* are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free
|
||||
* the instance of raw packet when the Packet is free or not
|
||||
* @param[in] rawPacket A pointer to the raw packet
|
||||
* @param[in] freeRawPacket Optional parameter. A flag indicating if the destructor should also call the raw packet destructor or not. Default value is false
|
||||
* @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a
|
||||
* certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this
|
||||
* parameter into account
|
||||
* @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to
|
||||
* parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet.
|
||||
* Default value is ::OsiModelLayerUnknown which means don't take this parameter into account
|
||||
*/
|
||||
Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
|
||||
|
||||
/**
|
||||
* A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network.
|
||||
* When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers
|
||||
* are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free
|
||||
* the instance of raw packet when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer
|
||||
* @param[in] rawPacket A pointer to the raw packet
|
||||
* @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a
|
||||
* certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet
|
||||
*/
|
||||
Packet(RawPacket* rawPacket, ProtocolType parseUntil);
|
||||
|
||||
/**
|
||||
* A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network.
|
||||
* When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers
|
||||
* are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free
|
||||
* the instance of raw packet when the Packet is free or not. . This constructor should be used to parse the packet up to a certain layer in the OSI model
|
||||
* @param[in] rawPacket A pointer to the raw packet
|
||||
* @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to
|
||||
* parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet
|
||||
*/
|
||||
Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer);
|
||||
|
||||
/**
|
||||
* A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers that weren't allocated by this
|
||||
* class, for example layers that were added by addLayer() or insertLayer() ). In addition it frees the raw packet if it was allocated by
|
||||
* this instance (meaning if it was allocated by this instance constructor)
|
||||
*/
|
||||
virtual ~Packet() { destructPacketData(); }
|
||||
|
||||
/**
|
||||
* A copy constructor for this class. This copy constructor copies all the raw data and re-create all layers. So when the original Packet
|
||||
* is being freed, no data will be lost in the copied instance
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
Packet(const Packet& other) { copyDataFrom(other); }
|
||||
|
||||
/**
|
||||
* Assignment operator overloading. It first frees all layers allocated by this instance (Notice: it doesn't free layers that weren't allocated by this
|
||||
* class, for example layers that were added by addLayer() or insertLayer() ). In addition it frees the raw packet if it was allocated by
|
||||
* this instance (meaning if it was allocated by this instance constructor).
|
||||
* Afterwards it copies the data from the other packet in the same way used in the copy constructor.
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
Packet& operator=(const Packet& other);
|
||||
|
||||
/**
|
||||
* Get a pointer to the Packet's RawPacket
|
||||
* @return A pointer to the Packet's RawPacket
|
||||
*/
|
||||
RawPacket* getRawPacket() const { return m_RawPacket; }
|
||||
|
||||
/**
|
||||
* Set a RawPacket and re-construct all packet layers
|
||||
* @param[in] rawPacket Raw packet to set
|
||||
* @param[in] freeRawPacket A flag indicating if the destructor should also call the raw packet destructor or not
|
||||
* @param[in] parseUntil Parse the packet until it reaches this protocol. Can be useful for cases when you need to parse only up to a certain layer and want to avoid the
|
||||
* performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this parameter into account
|
||||
* @param[in] parseUntilLayer Parse the packet until certain layer in OSI model. Can be useful for cases when you need to parse only up to a certain layer and want to avoid the
|
||||
* performance impact and memory consumption of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter into account
|
||||
*/
|
||||
void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown);
|
||||
|
||||
/**
|
||||
* Get a pointer to the Packet's RawPacket in a read-only manner
|
||||
* @return A pointer to the Packet's RawPacket
|
||||
*/
|
||||
RawPacket* getRawPacketReadOnly() const { return m_RawPacket; }
|
||||
|
||||
/**
|
||||
* Get a pointer to the first (lowest) layer in the packet
|
||||
* @return A pointer to the first (lowest) layer in the packet
|
||||
*/
|
||||
Layer* getFirstLayer() const { return m_FirstLayer; }
|
||||
|
||||
/**
|
||||
* Get a pointer to the last (highest) layer in the packet
|
||||
* @return A pointer to the last (highest) layer in the packet
|
||||
*/
|
||||
Layer* getLastLayer() const { return m_LastLayer; }
|
||||
|
||||
/**
|
||||
* Add a new layer as the last layer in the packet. This method gets a pointer to the new layer as a parameter
|
||||
* and attaches it to the packet. Notice after calling this method the input layer is attached to the packet so
|
||||
* every change you make in it affect the packet; Also it cannot be attached to other packets
|
||||
* @param[in] newLayer A pointer to the new layer to be added to the packet
|
||||
* @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default is false.
|
||||
* @return True if everything went well or false otherwise (an appropriate error log message will be printed in
|
||||
* such cases)
|
||||
*/
|
||||
bool addLayer(Layer* newLayer, bool ownInPacket = false) { return insertLayer(m_LastLayer, newLayer, ownInPacket); }
|
||||
|
||||
/**
|
||||
* Insert a new layer after an existing layer in the packet. This method gets a pointer to the new layer as a
|
||||
* parameter and attaches it to the packet. Notice after calling this method the input layer is attached to the
|
||||
* packet so every change you make in it affect the packet; Also it cannot be attached to other packets
|
||||
* @param[in] prevLayer A pointer to an existing layer in the packet which the new layer should followed by. If
|
||||
* this layer isn't attached to a packet and error will be printed to log and false will be returned
|
||||
* @param[in] newLayer A pointer to the new layer to be added to the packet
|
||||
* @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default is false.
|
||||
* @return True if everything went well or false otherwise (an appropriate error log message will be printed in
|
||||
* such cases)
|
||||
*/
|
||||
bool insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket = false);
|
||||
|
||||
|
||||
/**
|
||||
* Remove an existing layer from the packet. The layer to removed is identified by its type (protocol). If the
|
||||
* packet has multiple layers of the same type in the packet the user may specify the index of the layer to remove
|
||||
* (the default index is 0 - remove the first layer of this type). If the layer was allocated during packet creation
|
||||
* it will be deleted and any pointer to it will get invalid. However if the layer was allocated by the user and
|
||||
* manually added to the packet it will simply get detached from the packet, meaning the pointer to it will stay
|
||||
* valid and its data (that was removed from the packet) will be copied back to the layer. In that case it's
|
||||
* the user's responsibility to delete the layer instance
|
||||
* @param[in] layerType The layer type (protocol) to remove
|
||||
* @param[in] index If there are multiple layers of the same type, indicate which instance to remove. The default
|
||||
* value is 0, meaning remove the first layer of this type
|
||||
* @return True if everything went well or false otherwise (an appropriate error log message will be printed in
|
||||
* such cases)
|
||||
*/
|
||||
bool removeLayer(ProtocolType layerType, int index = 0);
|
||||
|
||||
/**
|
||||
* Remove the first layer in the packet. The layer will be deleted if it was allocated during packet creation, or detached
|
||||
* if was allocated outside of the packet. Please refer to removeLayer() to get more info
|
||||
* @return True if layer removed successfully, or false if removing the layer failed or if there are no layers in the
|
||||
* packet. In any case of failure an appropriate error log message will be printed
|
||||
*/
|
||||
bool removeFirstLayer();
|
||||
|
||||
/**
|
||||
* Remove the last layer in the packet. The layer will be deleted if it was allocated during packet creation, or detached
|
||||
* if was allocated outside of the packet. Please refer to removeLayer() to get more info
|
||||
* @return True if layer removed successfully, or false if removing the layer failed or if there are no layers in the
|
||||
* packet. In any case of failure an appropriate error log message will be printed
|
||||
*/
|
||||
bool removeLastLayer();
|
||||
|
||||
/**
|
||||
* Remove all layers that come after a certain layer. All layers removed will be deleted if they were allocated during
|
||||
* packet creation or detached if were allocated outside of the packet, please refer to removeLayer() to get more info
|
||||
* @param[in] layer A pointer to the layer to begin removing from. Please note this layer will not be removed, only the
|
||||
* layers that come after it will be removed. Also, if removal of one layer failed, the method will return immediately and
|
||||
* the following layers won't be deleted
|
||||
* @return True if all layers were removed successfully, or false if failed to remove at least one layer. In any case of
|
||||
* failure an appropriate error log message will be printed
|
||||
*/
|
||||
bool removeAllLayersAfter(Layer* layer);
|
||||
|
||||
/**
|
||||
* Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated from the
|
||||
* packet - e.g it will be removed from the layer chain of the packet and its data will be copied from the packet buffer
|
||||
* into an internal layer buffer. After a layer is detached, it can be added into another packet (but it's impossible to
|
||||
* attach a layer to multiple packets in the same time). After layer is detached, it's the user's responsibility to
|
||||
* delete it when it's not needed anymore
|
||||
* @param[in] layerType The layer type (protocol) to detach from the packet
|
||||
* @param[in] index If there are multiple layers of the same type, indicate which instance to detach. The default
|
||||
* value is 0, meaning detach the first layer of this type
|
||||
* @return A pointer to the detached layer or NULL if detaching process failed. In any case of failure an
|
||||
* appropriate error log message will be printed
|
||||
*/
|
||||
Layer* detachLayer(ProtocolType layerType, int index = 0);
|
||||
|
||||
/**
|
||||
* Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated from the
|
||||
* packet - e.g it will be removed from the layer chain of the packet and its data will be copied from the packet buffer
|
||||
* into an internal layer buffer. After a layer is detached, it can be added into another packet (but it's impossible to
|
||||
* attach a layer to multiple packets at the same time). After layer is detached, it's the user's responsibility to
|
||||
* delete it when it's not needed anymore
|
||||
* @param[in] layer A pointer to the layer to detach
|
||||
* @return True if the layer was detached successfully, or false if something went wrong. In any case of failure an
|
||||
* appropriate error log message will be printed
|
||||
*/
|
||||
bool detachLayer(Layer* layer) { return removeLayer(layer, false); }
|
||||
|
||||
/**
|
||||
* Get a pointer to the layer of a certain type (protocol). This method goes through the layers and returns a layer
|
||||
* that matches the give protocol type
|
||||
* @param[in] layerType The layer type (protocol) to fetch
|
||||
* @param[in] index If there are multiple layers of the same type, indicate which instance to fetch. The default
|
||||
* value is 0, meaning fetch the first layer of this type
|
||||
* @return A pointer to the layer or NULL if no such layer was found
|
||||
*/
|
||||
Layer* getLayerOfType(ProtocolType layerType, int index = 0) const;
|
||||
|
||||
/**
|
||||
* A templated method to get a layer of a certain type (protocol). If no layer of such type is found, NULL is returned
|
||||
* @param[in] reverseOrder The optional parameter that indicates that the lookup should run in reverse order, the default value is false
|
||||
* @return A pointer to the layer of the requested type, NULL if not found
|
||||
*/
|
||||
template<class TLayer>
|
||||
TLayer* getLayerOfType(bool reverseOrder = false) const;
|
||||
|
||||
/**
|
||||
* A templated method to get the first layer of a certain type (protocol), start searching from a certain layer.
|
||||
* For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> IPv4Layer
|
||||
* and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(3) will be returned
|
||||
* If no layer of such type is found, NULL is returned
|
||||
* @param[in] startLayer A pointer to the layer to start search from
|
||||
* @return A pointer to the layer of the requested type, NULL if not found
|
||||
*/
|
||||
template<class TLayer>
|
||||
TLayer* getNextLayerOfType(Layer* startLayer) const;
|
||||
|
||||
/**
|
||||
* A templated method to get the first layer of a certain type (protocol), start searching from a certain layer.
|
||||
* For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> IPv4Layer
|
||||
* and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(1) will be returned
|
||||
* If no layer of such type is found, NULL is returned
|
||||
* @param[in] startLayer A pointer to the layer to start search from
|
||||
* @return A pointer to the layer of the requested type, NULL if not found
|
||||
*/
|
||||
template<class TLayer>
|
||||
TLayer* getPrevLayerOfType(Layer* startLayer) const;
|
||||
|
||||
/**
|
||||
* Check whether the packet contains a certain protocol
|
||||
* @param[in] protocolType The protocol type to search
|
||||
* @return True if the packet contains the protocol, false otherwise
|
||||
*/
|
||||
bool isPacketOfType(ProtocolType protocolType) const { return m_ProtocolTypes & protocolType; }
|
||||
|
||||
/**
|
||||
* Each layer can have fields that can be calculate automatically from other fields using Layer#computeCalculateFields(). This method forces all layers to calculate these
|
||||
* fields values
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
/**
|
||||
* Each layer can print a string representation of the layer most important data using Layer#toString(). This method aggregates this string from all layers and
|
||||
* print it to a complete string containing all packet's relevant data
|
||||
* @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set to false
|
||||
* @return A string containing most relevant data from all layers (looks like the packet description in Wireshark)
|
||||
*/
|
||||
std::string toString(bool timeAsLocalTime = true) const;
|
||||
|
||||
/**
|
||||
* Similar to toString(), but instead of one string it outputs a list of strings, one string for every layer
|
||||
* @param[out] result A string vector that will contain all strings
|
||||
* @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set to false
|
||||
*/
|
||||
void toStringList(std::vector<std::string>& result, bool timeAsLocalTime = true) const;
|
||||
|
||||
private:
|
||||
void copyDataFrom(const Packet& other);
|
||||
|
||||
void destructPacketData();
|
||||
|
||||
bool extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend);
|
||||
bool shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten);
|
||||
|
||||
void reallocateRawData(size_t newSize);
|
||||
|
||||
bool removeLayer(Layer* layer, bool tryToDelete);
|
||||
|
||||
std::string printPacketInfo(bool timeAsLocalTime) const;
|
||||
|
||||
Layer* createFirstLayer(LinkLayerType linkType);
|
||||
}; // class Packet
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
template<class TLayer>
|
||||
TLayer* Packet::getLayerOfType(bool reverse) const
|
||||
{
|
||||
if (!reverse)
|
||||
{
|
||||
if (dynamic_cast<TLayer*>(getFirstLayer()) != NULL)
|
||||
return dynamic_cast<TLayer*>(getFirstLayer());
|
||||
|
||||
return getNextLayerOfType<TLayer>(getFirstLayer());
|
||||
}
|
||||
|
||||
// lookup in reverse order
|
||||
if (dynamic_cast<TLayer*>(getLastLayer()) != NULL)
|
||||
return dynamic_cast<TLayer*>(getLastLayer());
|
||||
|
||||
return getPrevLayerOfType<TLayer>(getLastLayer());
|
||||
}
|
||||
|
||||
template<class TLayer>
|
||||
TLayer* Packet::getNextLayerOfType(Layer* curLayer) const
|
||||
{
|
||||
if (curLayer == NULL)
|
||||
return NULL;
|
||||
|
||||
curLayer = curLayer->getNextLayer();
|
||||
while ((curLayer != NULL) && (dynamic_cast<TLayer*>(curLayer) == NULL))
|
||||
{
|
||||
curLayer = curLayer->getNextLayer();
|
||||
}
|
||||
|
||||
return dynamic_cast<TLayer*>(curLayer);
|
||||
}
|
||||
|
||||
template<class TLayer>
|
||||
TLayer* Packet::getPrevLayerOfType(Layer* curLayer) const
|
||||
{
|
||||
if (curLayer == NULL)
|
||||
return NULL;
|
||||
|
||||
curLayer = curLayer->getPrevLayer();
|
||||
while (curLayer != NULL && dynamic_cast<TLayer*>(curLayer) == NULL)
|
||||
{
|
||||
curLayer = curLayer->getPrevLayer();
|
||||
}
|
||||
|
||||
return dynamic_cast<TLayer*>(curLayer);
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet)
|
||||
{
|
||||
os << packet.toString();
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif /* PACKETPP_PACKET */
|
||||
359
pcappp/include/pcapplusplus/Packet32.h
Normal file
359
pcappp/include/pcapplusplus/Packet32.h
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (c) 2005 - 2007 CACE Technologies, Davis (California)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
|
||||
* nor the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @ingroup packetapi
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup packet32h Packet.dll definitions and data structures
|
||||
* Packet32.h contains the data structures and the definitions used by packet.dll.
|
||||
* The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
|
||||
* by the applications that use the functions of this library
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __PACKET32
|
||||
#define __PACKET32
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#ifdef HAVE_AIRPCAP_API
|
||||
#include <airpcap.h>
|
||||
#else
|
||||
#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
|
||||
#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
|
||||
typedef struct _AirpcapHandle *PAirpcapHandle;
|
||||
#endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */
|
||||
#endif /* HAVE_AIRPCAP_API */
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
#include <dagc.h>
|
||||
#endif /* HAVE_DAG_API */
|
||||
|
||||
// Working modes
|
||||
#define PACKET_MODE_CAPT 0x0 ///< Capture mode
|
||||
#define PACKET_MODE_STAT 0x1 ///< Statistical mode
|
||||
#define PACKET_MODE_MON 0x2 ///< Monitoring mode
|
||||
#define PACKET_MODE_DUMP 0x10 ///< Dump mode
|
||||
#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode
|
||||
|
||||
|
||||
/// Alignment macro. Defines the alignment size.
|
||||
#define Packet_ALIGNMENT sizeof(int)
|
||||
/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT.
|
||||
#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
|
||||
|
||||
#define NdisMediumNull -1 ///< Custom linktype: NDIS doesn't provide an equivalent
|
||||
#define NdisMediumCHDLC -2 ///< Custom linktype: NDIS doesn't provide an equivalent
|
||||
#define NdisMediumPPPSerial -3 ///< Custom linktype: NDIS doesn't provide an equivalent
|
||||
#define NdisMediumBare80211 -4 ///< Custom linktype: NDIS doesn't provide an equivalent
|
||||
#define NdisMediumRadio80211 -5 ///< Custom linktype: NDIS doesn't provide an equivalent
|
||||
#define NdisMediumPpi -6 ///< Custom linktype: NDIS doesn't provide an equivalent
|
||||
|
||||
// Loopback behaviour definitions
|
||||
#define NPF_DISABLE_LOOPBACK 1 ///< Drop the packets sent by the NPF driver
|
||||
#define NPF_ENABLE_LOOPBACK 2 ///< Capture the packets sent by the NPF driver
|
||||
|
||||
/*!
|
||||
\brief Network type structure.
|
||||
|
||||
This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
|
||||
*/
|
||||
typedef struct NetType
|
||||
{
|
||||
UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
|
||||
ULONGLONG LinkSpeed; ///< The speed of the network in bits per second
|
||||
}NetType;
|
||||
|
||||
|
||||
//some definitions stolen from libpcap
|
||||
|
||||
#ifndef BPF_MAJOR_VERSION
|
||||
|
||||
/*!
|
||||
\brief A BPF pseudo-assembly program.
|
||||
|
||||
The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.
|
||||
*/
|
||||
struct bpf_program
|
||||
{
|
||||
UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
|
||||
struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program.
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A single BPF pseudo-instruction.
|
||||
|
||||
bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
|
||||
*/
|
||||
struct bpf_insn
|
||||
{
|
||||
USHORT code; ///< Instruction type and addressing mode.
|
||||
UCHAR jt; ///< Jump if true
|
||||
UCHAR jf; ///< Jump if false
|
||||
int k; ///< Generic field used for various purposes.
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Structure that contains a couple of statistics values on the current capture.
|
||||
|
||||
It is used by packet.dll to return statistics about a capture session.
|
||||
*/
|
||||
struct bpf_stat
|
||||
{
|
||||
UINT bs_recv; ///< Number of packets that the driver received from the network adapter
|
||||
///< from the beginning of the current capture. This value includes the packets
|
||||
///< lost by the driver.
|
||||
UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
|
||||
///< Basically, a packet is lost when the the buffer of the driver is full.
|
||||
///< In this situation the packet cannot be stored and the driver rejects it.
|
||||
UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
|
||||
UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
|
||||
///< thus reach the application.
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Packet header.
|
||||
|
||||
This structure defines the header associated with every packet delivered to the application.
|
||||
*/
|
||||
struct bpf_hdr
|
||||
{
|
||||
struct timeval bh_tstamp; ///< The timestamp associated with the captured packet.
|
||||
///< It is stored in a TimeVal structure.
|
||||
UINT bh_caplen; ///< Length of captured portion. The captured portion <b>can be different</b>
|
||||
///< from the original packet, because it is possible (with a proper filter)
|
||||
///< to instruct the driver to capture only a portion of the packets.
|
||||
UINT bh_datalen; ///< Original length of packet
|
||||
USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases,
|
||||
///< a padding could be added between the end of this structure and the packet
|
||||
///< data for performance reasons. This filed can be used to retrieve the actual data
|
||||
///< of the packet.
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Dump packet header.
|
||||
|
||||
This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
|
||||
It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
|
||||
packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
|
||||
*/
|
||||
struct dump_bpf_hdr{
|
||||
struct timeval ts; ///< Time stamp of the packet
|
||||
UINT caplen; ///< Length of captured portion. The captured portion can smaller than the
|
||||
///< the original packet, because it is possible (with a proper filter) to
|
||||
///< instruct the driver to capture only a portion of the packets.
|
||||
UINT len; ///< Length of the original packet (off wire).
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
struct bpf_stat;
|
||||
|
||||
#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
|
||||
#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links
|
||||
#define NMAX_PACKET 65535
|
||||
|
||||
/*!
|
||||
\brief Addresses of a network adapter.
|
||||
|
||||
This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with
|
||||
an adapter.
|
||||
*/
|
||||
typedef struct npf_if_addr {
|
||||
struct sockaddr_storage IPAddress; ///< IP address.
|
||||
struct sockaddr_storage SubnetMask; ///< Netmask for that address.
|
||||
struct sockaddr_storage Broadcast; ///< Broadcast address.
|
||||
}npf_if_addr;
|
||||
|
||||
|
||||
#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API.
|
||||
#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API.
|
||||
#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
|
||||
#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
|
||||
|
||||
|
||||
typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
|
||||
typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
|
||||
|
||||
#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter
|
||||
#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET
|
||||
#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card
|
||||
#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file
|
||||
#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.
|
||||
#define INFO_FLAG_AIRPCAP_CARD 16 ///< Flag for ADAPTER_INFO: this is an airpcap card
|
||||
#define INFO_FLAG_NPFIM_DEVICE 32
|
||||
|
||||
/*!
|
||||
\brief Describes an opened network adapter.
|
||||
|
||||
This structure is the most important for the functioning of packet.dll, but the great part of its fields
|
||||
should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
|
||||
*/
|
||||
typedef struct _ADAPTER {
|
||||
HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver.
|
||||
CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
|
||||
int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated
|
||||
///< on the wire.
|
||||
HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter.
|
||||
///< It can be passed to standard Win32 functions (like WaitForSingleObject
|
||||
///< or WaitForMultipleObjects) to wait until the driver's buffer contains some
|
||||
///< data. It is particularly useful in GUI applications that need to wait
|
||||
///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
|
||||
///< function can be used to define the minimum amount of data in the kernel buffer
|
||||
///< that will cause the event to be signalled.
|
||||
|
||||
UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and
|
||||
///< ReadEvent will be signaled, also if no packets were captured
|
||||
CHAR Name[ADAPTER_NAME_LENGTH];
|
||||
PWAN_ADAPTER pWanAdapter;
|
||||
UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
|
||||
|
||||
#ifdef HAVE_AIRPCAP_API
|
||||
PAirpcapHandle AirpcapAd;
|
||||
#endif // HAVE_AIRPCAP_API
|
||||
|
||||
#ifdef HAVE_NPFIM_API
|
||||
void* NpfImHandle;
|
||||
#endif // HAVE_NPFIM_API
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter
|
||||
PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card
|
||||
struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure
|
||||
unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry
|
||||
DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).
|
||||
#endif // HAVE_DAG_API
|
||||
} ADAPTER, *LPADAPTER;
|
||||
|
||||
/*!
|
||||
\brief Structure that contains a group of packets coming from the driver.
|
||||
|
||||
This structure defines the header associated with every packet delivered to the application.
|
||||
*/
|
||||
typedef struct _PACKET {
|
||||
HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications.
|
||||
OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications.
|
||||
PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for
|
||||
///< details about the organization of the data in this buffer
|
||||
UINT Length; ///< Length of the buffer
|
||||
DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data
|
||||
///< received by the last call to PacketReceivePacket()
|
||||
BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications.
|
||||
} PACKET, *LPPACKET;
|
||||
|
||||
/*!
|
||||
\brief Structure containing an OID request.
|
||||
|
||||
It is used by the PacketRequest() function to send an OID to the interface card driver.
|
||||
It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
|
||||
the list of the multicast groups defined on it, and so on.
|
||||
*/
|
||||
struct _PACKET_OID_DATA {
|
||||
ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
|
||||
///< for a complete list of valid codes.
|
||||
ULONG Length; ///< Length of the data field
|
||||
UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
|
||||
///< from the adapter.
|
||||
};
|
||||
typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*
|
||||
BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName,
|
||||
CHAR *Value,
|
||||
UINT *pValueLen,
|
||||
CHAR *DefaultVal);
|
||||
|
||||
BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName,
|
||||
WCHAR *Value,
|
||||
UINT *pValueLen,
|
||||
WCHAR *DefaultVal);
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EXPORTED FUNCTIONS
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
PCHAR PacketGetVersion();
|
||||
PCHAR PacketGetDriverVersion();
|
||||
BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);
|
||||
BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);
|
||||
BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
|
||||
BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
|
||||
BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
|
||||
BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior);
|
||||
INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);
|
||||
BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
|
||||
BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
|
||||
BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
|
||||
BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
|
||||
LPADAPTER PacketOpenAdapter(PCHAR AdapterName);
|
||||
BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
|
||||
INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
|
||||
LPPACKET PacketAllocatePacket(void);
|
||||
VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
|
||||
VOID PacketFreePacket(LPPACKET lpPacket);
|
||||
BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
|
||||
BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);
|
||||
BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize);
|
||||
BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
|
||||
BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
|
||||
HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
|
||||
BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
|
||||
BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
|
||||
BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
|
||||
BOOL PacketStopDriver();
|
||||
VOID PacketCloseAdapter(LPADAPTER lpAdapter);
|
||||
BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength);
|
||||
BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags);
|
||||
PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject);
|
||||
|
||||
//
|
||||
// Used by PacketStartOemEx
|
||||
//
|
||||
#define PACKET_START_OEM_NO_NETMON 0x00000001
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__PACKET32
|
||||
84
pcappp/include/pcapplusplus/PacketTrailerLayer.h
Normal file
84
pcappp/include/pcapplusplus/PacketTrailerLayer.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef PACKETPP_PACKET_TRAILER_LAYER
|
||||
#define PACKETPP_PACKET_TRAILER_LAYER
|
||||
|
||||
/// @file
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @class PacketTrailerLayer
|
||||
* A class for representing packet tailer (a.k.a footer or padding) which refers to supplemental data placed at the end of a block of data
|
||||
* being stored or transmitted, which may contain information for the handling of the data block, or just mark its end
|
||||
* (taken from Wikipedia: https://en.wikipedia.org/wiki/Trailer_(computing) )
|
||||
*
|
||||
* There are various reasons for adding a packet trailer, one of the most famous is FCS (Frame check sequence) which refers to the extra
|
||||
* error-detecting code added to a frame. Another usage is padding which means adding data to reach a minimum required packet length.
|
||||
*
|
||||
* Although this layer inherits from the Layer class, it is not a standard layer in the sense that it can't be constructed by the user.
|
||||
* This layer may be only be constructed in the Packet class, in the process of parsing the packet and creating the layers; if at the end
|
||||
* of the parsing process there is data left that is not allocated to any layer, it's assumed to be the packet trailer and an instance of
|
||||
* this class is created. This means this layer can only exist as the last layer in a packet, if a packet trailer indeed exists.
|
||||
*
|
||||
* No layer can be added by the user after this layer (trying to do that will result with an error).
|
||||
*
|
||||
* This layer can be removed by the user or extended/shortened, as any layer.
|
||||
*
|
||||
* It also contains method to extract the trailer data
|
||||
*/
|
||||
class PacketTrailerLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
PacketTrailerLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = PacketTrailer; }
|
||||
|
||||
~PacketTrailerLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the trailer data
|
||||
* @return A pointer to the trailer data
|
||||
*/
|
||||
uint8_t* getTrailerData() const { return m_Data; }
|
||||
|
||||
/**
|
||||
* @return Trailer data as hex string
|
||||
*/
|
||||
std::string getTrailerDataAsHexString() const;
|
||||
|
||||
/**
|
||||
* Get the trailer data length
|
||||
* @return The trailer data length in bytes
|
||||
*/
|
||||
size_t getTrailerLen() const { return m_DataLen; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (PacketTrailerLayer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return trailer data length in bytes
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_PACKET_TRAILER_LAYER
|
||||
76
pcappp/include/pcapplusplus/PacketUtils.h
Normal file
76
pcappp/include/pcapplusplus/PacketUtils.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef PACKETPP_PACKET_UTILS
|
||||
#define PACKETPP_PACKET_UTILS
|
||||
|
||||
#include "Packet.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* A struct that represent a single buffer
|
||||
*/
|
||||
template<typename T>
|
||||
struct ScalarBuffer
|
||||
{
|
||||
/**
|
||||
* The pointer to the buffer
|
||||
*/
|
||||
T* buffer;
|
||||
|
||||
/**
|
||||
* Buffer length
|
||||
*/
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the checksum for a vector of buffers
|
||||
* @param[in] vec The vector of buffers
|
||||
* @param[in] vecSize Number of ScalarBuffers in vector
|
||||
* @return The checksum result
|
||||
*/
|
||||
uint16_t computeChecksum(ScalarBuffer<uint16_t> vec[], size_t vecSize);
|
||||
|
||||
/**
|
||||
* Computes Fowler-Noll-Vo (FNV-1) 32bit hash function on an array of byte buffers. The hash is calculated on each
|
||||
* byte in each byte buffer, as if all byte buffers were one long byte buffer
|
||||
* @param[in] vec An array of byte buffers (ScalarBuffer of type uint8_t)
|
||||
* @param[in] vecSize The length of vec
|
||||
* @return The 32bit hash value
|
||||
*/
|
||||
uint32_t fnvHash(ScalarBuffer<uint8_t> vec[], size_t vecSize);
|
||||
|
||||
/**
|
||||
* Computes Fowler-Noll-Vo (FNV-1) 32bit hash function on a byte buffer
|
||||
* @param[in] buffer The byte buffer
|
||||
* @param[in] bufSize The size of the byte buffer
|
||||
* @return The 32bit hash value
|
||||
*/
|
||||
uint32_t fnvHash(uint8_t* buffer, size_t bufSize);
|
||||
|
||||
/**
|
||||
* A method that is given a packet and calculates a hash value by the packet's 5-tuple. Supports IPv4, IPv6,
|
||||
* TCP and UDP. For packets which doesn't have 5-tuple (for example: packets which aren't IPv4/6 or aren't
|
||||
* TCP/UDP) the value of 0 will be returned
|
||||
* @param[in] packet The packet to calculate hash for
|
||||
* @param[in] directionUnique Make hash value unique for each direction
|
||||
* @return The hash value calculated for this packet or 0 if the packet doesn't contain 5-tuple
|
||||
*/
|
||||
uint32_t hash5Tuple(Packet* packet, bool const& directionUnique = false);
|
||||
|
||||
/**
|
||||
* A method that is given a packet and calculates a hash value by the packet's 2-tuple (IP src + IP dst). Supports
|
||||
* IPv4 and IPv6. For packets which aren't IPv4/6 the value of 0 will be returned
|
||||
* @param[in] packet The packet to calculate hash for
|
||||
* @return The hash value calculated for this packet or 0 if the packet isn't IPv4/6
|
||||
*/
|
||||
uint32_t hash2Tuple(Packet* packet);
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_PACKET_UTILS */
|
||||
94
pcappp/include/pcapplusplus/PayloadLayer.h
Normal file
94
pcappp/include/pcapplusplus/PayloadLayer.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef PACKETPP_PAYLOAD_LAYER
|
||||
#define PACKETPP_PAYLOAD_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class PayloadLayer
|
||||
* Represents a generic or unknown layer or a packet payload
|
||||
*/
|
||||
class PayloadLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
PayloadLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = GenericPayload; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new payload
|
||||
* @param[in] data A raw buffer that will be used as a payload. This data will be copied to the layer
|
||||
* @param[in] dataLen The raw buffer length
|
||||
* @param[in] dummy A dummy parameter to separate the constructor signature from the other constructor. Its value isn't used anywhere
|
||||
* @todo dummy is probably not necessary anymore. Remove it
|
||||
*/
|
||||
PayloadLayer(const uint8_t* data, size_t dataLen, bool dummy);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new payload from an hex stream
|
||||
* @param[in] payloadAsHexStream A string that represents an hex stream of the payload. For example: 0001080006040002842b2b774c56c0a80078000000000000c0a8.
|
||||
* In order for the hex stream to be valid it has to contain valid hex chars only (which means, for example, that it can't begin with "0x") and it also has
|
||||
* to have an even number of chars (each char represents one nibble). If the string is not a valid hex stream an error will be printed to log and the payload
|
||||
* layer will be empty (no data)
|
||||
*/
|
||||
PayloadLayer(const std::string& payloadAsHexStream);
|
||||
|
||||
~PayloadLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the payload data
|
||||
* @return A pointer to the payload data
|
||||
*/
|
||||
uint8_t* getPayload() const { return m_Data; }
|
||||
|
||||
/**
|
||||
* Get the payload data length
|
||||
* @return The payload data length in bytes
|
||||
*/
|
||||
size_t getPayloadLen() const { return m_DataLen; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Does nothing for this layer (PayloadLayer is always last)
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* @return Payload data length in bytes
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
/**
|
||||
* Sets the payload of the PayloadLayer to the given pointer. This will resize (extend/shorten) the underlying packet respectively if there is one.
|
||||
* @param[in] newPayload New payload that shall be set
|
||||
* @param[in] newPayloadLength New length of payload
|
||||
*/
|
||||
void setPayload(const uint8_t* newPayload, size_t newPayloadLength);
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_PAYLOAD_LAYER */
|
||||
100
pcappp/include/pcapplusplus/PcapDevice.h
Normal file
100
pcappp/include/pcapplusplus/PcapDevice.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#ifndef PCAPPP_PCAP_DEVICE
|
||||
#define PCAPPP_PCAP_DEVICE
|
||||
|
||||
#include "Device.h"
|
||||
|
||||
// forward declaration for the pcap descriptor defined in pcap.h
|
||||
struct pcap;
|
||||
typedef pcap pcap_t;
|
||||
struct pcap_pkthdr;
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
//Forward Declaration - required for IPcapDevice::matchPacketWithFilter
|
||||
class GeneralFilter;
|
||||
|
||||
/**
|
||||
* @class IPcapDevice
|
||||
* An abstract class representing all libpcap-based packet capturing devices: files, libPcap, WinPcap/Npcap and RemoteCapture.
|
||||
* This class is abstract and cannot be instantiated
|
||||
*/
|
||||
class IPcapDevice : public IDevice, public IFilterableDevice
|
||||
{
|
||||
protected:
|
||||
pcap_t* m_PcapDescriptor;
|
||||
|
||||
// c'tor should not be public
|
||||
IPcapDevice() : IDevice() { m_PcapDescriptor = NULL; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @struct PcapStats
|
||||
* A container for pcap device statistics
|
||||
*/
|
||||
struct PcapStats
|
||||
{
|
||||
/** Number of packets received */
|
||||
uint64_t packetsRecv;
|
||||
/** Number of packets dropped */
|
||||
uint64_t packetsDrop;
|
||||
/** number of packets dropped by interface (not supported on all platforms) */
|
||||
uint64_t packetsDropByInterface;
|
||||
};
|
||||
|
||||
|
||||
virtual ~IPcapDevice();
|
||||
|
||||
/**
|
||||
* Get statistics from the device
|
||||
* @param[out] stats An object containing the stats
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void getStatistics(PcapStats& stats) const = 0;
|
||||
|
||||
/**
|
||||
* A static method for retrieving pcap lib (libpcap/WinPcap/etc.) version information. This method is actually
|
||||
* a wrapper for [pcap_lib_version()](https://www.tcpdump.org/manpages/pcap_lib_version.3pcap.html)
|
||||
* @return A string containing the pcap lib version information
|
||||
*/
|
||||
static std::string getPcapLibVersionInfo();
|
||||
|
||||
/**
|
||||
* Match a raw packet with a given BPF filter. Notice this method is static which means you don't need any device instance
|
||||
* in order to perform this match
|
||||
* @param[in] filter A filter class to test against
|
||||
* @param[in] rawPacket A pointer to the raw packet to match the filter with
|
||||
* @return True if raw packet matches the filter or false otherwise
|
||||
*/
|
||||
static bool matchPacketWithFilter(GeneralFilter& filter, RawPacket* rawPacket);
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
using IFilterableDevice::setFilter;
|
||||
|
||||
/**
|
||||
* Set a filter for the device. When implemented by the device, only packets that match the filter will be received.
|
||||
* Please note that when the device is closed the filter is reset so when reopening the device you need to call this
|
||||
* method again in order to reactivate the filter
|
||||
* @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
|
||||
* @return True if filter set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setFilter(std::string filterAsString);
|
||||
|
||||
/**
|
||||
* Clear the filter currently set on device
|
||||
* @return True if filter was removed successfully or if no filter was set, false otherwise
|
||||
*/
|
||||
bool clearFilter();
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // PCAPPP_PCAP_DEVICE
|
||||
595
pcappp/include/pcapplusplus/PcapFileDevice.h
Normal file
595
pcappp/include/pcapplusplus/PcapFileDevice.h
Normal file
@@ -0,0 +1,595 @@
|
||||
#ifndef PCAPPP_FILE_DEVICE
|
||||
#define PCAPPP_FILE_DEVICE
|
||||
|
||||
#include "PcapDevice.h"
|
||||
#include "RawPacket.h"
|
||||
#include <fstream>
|
||||
|
||||
// forward declaration for structs and typedefs defined in pcap.h
|
||||
struct pcap_dumper;
|
||||
typedef struct pcap_dumper pcap_dumper_t;
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class IFileDevice
|
||||
* An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for all file devices
|
||||
*/
|
||||
class IFileDevice : public IPcapDevice
|
||||
{
|
||||
protected:
|
||||
std::string m_FileName;
|
||||
|
||||
IFileDevice(const std::string& fileName);
|
||||
virtual ~IFileDevice();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @return The name of the file
|
||||
*/
|
||||
std::string getFileName() const;
|
||||
|
||||
|
||||
//override methods
|
||||
|
||||
/**
|
||||
* Close the file
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void close();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IFileReaderDevice
|
||||
* An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file reader devices
|
||||
*/
|
||||
class IFileReaderDevice : public IFileDevice
|
||||
{
|
||||
protected:
|
||||
uint32_t m_NumOfPacketsRead;
|
||||
uint32_t m_NumOfPacketsNotParsed;
|
||||
|
||||
/**
|
||||
* A constructor for this class that gets the pcap full path file name to open. Notice that after calling this constructor the file
|
||||
* isn't opened yet, so reading packets will fail. For opening the file call open()
|
||||
* @param[in] fileName The full path of the file to read
|
||||
*/
|
||||
IFileReaderDevice(const std::string& fileName);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~IFileReaderDevice() {}
|
||||
|
||||
/**
|
||||
* @return The file size in bytes
|
||||
*/
|
||||
uint64_t getFileSize() const;
|
||||
|
||||
virtual bool getNextPacket(RawPacket& rawPacket) = 0;
|
||||
|
||||
/**
|
||||
* Read the next N packets into a raw packet vector
|
||||
* @param[out] packetVec The raw packet vector to read packets into
|
||||
* @param[in] numOfPacketsToRead Number of packets to read. If value <0 all remaining packets in the file will be read into the
|
||||
* raw packet vector (this is the default value)
|
||||
* @return The number of packets actually read
|
||||
*/
|
||||
int getNextPackets(RawPacketVector& packetVec, int numOfPacketsToRead = -1);
|
||||
|
||||
/**
|
||||
* A static method that creates an instance of the reader best fit to read the file. It decides by the file extension: for .pcapng
|
||||
* files it returns an instance of PcapNgFileReaderDevice and for all other extensions it returns an instance of PcapFileReaderDevice
|
||||
* @param[in] fileName The file name to open
|
||||
* @return An instance of the reader to read the file. Notice you should free this instance when done using it
|
||||
*/
|
||||
static IFileReaderDevice* getReader(const std::string& fileName);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PcapFileReaderDevice
|
||||
* A class for opening a pcap file in read-only mode. This class enable to open the file and read all packets, packet-by-packet
|
||||
*/
|
||||
class PcapFileReaderDevice : public IFileReaderDevice
|
||||
{
|
||||
private:
|
||||
LinkLayerType m_PcapLinkLayerType;
|
||||
|
||||
// private copy c'tor
|
||||
PcapFileReaderDevice(const PcapFileReaderDevice& other);
|
||||
PcapFileReaderDevice& operator=(const PcapFileReaderDevice& other);
|
||||
|
||||
public:
|
||||
/**
|
||||
* A constructor for this class that gets the pcap full path file name to open. Notice that after calling this constructor the file
|
||||
* isn't opened yet, so reading packets will fail. For opening the file call open()
|
||||
* @param[in] fileName The full path of the file to read
|
||||
*/
|
||||
PcapFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET) {}
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~PcapFileReaderDevice() {}
|
||||
|
||||
/**
|
||||
* @return The link layer type of this file
|
||||
*/
|
||||
LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; }
|
||||
|
||||
|
||||
//overridden methods
|
||||
|
||||
/**
|
||||
* Read the next packet from the file. Before using this method please verify the file is opened using open()
|
||||
* @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
|
||||
* @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
|
||||
* or if reached end-of-file
|
||||
*/
|
||||
bool getNextPacket(RawPacket& rawPacket);
|
||||
|
||||
/**
|
||||
* Open the file name which path was specified in the constructor in a read-only mode
|
||||
* @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example:
|
||||
* file path does not exist)
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The rest of the members will contain 0
|
||||
* @param[out] stats The stats struct where stats are returned
|
||||
*/
|
||||
void getStatistics(PcapStats& stats) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class SnoopFileReaderDevice
|
||||
* A class for opening a snoop file in read-only mode. This class enable to open the file and read all packets, packet-by-packet
|
||||
*/
|
||||
class SnoopFileReaderDevice : public IFileReaderDevice
|
||||
{
|
||||
private:
|
||||
#pragma pack(0)
|
||||
/*
|
||||
* File format header.
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t identification_pattern;
|
||||
uint32_t version_number;
|
||||
uint32_t datalink_type;
|
||||
} snoop_file_header_t;
|
||||
|
||||
/*
|
||||
* Packet record header.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t original_length; /* original packet length */
|
||||
uint32_t included_length; /* saved packet length */
|
||||
uint32_t packet_record_length;/* total record length */
|
||||
uint32_t ndrops_cumulative; /* cumulative drops */
|
||||
uint32_t time_sec; /* timestamp */
|
||||
uint32_t time_usec; /* microsecond timestamp */
|
||||
} snoop_packet_header_t;
|
||||
#pragma pack()
|
||||
|
||||
LinkLayerType m_PcapLinkLayerType;
|
||||
std::ifstream m_snoopFile;
|
||||
|
||||
// private copy c'tor
|
||||
SnoopFileReaderDevice(const PcapFileReaderDevice& other);
|
||||
SnoopFileReaderDevice& operator=(const PcapFileReaderDevice& other);
|
||||
|
||||
public:
|
||||
/**
|
||||
* A constructor for this class that gets the snoop full path file name to open. Notice that after calling this constructor the file
|
||||
* isn't opened yet, so reading packets will fail. For opening the file call open()
|
||||
* @param[in] fileName The full path of the file to read
|
||||
*/
|
||||
SnoopFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET) {}
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~SnoopFileReaderDevice();
|
||||
|
||||
/**
|
||||
* @return The link layer type of this file
|
||||
*/
|
||||
LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; }
|
||||
|
||||
|
||||
//overridden methods
|
||||
|
||||
/**
|
||||
* Read the next packet from the file. Before using this method please verify the file is opened using open()
|
||||
* @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
|
||||
* @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
|
||||
* or if reached end-of-file
|
||||
*/
|
||||
bool getNextPacket(RawPacket& rawPacket);
|
||||
|
||||
/**
|
||||
* Open the file name which path was specified in the constructor in a read-only mode
|
||||
* @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example:
|
||||
* file path does not exist)
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The rest of the members will contain 0
|
||||
* @param[out] stats The stats struct where stats are returned
|
||||
*/
|
||||
void getStatistics(PcapStats& stats) const;
|
||||
|
||||
/**
|
||||
* Close the snoop file
|
||||
*/
|
||||
void close();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PcapNgFileReaderDevice
|
||||
* A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets, packet-by-packet
|
||||
*/
|
||||
class PcapNgFileReaderDevice : public IFileReaderDevice
|
||||
{
|
||||
private:
|
||||
void* m_LightPcapNg;
|
||||
BpfFilterWrapper m_BpfWrapper;
|
||||
|
||||
// private copy c'tor
|
||||
PcapNgFileReaderDevice(const PcapNgFileReaderDevice& other);
|
||||
PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other);
|
||||
|
||||
public:
|
||||
/**
|
||||
* A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling this constructor the file
|
||||
* isn't opened yet, so reading packets will fail. For opening the file call open()
|
||||
* @param[in] fileName The full path of the file to read
|
||||
*/
|
||||
PcapNgFileReaderDevice(const std::string& fileName);
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~PcapNgFileReaderDevice() { close(); }
|
||||
|
||||
/**
|
||||
* The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the
|
||||
* operating system that was used for capturing the packets. This method reads this string from the metadata (if exists) and
|
||||
* returns it
|
||||
* @return The operating system string if exists, or an empty string otherwise
|
||||
*/
|
||||
std::string getOS() const;
|
||||
|
||||
/**
|
||||
* The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the
|
||||
* hardware that was used for capturing the packets. This method reads this string from the metadata (if exists) and
|
||||
* returns it
|
||||
* @return The hardware string if exists, or an empty string otherwise
|
||||
*/
|
||||
std::string getHardware() const;
|
||||
|
||||
/**
|
||||
* The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the
|
||||
* capture application that was used for capturing the packets. This method reads this string from the metadata (if exists) and
|
||||
* returns it
|
||||
* @return The capture application string if exists, or an empty string otherwise
|
||||
*/
|
||||
std::string getCaptureApplication() const;
|
||||
|
||||
/**
|
||||
* The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string containing a user-defined
|
||||
* comment (can be any string). This method reads this string from the metadata (if exists) and
|
||||
* returns it
|
||||
* @return The comment written inside the file if exists, or an empty string otherwise
|
||||
*/
|
||||
std::string getCaptureFileComment() const;
|
||||
|
||||
/**
|
||||
* The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file). This method reads
|
||||
* the next packet and the comment attached to it (if such comment exists), and returns them both
|
||||
* @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
|
||||
* @param[out] packetComment The comment attached to the packet or an empty string if no comment exists
|
||||
* @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
|
||||
* or if reached end-of-file
|
||||
*/
|
||||
bool getNextPacket(RawPacket& rawPacket, std::string& packetComment);
|
||||
|
||||
//overridden methods
|
||||
|
||||
/**
|
||||
* Read the next packet from the file. Before using this method please verify the file is opened using open()
|
||||
* @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
|
||||
* @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed)
|
||||
* or if reached end-of-file
|
||||
*/
|
||||
bool getNextPacket(RawPacket& rawPacket);
|
||||
|
||||
/**
|
||||
* Open the file name which path was specified in the constructor in a read-only mode
|
||||
* @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example:
|
||||
* file path does not exist)
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Get statistics of packets read so far.
|
||||
* @param[out] stats The stats struct where stats are returned
|
||||
*/
|
||||
void getStatistics(PcapStats& stats) const;
|
||||
|
||||
/**
|
||||
* Set a filter for PcapNG reader device. Only packets that match the filter will be received
|
||||
* @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
|
||||
* @return True if filter set successfully, false otherwise
|
||||
*/
|
||||
bool setFilter(std::string filterAsString);
|
||||
|
||||
/**
|
||||
* Close the pacp-ng file
|
||||
*/
|
||||
void close();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IFileWriterDevice
|
||||
* An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer devices
|
||||
*/
|
||||
class IFileWriterDevice : public IFileDevice
|
||||
{
|
||||
protected:
|
||||
uint32_t m_NumOfPacketsWritten;
|
||||
uint32_t m_NumOfPacketsNotWritten;
|
||||
|
||||
IFileWriterDevice(const std::string& fileName);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~IFileWriterDevice() {}
|
||||
|
||||
virtual bool writePacket(RawPacket const& packet) = 0;
|
||||
|
||||
virtual bool writePackets(const RawPacketVector& packets) = 0;
|
||||
|
||||
using IFileDevice::open;
|
||||
virtual bool open(bool appendMode) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PcapFileWriterDevice
|
||||
* A class for opening a pcap file for writing or create a new pcap file and write packets to it. This class adds
|
||||
* a unique capability that isn't supported in WinPcap and in older libpcap versions which is to open a pcap file
|
||||
* in append mode where packets are written at the end of the pcap file instead of running it over
|
||||
*/
|
||||
class PcapFileWriterDevice : public IFileWriterDevice
|
||||
{
|
||||
private:
|
||||
pcap_dumper_t* m_PcapDumpHandler;
|
||||
LinkLayerType m_PcapLinkLayerType;
|
||||
bool m_AppendMode;
|
||||
FILE* m_File;
|
||||
|
||||
// private copy c'tor
|
||||
PcapFileWriterDevice(const PcapFileWriterDevice& other);
|
||||
PcapFileWriterDevice& operator=(const PcapFileWriterDevice& other);
|
||||
|
||||
void closeFile();
|
||||
|
||||
public:
|
||||
/**
|
||||
* A constructor for this class that gets the pcap full path file name to open for writing or create. Notice that after calling this
|
||||
* constructor the file isn't opened yet, so writing packets will fail. For opening the file call open()
|
||||
* @param[in] fileName The full path of the file
|
||||
* @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is Ethernet
|
||||
*/
|
||||
PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET);
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
~PcapFileWriterDevice() {}
|
||||
|
||||
/**
|
||||
* Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change the
|
||||
* written packet
|
||||
* @param[in] packet A reference for an existing RawPcket to write to the file
|
||||
* @return True if a packet was written successfully. False will be returned if the file isn't opened
|
||||
* or if the packet link layer type is different than the one defined for the file
|
||||
* (in all cases, an error will be printed to log)
|
||||
*/
|
||||
bool writePacket(RawPacket const& packet);
|
||||
|
||||
/**
|
||||
* Write multiple RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change
|
||||
* the written packets or the RawPacketVector instance
|
||||
* @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file
|
||||
* @return True if all packets were written successfully to the file. False will be returned if the file isn't opened (also, an error
|
||||
* log will be printed) or if at least one of the packets wasn't written successfully to the file
|
||||
*/
|
||||
bool writePackets(const RawPacketVector& packets);
|
||||
|
||||
//override methods
|
||||
|
||||
/**
|
||||
* Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
|
||||
* overwritten, meaning all its current content will be deleted
|
||||
* @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason
|
||||
* (an error will be printed to log)
|
||||
*/
|
||||
virtual bool open();
|
||||
|
||||
/**
|
||||
* Same as open(), but enables to open the file in append mode in which packets will be appended to the file
|
||||
* instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
|
||||
* @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
|
||||
* this method will act exactly like open(). If set to true, file will be opened in append mode
|
||||
* @return True of managed to open the file successfully. In case appendMode is set to true, false will be returned
|
||||
* if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in c'tor is
|
||||
* different from current file link type. In case appendMode is set to false, please refer to open() for return
|
||||
* values
|
||||
*/
|
||||
bool open(bool appendMode);
|
||||
|
||||
/**
|
||||
* Flush and close the pacp file
|
||||
*/
|
||||
virtual void close();
|
||||
|
||||
/**
|
||||
* Flush packets to disk.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Get statistics of packets written so far.
|
||||
* @param[out] stats The stats struct where stats are returned
|
||||
*/
|
||||
virtual void getStatistics(PcapStats& stats) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class PcapNgFileWriterDevice
|
||||
* A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This class adds
|
||||
* unique capabilities such as writing metadata attributes into the file header, adding comments per packet and opening
|
||||
* the file in append mode where packets are added to a file instead of overriding it. This capabilities are part of the
|
||||
* pcap-ng standard but aren't supported in most tools and libraries
|
||||
*/
|
||||
class PcapNgFileWriterDevice : public IFileWriterDevice
|
||||
{
|
||||
private:
|
||||
void* m_LightPcapNg;
|
||||
int m_CompressionLevel;
|
||||
BpfFilterWrapper m_BpfWrapper;
|
||||
|
||||
// private copy c'tor
|
||||
PcapNgFileWriterDevice(const PcapFileWriterDevice& other);
|
||||
PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice that after calling this
|
||||
* constructor the file isn't opened yet, so writing packets will fail. For opening the file call open()
|
||||
* @param[in] fileName The full path of the file
|
||||
* @param[in] compressionLevel The compression level to use when writing the file, use 0 to disable compression or 10 for max compression. Default is 0
|
||||
*/
|
||||
PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel = 0);
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~PcapNgFileWriterDevice() { close(); }
|
||||
|
||||
/**
|
||||
* Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
|
||||
* overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows writing several
|
||||
* metadata attributes that will be stored in the header of the file
|
||||
* @param[in] os A string describing the operating system that was used to capture the packets. If this string is empty or null it
|
||||
* will be ignored
|
||||
* @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is empty or null it
|
||||
* will be ignored
|
||||
* @param[in] captureApp A string describing the application that was used to capture the packets. If this string is empty or null it
|
||||
* will be ignored
|
||||
* @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the file.
|
||||
* If this string is empty or null it will be ignored
|
||||
* @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason
|
||||
* (an error will be printed to log)
|
||||
*/
|
||||
bool open(const std::string& os, const std::string& hardware, const std::string& captureApp, const std::string& fileComment);
|
||||
|
||||
/**
|
||||
* The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a RawPacket to the file and
|
||||
* adds a comment to it. Before using this method please verify the file is opened using open(). This method won't change the
|
||||
* written packet or the input comment
|
||||
* @param[in] packet A reference for an existing RawPcket to write to the file
|
||||
* @param[in] comment The comment to be written for the packet. If this string is empty or null it will be ignored
|
||||
* @return True if a packet was written successfully. False will be returned if the file isn't opened (an error will be printed to log)
|
||||
*/
|
||||
bool writePacket(RawPacket const& packet, const std::string& comment);
|
||||
|
||||
//overridden methods
|
||||
|
||||
/**
|
||||
* Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change the
|
||||
* written packet
|
||||
* @param[in] packet A reference for an existing RawPcket to write to the file
|
||||
* @return True if a packet was written successfully. False will be returned if the file isn't opened (an error will be printed to log)
|
||||
*/
|
||||
bool writePacket(RawPacket const& packet);
|
||||
|
||||
/**
|
||||
* Write multiple RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change
|
||||
* the written packets or the RawPacketVector instance
|
||||
* @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file
|
||||
* @return True if all packets were written successfully to the file. False will be returned if the file isn't opened (also, an error
|
||||
* log will be printed) or if at least one of the packets wasn't written successfully to the file
|
||||
*/
|
||||
bool writePackets(const RawPacketVector& packets);
|
||||
|
||||
/**
|
||||
* Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
|
||||
* overwritten, meaning all its current content will be deleted
|
||||
* @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason
|
||||
* (an error will be printed to log)
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Same as open(), but enables to open the file in append mode in which packets will be appended to the file
|
||||
* instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
|
||||
* @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
|
||||
* this method will act exactly like open(). If set to true, file will be opened in append mode
|
||||
* @return True of managed to open the file successfully. In case appendMode is set to true, false will be returned
|
||||
* if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to false, please refer to open()
|
||||
* for return values
|
||||
*/
|
||||
bool open(bool appendMode);
|
||||
|
||||
/**
|
||||
* Flush packets to the pcap-ng file
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Flush and close the pcap-ng file
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Get statistics of packets written so far.
|
||||
* @param[out] stats The stats struct where stats are returned
|
||||
*/
|
||||
void getStatistics(PcapStats& stats) const;
|
||||
|
||||
/**
|
||||
* Set a filter for PcapNG writer device. Only packets that match the filter will be persisted
|
||||
* @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)
|
||||
* @return True if filter set successfully, false otherwise
|
||||
*/
|
||||
bool setFilter(std::string filterAsString);
|
||||
|
||||
};
|
||||
|
||||
}// namespace pcpp
|
||||
|
||||
#endif
|
||||
803
pcappp/include/pcapplusplus/PcapFilter.h
Normal file
803
pcappp/include/pcapplusplus/PcapFilter.h
Normal file
@@ -0,0 +1,803 @@
|
||||
#ifndef PCAPP_FILTER
|
||||
#define PCAPP_FILTER
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "ProtocolType.h"
|
||||
#include <stdint.h>
|
||||
#include "ArpLayer.h"
|
||||
#include "RawPacket.h"
|
||||
|
||||
//Forward Declaration - used in GeneralFilter
|
||||
struct bpf_program;
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Most packet capture engines contain packet filtering capabilities. In order to set the filters there should be a known syntax user can use.
|
||||
* The most popular syntax is Berkeley Packet Filter (BPF) - see more in here: http://en.wikipedia.org/wiki/Berkeley_Packet_Filter.
|
||||
* Detailed explanation of the syntax can be found here: http://www.tcpdump.org/manpages/pcap-filter.7.html.<BR>
|
||||
* The problem with BPF is that, for my opinion, the syntax is too complicated and too poorly documented. In addition the BPF filter compilers
|
||||
* may output syntax errors that are hard to understand. My experience with BPF was not good, so I decided to make the filters mechanism more
|
||||
* structured, easier to understand and less error-prone by creating classes that represent filters. Each possible filter phrase is represented
|
||||
* by a class. The filter, at the end, is that class.<BR>
|
||||
* For example: the filter "src host 1.1.1.1" will be represented by IPFilter instance; "dst port 80" will be represented by PortFilter, and
|
||||
* so on.<BR>
|
||||
* So what about complex filters that involve "and", "or"? There are also 2 classes: AndFilter and OrFilter that can store more filters (in a
|
||||
* composite idea) and connect them by "and" or "or". For example: "src host 1.1.1.1 and dst port 80" will be represented by an AndFilter that
|
||||
* h olds IPFilter and PortFilter inside it
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
//Forward Declaration - used in GeneralFilter
|
||||
class RawPacket;
|
||||
|
||||
/**
|
||||
* An enum that contains direction (source or destination)
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Source */
|
||||
SRC,
|
||||
/** Destination */
|
||||
DST,
|
||||
/** Source or destination */
|
||||
SRC_OR_DST
|
||||
} Direction;
|
||||
|
||||
|
||||
/**
|
||||
* Supported operators enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Equals */
|
||||
EQUALS,
|
||||
/** Not equals */
|
||||
NOT_EQUALS,
|
||||
/** Greater than */
|
||||
GREATER_THAN,
|
||||
/** Greater or equal */
|
||||
GREATER_OR_EQUAL,
|
||||
/** Less than */
|
||||
LESS_THAN,
|
||||
/** Less or equal */
|
||||
LESS_OR_EQUAL
|
||||
} FilterOperator;
|
||||
|
||||
/**
|
||||
* @class BpfFilterWrapper
|
||||
* A wrapper class for BPF filtering. Enables setting a BPF filter and matching it against a packet
|
||||
*/
|
||||
class BpfFilterWrapper
|
||||
{
|
||||
private:
|
||||
std::string m_FilterStr;
|
||||
LinkLayerType m_LinkType;
|
||||
bpf_program* m_Program;
|
||||
|
||||
void freeProgram();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
*/
|
||||
BpfFilterWrapper();
|
||||
|
||||
/**
|
||||
* A d'tor for this class. Makes sure to clear the bpf_program object if was previously set.
|
||||
*/
|
||||
~BpfFilterWrapper();
|
||||
|
||||
/**
|
||||
* Set a filter. This method receives a filter in BPF syntax (https://biot.com/capstats/bpf.html) and an optional link type,
|
||||
* compiles them, and if compilation is successful it stores the filter.
|
||||
* @param[in] filter A filter in BPF syntax
|
||||
* @param[in] linkType An optional parameter to set the filter's link type. The default is LINKTYPE_ETHERNET
|
||||
* @return True if compilation is successful and filter is stored in side this object, false otherwise
|
||||
*/
|
||||
bool setFilter(const std::string& filter, LinkLayerType linkType = LINKTYPE_ETHERNET);
|
||||
|
||||
/**
|
||||
* Match a packet with the filter stored in this object. If the filter is empty the method returns "true".
|
||||
* If the link type of the raw packet is different than the one set in setFilter(), the filter will be
|
||||
* re-compiled and stored in the object.
|
||||
* @param[in] rawPacket A pointer to a raw packet which the filter will be matched against
|
||||
* @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter
|
||||
* could not be compiled
|
||||
*/
|
||||
bool matchPacketWithFilter(const RawPacket* rawPacket);
|
||||
|
||||
/**
|
||||
* Match a packet data with the filter stored in this object. If the filter is empty the method returns "true".
|
||||
* If the link type provided is different than the one set in setFilter(), the filter will be re-compiled
|
||||
* and stored in the object.
|
||||
* @param[in] packetData A byte stream containing the packet data
|
||||
* @param[in] packetDataLength The length in [bytes] of the byte stream
|
||||
* @param[in] packetTimestamp The packet timestamp
|
||||
* @param[in] linkType The packet link type
|
||||
* @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter
|
||||
* could not be compiled
|
||||
*/
|
||||
bool matchPacketWithFilter(const uint8_t* packetData, uint32_t packetDataLength, timespec packetTimestamp, uint16_t linkType);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class GeneralFilter
|
||||
* The base class for all filter classes. This class is virtual and abstract, hence cannot be instantiated.<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class GeneralFilter
|
||||
{
|
||||
protected:
|
||||
BpfFilterWrapper m_BpfWrapper;
|
||||
|
||||
public:
|
||||
/**
|
||||
* A method that parses the class instance into BPF string format
|
||||
* @param[out] result An empty string that the parsing will be written into. If the string isn't empty, its content will be overridden
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void parseToString(std::string& result) = 0;
|
||||
|
||||
/**
|
||||
* Match a raw packet with a given BPF filter.
|
||||
* @param[in] rawPacket A pointer to the raw packet to match the BPF filter with
|
||||
* @return True if a raw packet matches the BPF filter or false otherwise
|
||||
*/
|
||||
bool matchPacketWithFilter(RawPacket* rawPacket);
|
||||
|
||||
GeneralFilter() {}
|
||||
|
||||
/**
|
||||
* Virtual destructor, frees the bpf program
|
||||
*/
|
||||
virtual ~GeneralFilter() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BPFStringFilter
|
||||
* This class can be loaded with a BPF filter string and then can be used to verify the string is valid.<BR>
|
||||
*/
|
||||
class BPFStringFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
const std::string m_FilterStr;
|
||||
|
||||
public:
|
||||
BPFStringFilter(const std::string& filterStr) : m_FilterStr(filterStr) {}
|
||||
|
||||
virtual ~BPFStringFilter() {}
|
||||
|
||||
/**
|
||||
* A method that parses the class instance into BPF string format
|
||||
* @param[out] result An empty string that the parsing will be written into. If the string isn't empty, its content will be overridden
|
||||
* If the filter is not valid the result will be an empty string
|
||||
* @return No return value
|
||||
*/
|
||||
virtual void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Verify the filter is valid
|
||||
* @return True if the filter is valid or false otherwise
|
||||
*/
|
||||
bool verifyFilter();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IFilterWithDirection
|
||||
* An abstract class that is the base class for all filters which contain a direction (source or destination). This class cannot be instantiated<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class IFilterWithDirection : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
Direction m_Dir;
|
||||
protected:
|
||||
void parseDirection(std::string& directionAsString);
|
||||
Direction getDir() const { return m_Dir; }
|
||||
IFilterWithDirection(Direction dir) { m_Dir = dir; }
|
||||
public:
|
||||
/**
|
||||
* Set the direction for the filter (source or destination)
|
||||
* @param[in] dir The direction
|
||||
*/
|
||||
void setDirection(Direction dir) { m_Dir = dir; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class IFilterWithOperator
|
||||
* An abstract class that is the base class for all filters which contain an operator (e.g X equals Y; A is greater than B; Z1 not equals Z2, etc.).
|
||||
* This class cannot be instantiated<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class IFilterWithOperator : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
FilterOperator m_Operator;
|
||||
protected:
|
||||
std::string parseOperator();
|
||||
FilterOperator getOperator() const { return m_Operator; }
|
||||
IFilterWithOperator(FilterOperator op) { m_Operator = op; }
|
||||
public:
|
||||
/**
|
||||
* Set the operator for the filter
|
||||
* @param[in] op The operator to set
|
||||
*/
|
||||
void setOperator(FilterOperator op) { m_Operator = op; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPFilter
|
||||
* A class for representing IPv4 address filter, equivalent to "net src x.x.x.x" or "net dst x.x.x.x"<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
* @todo Add IPv6 filtering support
|
||||
*/
|
||||
class IPFilter : public IFilterWithDirection
|
||||
{
|
||||
private:
|
||||
std::string m_Address;
|
||||
std::string m_IPv4Mask;
|
||||
int m_Len;
|
||||
void convertToIPAddressWithMask(std::string& ipAddrmodified, std::string& mask) const;
|
||||
void convertToIPAddressWithLen(std::string& ipAddrmodified) const;
|
||||
public:
|
||||
/**
|
||||
* The basic constructor that creates the filter from an IPv4 address and direction (source or destination)
|
||||
* @param[in] ipAddress The IPv4 address to build the filter with. If this address is not a valid IPv4 address an error will be
|
||||
* written to log and parsing this filter will fail
|
||||
* @param[in] dir The address direction to filter (source or destination)
|
||||
*/
|
||||
IPFilter(const std::string& ipAddress, Direction dir) : IFilterWithDirection(dir), m_Address(ipAddress), m_IPv4Mask(""), m_Len(0) {}
|
||||
|
||||
/**
|
||||
* A constructor that enable to filter only part of the address by using a mask (aka subnet). For example: "filter only IP addresses that matches
|
||||
* the subnet 10.0.0.x"
|
||||
* @param[in] ipAddress The IPv4 address to use. Only the part of the address that is not masked will be matched. For example: if the address
|
||||
* is "1.2.3.4" and the mask is "255.255.255.0" than the part of the address that will be matched is "1.2.3.X". If this address is not a
|
||||
* valid IPv4 address an error will be written to log and parsing this filter will fail
|
||||
* @param[in] dir The address direction to filter (source or destination)
|
||||
* @param[in] ipv4Mask The mask to use. Mask should also be in a valid IPv4 format (i.e x.x.x.x), otherwise parsing this filter will fail
|
||||
*/
|
||||
IPFilter(const std::string& ipAddress, Direction dir, const std::string& ipv4Mask) : IFilterWithDirection(dir), m_Address(ipAddress), m_IPv4Mask(ipv4Mask), m_Len(0) {}
|
||||
|
||||
/**
|
||||
* A constructor that enables to filter by a subnet. For example: "filter only IP addresses that matches the subnet 10.0.0.3/24" which means
|
||||
* the part of the address that will be matched is "10.0.0.X"
|
||||
* @param[in] ipAddress The IPv4 address to use. Only the part of the address that is not masked will be matched. For example: if the address
|
||||
* is "1.2.3.4" and the subnet is "/24" than the part of the address that will be matched is "1.2.3.X". If this address is not a
|
||||
* valid IPv4 address an error will be written to log and parsing this filter will fail
|
||||
* @param[in] dir The address direction to filter (source or destination)
|
||||
* @param[in] len The subnet to use (e.g "/24")
|
||||
*/
|
||||
IPFilter(const std::string& ipAddress, Direction dir, int len) : IFilterWithDirection(dir), m_Address(ipAddress), m_IPv4Mask(""), m_Len(len) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the IPv4 address
|
||||
* @param[in] ipAddress The IPv4 address to build the filter with. If this address is not a valid IPv4 address an error will be
|
||||
* written to log and parsing this filter will fail
|
||||
*/
|
||||
void setAddr(const std::string& ipAddress) { m_Address = ipAddress; }
|
||||
|
||||
/**
|
||||
* Set the IPv4 mask
|
||||
* @param[in] ipv4Mask The mask to use. Mask should also be in a valid IPv4 format (i.e x.x.x.x), otherwise parsing this filter will fail
|
||||
*/
|
||||
void setMask(const std::string& ipv4Mask) { m_IPv4Mask = ipv4Mask; m_Len = 0; }
|
||||
|
||||
/**
|
||||
* Set the subnet
|
||||
* @param[in] len The subnet to use (e.g "/24")
|
||||
*/
|
||||
void setLen(int len) { m_IPv4Mask = ""; m_Len = len; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4IDFilter
|
||||
* A class for filtering IPv4 traffic by IP ID field of the IPv4 protocol, For example:
|
||||
* "filter only IPv4 traffic which IP ID is greater than 1234"<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class IPv4IDFilter : public IFilterWithOperator
|
||||
{
|
||||
private:
|
||||
uint16_t m_IpID;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the IP ID to filter and the operator and creates the filter out of them
|
||||
* @param[in] ipID The IP ID to filter
|
||||
* @param[in] op The operator to use (e.g "equal", "greater than", etc.)
|
||||
*/
|
||||
IPv4IDFilter(uint16_t ipID, FilterOperator op) : IFilterWithOperator(op), m_IpID(ipID) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the IP ID to filter
|
||||
* @param[in] ipID The IP ID to filter
|
||||
*/
|
||||
void setIpID(uint16_t ipID) { m_IpID = ipID; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class IPv4TotalLengthFilter
|
||||
* A class for filtering IPv4 traffic by "total length" field of the IPv4 protocol, For example:
|
||||
* "filter only IPv4 traffic which "total length" value is less than 60B"<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class IPv4TotalLengthFilter : public IFilterWithOperator
|
||||
{
|
||||
private:
|
||||
uint16_t m_TotalLength;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the total length to filter and the operator and creates the filter out of them
|
||||
* @param[in] totalLength The total length value to filter
|
||||
* @param[in] op The operator to use (e.g "equal", "greater than", etc.)
|
||||
*/
|
||||
IPv4TotalLengthFilter(uint16_t totalLength, FilterOperator op) : IFilterWithOperator(op), m_TotalLength(totalLength) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the total length value
|
||||
* @param[in] totalLength The total length value to filter
|
||||
*/
|
||||
void setTotalLength(uint16_t totalLength) { m_TotalLength = totalLength; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class PortFilter
|
||||
* A class for filtering TCP or UDP traffic by port, for example: "dst port 80" or "src port 12345"<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class PortFilter : public IFilterWithDirection
|
||||
{
|
||||
private:
|
||||
std::string m_Port;
|
||||
void portToString(uint16_t portAsInt);
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the port and the direction and creates the filter
|
||||
* @param[in] port The port to create the filter with
|
||||
* @param[in] dir The port direction to filter (source or destination)
|
||||
*/
|
||||
PortFilter(uint16_t port, Direction dir);
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the port
|
||||
* @param[in] port The port to create the filter with
|
||||
*/
|
||||
void setPort(uint16_t port) { portToString(port); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class PortRangeFilter
|
||||
* A class for filtering TCP or UDP port ranges, meaning match only packets which port is within this range, for example: "src portrange 1000-2000"
|
||||
* will match only TCP or UDP traffic which source port is in the range of 1000 - 2000<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class PortRangeFilter : public IFilterWithDirection
|
||||
{
|
||||
private:
|
||||
uint16_t m_FromPort;
|
||||
uint16_t m_ToPort;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the port range the the direction and creates the filter with them
|
||||
* @param[in] fromPort The lower end of the port range
|
||||
* @param[in] toPort The higher end of the port range
|
||||
* @param[in] dir The port range direction to filter (source or destination)
|
||||
*/
|
||||
PortRangeFilter(uint16_t fromPort, uint16_t toPort, Direction dir) : IFilterWithDirection(dir), m_FromPort(fromPort), m_ToPort(toPort) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the lower end of the port range
|
||||
* @param[in] fromPort The lower end of the port range
|
||||
*/
|
||||
void setFromPort(uint16_t fromPort) { m_FromPort = fromPort; }
|
||||
|
||||
/**
|
||||
* Set the higher end of the port range
|
||||
* @param[in] toPort The higher end of the port range
|
||||
*/
|
||||
void setToPort(uint16_t toPort) { m_ToPort = toPort; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class MacAddressFilter
|
||||
* A class for filtering Ethernet traffic by MAC addresses, for example: "ether src 12:34:56:78:90:12" or "ether dst "10:29:38:47:56:10:29"<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class MacAddressFilter : public IFilterWithDirection
|
||||
{
|
||||
private:
|
||||
MacAddress m_MacAddress;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the MAC address and the direction and creates the filter with them
|
||||
* @param[in] address The MAC address to use for filtering
|
||||
* @param[in] dir The MAC address direction to filter (source or destination)
|
||||
*/
|
||||
MacAddressFilter(MacAddress address, Direction dir) : IFilterWithDirection(dir), m_MacAddress(address) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the MAC address
|
||||
* @param[in] address The MAC address to use for filtering
|
||||
*/
|
||||
void setMacAddress(MacAddress address) { m_MacAddress = address; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class EtherTypeFilter
|
||||
* A class for filtering by EtherType field of the Ethernet protocol. This enables to filter packets from certain protocols, such as ARP, IPv4,
|
||||
* IPv6, VLAN tags, etc.<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class EtherTypeFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
uint16_t m_EtherType;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the EtherType and creates the filter with it
|
||||
* @param[in] etherType The EtherType value to create the filter with
|
||||
*/
|
||||
EtherTypeFilter(uint16_t etherType) : m_EtherType(etherType) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the EtherType value
|
||||
* @param[in] etherType The EtherType value to create the filter with
|
||||
*/
|
||||
void setEtherType(uint16_t etherType) { m_EtherType = etherType; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class AndFilter
|
||||
* A class for connecting several filters into one filter with logical "and" between them. For example: if the 2 filters are: "IPv4 address =
|
||||
* x.x.x.x" + "TCP port dst = 80", then the new filter will be: "IPv4 address = x.x.x.x _AND_ TCP port dst = 80"<BR>
|
||||
* This class follows the composite design pattern<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
* @todo add some methods: "addFilter", "removeFilter", "clearAllFilter"
|
||||
*/
|
||||
class AndFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
std::vector<GeneralFilter*> m_FilterList;
|
||||
public:
|
||||
|
||||
/**
|
||||
* An empty constructor for this class. Use addFilter() to add filters to the and condition
|
||||
*/
|
||||
AndFilter() {}
|
||||
|
||||
/**
|
||||
* A constructor that gets a list of pointers to filters and creates one filter from all filters with logical "and" between them
|
||||
* @param[in] filters The list of pointers to filters
|
||||
*/
|
||||
AndFilter(std::vector<GeneralFilter*>& filters);
|
||||
|
||||
/**
|
||||
* Add filter to the and condition
|
||||
* @param[in] filter The filter to add
|
||||
*/
|
||||
void addFilter(GeneralFilter* filter) { m_FilterList.push_back(filter); }
|
||||
|
||||
/**
|
||||
* Remove the current filters and set new ones
|
||||
* @param[in] filters The new filters to set. The previous ones will be removed
|
||||
*/
|
||||
void setFilters(std::vector<GeneralFilter*>& filters);
|
||||
|
||||
void parseToString(std::string& result);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class OrFilter
|
||||
* A class for connecting several filters into one filter with logical "or" between them. For example: if the 2 filters are: "IPv4 address =
|
||||
* x.x.x.x" + "TCP port dst = 80", then the new filter will be: "IPv4 address = x.x.x.x _OR_ TCP port dst = 80"<BR>
|
||||
* This class follows the composite design pattern<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
* @todo add some methods: "addFilter", "removeFilter", "clearAllFilter"
|
||||
*/
|
||||
class OrFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
std::vector<GeneralFilter*> m_FilterList;
|
||||
public:
|
||||
|
||||
/**
|
||||
* An empty constructor for this class. Use addFilter() to add filters to the or condition
|
||||
*/
|
||||
OrFilter() {}
|
||||
|
||||
/**
|
||||
* A constructor that gets a list of pointers to filters and creates one filter from all filters with logical "or" between them
|
||||
* @param[in] filters The list of pointers to filters
|
||||
*/
|
||||
OrFilter(std::vector<GeneralFilter*>& filters);
|
||||
|
||||
/**
|
||||
* Add filter to the or condition
|
||||
* @param[in] filter The filter to add
|
||||
*/
|
||||
void addFilter(GeneralFilter* filter) { m_FilterList.push_back(filter); }
|
||||
|
||||
void parseToString(std::string& result);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class NotFilter
|
||||
* A class for creating a filter which is inverse to another filter<BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class NotFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
GeneralFilter* m_FilterToInverse;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets a pointer to a filter and create the inverse version of it
|
||||
* @param[in] filterToInverse A pointer to filter which the created filter be the inverse of
|
||||
*/
|
||||
NotFilter(GeneralFilter* filterToInverse) { m_FilterToInverse = filterToInverse; }
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set a filter to create an inverse filter from
|
||||
* @param[in] filterToInverse A pointer to filter which the created filter be the inverse of
|
||||
*/
|
||||
void setFilter(GeneralFilter* filterToInverse) { m_FilterToInverse = filterToInverse; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class ProtoFilter
|
||||
* A class for filtering traffic by protocol. Notice not all protocols are supported, only the following are supported:
|
||||
* ::TCP, ::UDP, ::ICMP, ::VLAN, ::IPv4, ::IPv6, ::ARP, ::Ethernet, ::GRE (distinguish between ::GREv0 and ::GREv1 is not supported),
|
||||
* ::IGMP (distinguish between ::IGMPv1, ::IGMPv2 and ::IGMPv3 is not supported). <BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class ProtoFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
ProtocolType m_Proto;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets the protocol and creates the filter
|
||||
* @param[in] proto The protocol to filter, only packets matching this protocol will be received. Please note not all protocols are
|
||||
* supported. List of supported protocols is found in the class description
|
||||
*/
|
||||
ProtoFilter(ProtocolType proto) { m_Proto = proto; }
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the protocol to filter with
|
||||
* @param[in] proto The protocol to filter, only packets matching this protocol will be received. Please note not all protocols are
|
||||
* supported. List of supported protocols is found in the class description
|
||||
*/
|
||||
void setProto(ProtocolType proto) { m_Proto = proto; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class ArpFilter
|
||||
* A class for filtering ARP packets according the ARP opcode. When using this filter only ARP packets with the relevant opcode will be
|
||||
* received <BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class ArpFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
ArpOpcode m_OpCode;
|
||||
public:
|
||||
/**
|
||||
* A constructor that get the ARP opcode and creates the filter
|
||||
* @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY
|
||||
*/
|
||||
ArpFilter(ArpOpcode opCode) { m_OpCode = opCode; }
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the ARP opcode
|
||||
* @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY
|
||||
*/
|
||||
void setOpCode(ArpOpcode opCode) { m_OpCode = opCode; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class VlanFilter
|
||||
* A class for filtering VLAN tagged packets by VLAN ID. When using this filter only packets tagged with VLAN which has the specific VLAN ID
|
||||
* will be received <BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class VlanFilter : public GeneralFilter
|
||||
{
|
||||
private:
|
||||
uint16_t m_VlanID;
|
||||
public:
|
||||
/**
|
||||
* A constructor the gets the VLAN ID and creates the filter
|
||||
* @param[in] vlanId The VLAN ID to use for the filter
|
||||
*/
|
||||
VlanFilter(uint16_t vlanId) : m_VlanID(vlanId) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set the VLAN ID of the filter
|
||||
* @param[in] vlanId The VLAN ID to use for the filter
|
||||
*/
|
||||
void setVlanID(uint16_t vlanId) { m_VlanID = vlanId; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpFlagsFilter
|
||||
* A class for filtering only TCP packets which certain TCP flags are set in them <BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class TcpFlagsFilter : public GeneralFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* An enum of all TCP flags that can be use in the filter
|
||||
*/
|
||||
enum TcpFlags
|
||||
{
|
||||
/** TCP FIN flag */
|
||||
tcpFin = 1,
|
||||
/** TCP SYN flag */
|
||||
tcpSyn = 2,
|
||||
/** TCP RST flag */
|
||||
tcpRst = 4,
|
||||
/** TCP PSH flag */
|
||||
tcpPush = 8,
|
||||
/** TCP ACK flag */
|
||||
tcpAck = 16,
|
||||
/** TCP URG flag */
|
||||
tcpUrg = 32
|
||||
};
|
||||
|
||||
/**
|
||||
* An enum for representing 2 type of matches: match only packets that contain all flags defined in the filter or match packets that
|
||||
* contain at least one of the flags defined in the filter
|
||||
*/
|
||||
enum MatchOptions
|
||||
{
|
||||
/** Match only packets that contain all flags defined in the filter */
|
||||
MatchAll,
|
||||
/** Match packets that contain at least one of the flags defined in the filter */
|
||||
MatchOneAtLeast
|
||||
};
|
||||
private:
|
||||
uint8_t m_TcpFlagsBitMask;
|
||||
MatchOptions m_MatchOption;
|
||||
public:
|
||||
/**
|
||||
* A constructor that gets a 1-byte bitmask containing all TCP flags participating in the filter and the match option, and
|
||||
* creates the filter
|
||||
* @param[in] tcpFlagBitMask A 1-byte bitmask containing all TCP flags participating in the filter. This parameter can contain the
|
||||
* following value for example: TcpFlagsFilter::tcpSyn | TcpFlagsFilter::tcpAck | TcpFlagsFilter::tcpUrg
|
||||
* @param[in] matchOption The match option: TcpFlagsFilter::MatchAll or TcpFlagsFilter::MatchOneAtLeast
|
||||
*/
|
||||
TcpFlagsFilter(uint8_t tcpFlagBitMask, MatchOptions matchOption) : m_TcpFlagsBitMask(tcpFlagBitMask), m_MatchOption(matchOption) {}
|
||||
|
||||
/**
|
||||
* Set the TCP flags and the match option
|
||||
* @param[in] tcpFlagBitMask A 1-byte bitmask containing all TCP flags participating in the filter. This parameter can contain the
|
||||
* following value for example: TcpFlagsFilter::tcpSyn | TcpFlagsFilter::tcpAck | TcpFlagsFilter::tcpUrg
|
||||
* @param[in] matchOption The match option: TcpFlagsFilter::MatchAll or TcpFlagsFilter::MatchOneAtLeast
|
||||
*/
|
||||
void setTcpFlagsBitMask(uint8_t tcpFlagBitMask, MatchOptions matchOption) { m_TcpFlagsBitMask = tcpFlagBitMask; m_MatchOption = matchOption; }
|
||||
|
||||
void parseToString(std::string& result);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpWindowSizeFilter
|
||||
* A class for filtering TCP packets that matches TCP window-size criteria <BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class TcpWindowSizeFilter : public IFilterWithOperator
|
||||
{
|
||||
private:
|
||||
uint16_t m_WindowSize;
|
||||
public:
|
||||
/**
|
||||
* A constructor that get the window-size and operator and creates the filter. For example: "filter all TCP packets with window-size
|
||||
* less than 1000"
|
||||
* @param[in] windowSize The window-size value that will be used in the filter
|
||||
* @param[in] op The operator to use (e.g "equal", "greater than", etc.)
|
||||
*/
|
||||
TcpWindowSizeFilter(uint16_t windowSize, FilterOperator op) : IFilterWithOperator(op), m_WindowSize(windowSize) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set window-size value
|
||||
* @param[in] windowSize The window-size value that will be used in the filter
|
||||
*/
|
||||
void setWindowSize(uint16_t windowSize) { m_WindowSize = windowSize; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class UdpLengthFilter
|
||||
* A class for filtering UDP packets that matches UDP length criteria <BR>
|
||||
* For deeper understanding of the filter concept please refer to PcapFilter.h
|
||||
*/
|
||||
class UdpLengthFilter : public IFilterWithOperator
|
||||
{
|
||||
private:
|
||||
uint16_t m_Length;
|
||||
public:
|
||||
/**
|
||||
* A constructor that get the UDP length and operator and creates the filter. For example: "filter all UDP packets with length
|
||||
* greater or equal to 500"
|
||||
* @param[in] length The length value that will be used in the filter
|
||||
* @param[in] op The operator to use (e.g "equal", "greater than", etc.)
|
||||
*/
|
||||
UdpLengthFilter(uint16_t length, FilterOperator op) : IFilterWithOperator(op), m_Length(length) {}
|
||||
|
||||
void parseToString(std::string& result);
|
||||
|
||||
/**
|
||||
* Set length value
|
||||
* @param[in] length The length value that will be used in the filter
|
||||
*/
|
||||
void setLength(uint16_t length) { m_Length = length; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif
|
||||
556
pcappp/include/pcapplusplus/PcapLiveDevice.h
Normal file
556
pcappp/include/pcapplusplus/PcapLiveDevice.h
Normal file
@@ -0,0 +1,556 @@
|
||||
//TODO: replace all these defines with #pragma once
|
||||
#ifndef PCAPPP_LIVE_DEVICE
|
||||
#define PCAPPP_LIVE_DEVICE
|
||||
|
||||
#include "PcapDevice.h"
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include "IpAddress.h"
|
||||
#include "Packet.h"
|
||||
|
||||
// forward declarations for structs and typedefs that are defined in pcap.h
|
||||
struct pcap_if;
|
||||
typedef pcap_if pcap_if_t;
|
||||
struct pcap_addr;
|
||||
typedef struct pcap_addr pcap_addr_t;
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
class PcapLiveDevice;
|
||||
|
||||
/**
|
||||
* @typedef OnPacketArrivesCallback
|
||||
* A callback that is called when a packet is captured by PcapLiveDevice
|
||||
* @param[in] pPacket A pointer to the raw packet
|
||||
* @param[in] pDevice A pointer to the PcapLiveDevice instance
|
||||
* @param[in] userCookie A pointer to the object put by the user when packet capturing stared
|
||||
*/
|
||||
typedef void (*OnPacketArrivesCallback)(RawPacket* pPacket, PcapLiveDevice* pDevice, void* userCookie);
|
||||
|
||||
/**
|
||||
* @typedef OnPacketArrivesStopBlocking
|
||||
* A callback that is called when a packet is captured by PcapLiveDevice
|
||||
* @param[in] pPacket A pointer to the raw packet
|
||||
* @param[in] pDevice A pointer to the PcapLiveDevice instance
|
||||
* @param[in] userCookie A pointer to the object put by the user when packet capturing stared
|
||||
* @return True when main thread should stop blocking or false otherwise
|
||||
*/
|
||||
typedef bool (*OnPacketArrivesStopBlocking)(RawPacket* pPacket, PcapLiveDevice* pDevice, void* userData);
|
||||
|
||||
|
||||
/**
|
||||
* @typedef OnStatsUpdateCallback
|
||||
* A callback that is called periodically for stats collection if user asked to start packet capturing with periodic stats collection
|
||||
* @param[in] stats A reference to the most updated stats
|
||||
* @param[in] userCookie A pointer to the object put by the user when packet capturing stared
|
||||
*/
|
||||
typedef void (*OnStatsUpdateCallback)(IPcapDevice::PcapStats& stats, void* userCookie);
|
||||
|
||||
// for internal use only
|
||||
typedef void* (*ThreadStart)(void*);
|
||||
|
||||
struct PcapThread;
|
||||
|
||||
/**
|
||||
* @class PcapLiveDevice
|
||||
* A class that wraps a network interface (each of the interfaces listed in ifconfig/ipconfig).
|
||||
* This class wraps the libpcap capabilities of capturing packets from the network, filtering packets and sending packets back to the network.
|
||||
* This class is relevant for Linux applications only. On Windows the WinPcapLiveDevice (which inherits this class) is used. Both classes are
|
||||
* almost similar in capabilities, the main difference between them is adapting some capabilities to the specific OS.
|
||||
* This class cannot be instantiated by the user (it has a private constructor), as network interfaces aren't dynamic. Instances of
|
||||
* this class (one instance per network interface) are created by PcapLiveDeviceList singleton on application startup and the user can get
|
||||
* access to them by using PcapLiveDeviceList public methods such as PcapLiveDeviceList#getPcapLiveDeviceByIp()<BR>
|
||||
* Main capabilities of this class:
|
||||
* - Get all available information for this network interfaces such as name, IP addresses, MAC address, MTU, etc. This information is taken
|
||||
* from both libpcap and the OS
|
||||
* - Capture packets from the network. Capturing is always conducted on a different thread. PcapPlusPlus creates this
|
||||
* thread when capturing starts and kills it when capturing ends. This prevents the application from being stuck while waiting for packets or
|
||||
* processing them. Currently only one capturing thread is allowed, so when the interface is in capture mode, no further capturing is allowed.
|
||||
* In addition to capturing the user can get stats on packets that were received by the application, dropped by the NIC (due to full
|
||||
* NIC buffers), etc. Stats collection can be initiated by the user by calling getStatistics() or be pushed to the user periodically by
|
||||
* supplying a callback and a timeout to startCapture()
|
||||
* - Send packets back to the network. Sending the packets is done on the caller thread. No additional threads are created for this task
|
||||
*/
|
||||
class PcapLiveDevice : public IPcapDevice
|
||||
{
|
||||
friend class PcapLiveDeviceList;
|
||||
protected:
|
||||
// This is a second descriptor for the same device. It is needed because of a bug
|
||||
// that occurs in libpcap on Linux (on Windows using WinPcap/Npcap it works well):
|
||||
// It's impossible to capture packets sent by the same descriptor
|
||||
pcap_t* m_PcapSendDescriptor;
|
||||
std::string m_Name;
|
||||
std::string m_Description;
|
||||
bool m_IsLoopback;
|
||||
uint32_t m_DeviceMtu;
|
||||
std::vector<pcap_addr_t> m_Addresses;
|
||||
MacAddress m_MacAddress;
|
||||
IPv4Address m_DefaultGateway;
|
||||
PcapThread* m_CaptureThread;
|
||||
bool m_CaptureThreadStarted;
|
||||
PcapThread* m_StatsThread;
|
||||
bool m_StatsThreadStarted;
|
||||
bool m_StopThread;
|
||||
OnPacketArrivesCallback m_cbOnPacketArrives;
|
||||
void* m_cbOnPacketArrivesUserCookie;
|
||||
OnStatsUpdateCallback m_cbOnStatsUpdate;
|
||||
void* m_cbOnStatsUpdateUserCookie;
|
||||
OnPacketArrivesStopBlocking m_cbOnPacketArrivesBlockingMode;
|
||||
void* m_cbOnPacketArrivesBlockingModeUserCookie;
|
||||
int m_IntervalToUpdateStats;
|
||||
RawPacketVector* m_CapturedPackets;
|
||||
bool m_CaptureCallbackMode;
|
||||
LinkLayerType m_LinkType;
|
||||
|
||||
// c'tor is not public, there should be only one for every interface (created by PcapLiveDeviceList)
|
||||
PcapLiveDevice(pcap_if_t* pInterface, bool calculateMTU, bool calculateMacAddress, bool calculateDefaultGateway);
|
||||
// copy c'tor is not public
|
||||
PcapLiveDevice( const PcapLiveDevice& other );
|
||||
PcapLiveDevice& operator=(const PcapLiveDevice& other);
|
||||
|
||||
void setDeviceMtu();
|
||||
void setDeviceMacAddress();
|
||||
void setDefaultGateway();
|
||||
static void* captureThreadMain(void* ptr);
|
||||
static void* statsThreadMain(void* ptr);
|
||||
static void onPacketArrives(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet);
|
||||
static void onPacketArrivesNoCallback(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet);
|
||||
static void onPacketArrivesBlockingMode(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet);
|
||||
std::string printThreadId(PcapThread* id);
|
||||
virtual ThreadStart getCaptureThreadStart();
|
||||
public:
|
||||
|
||||
/**
|
||||
* The type of the live device
|
||||
*/
|
||||
enum LiveDeviceType
|
||||
{
|
||||
/** libPcap live device */
|
||||
LibPcapDevice,
|
||||
/** WinPcap/Npcap live device */
|
||||
WinPcapDevice,
|
||||
/** WinPcap/Npcap Remote Capture device */
|
||||
RemoteDevice
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Device capturing mode
|
||||
*/
|
||||
enum DeviceMode
|
||||
{
|
||||
/** Only packets that their destination is this NIC are captured */
|
||||
Normal = 0,
|
||||
/** All packets that arrive to the NIC are captured, even packets that their destination isn't this NIC */
|
||||
Promiscuous = 1
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set direction for capturing packets (you can read more here: <https://www.tcpdump.org/manpages/pcap.3pcap.html#lbAI>)
|
||||
*/
|
||||
enum PcapDirection
|
||||
{
|
||||
/** Capture traffics both incoming and outgoing */
|
||||
PCPP_INOUT = 0,
|
||||
/** Only capture incoming traffics */
|
||||
PCPP_IN,
|
||||
/** Only capture outgoing traffics */
|
||||
PCPP_OUT
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct DeviceConfiguration
|
||||
* A struct that contains user configurable parameters for opening a device. All parameters have default values so
|
||||
* the user isn't expected to set all parameters or understand exactly how they work
|
||||
*/
|
||||
struct DeviceConfiguration
|
||||
{
|
||||
/** Indicates whether to open the device in promiscuous or normal mode */
|
||||
DeviceMode mode;
|
||||
|
||||
/** Set the packet buffer timeout in milliseconds. You can read more here:
|
||||
* https://www.tcpdump.org/manpages/pcap.3pcap.html .
|
||||
* Any value above 0 is considered legal, otherwise a value of 1 or -1 is used (depends on the platform)
|
||||
*/
|
||||
int packetBufferTimeoutMs;
|
||||
|
||||
/**
|
||||
* Set the packet buffer size. You can read more about the packet buffer here:
|
||||
* https://www.tcpdump.org/manpages/pcap.3pcap.html .
|
||||
* Any value of 100 or above is considered valid, otherwise the default value is used (which varies between different OS's).
|
||||
* However, please notice that setting values which are too low or two high may result in failure to open the device.
|
||||
* These too low or too high thresholds may vary between OS's, as an example please refer to this thread:
|
||||
* https://stackoverflow.com/questions/11397367/issue-in-pcap-set-buffer-size
|
||||
*/
|
||||
int packetBufferSize;
|
||||
|
||||
/**
|
||||
* Set the direction for capturing packets. You can read more here:
|
||||
* <https://www.tcpdump.org/manpages/pcap.3pcap.html#lbAI>.
|
||||
*/
|
||||
PcapDirection direction;
|
||||
|
||||
/**
|
||||
* Set the snapshot length. Snapshot length is the amount of data for each frame that is actually captured. Note that taking
|
||||
* larger snapshots both increases the amount of time it takes to process packets and, effectively, decreases the amount of
|
||||
* packet buffering. This may cause packets to be lost. Note also that taking smaller snapshots will discard data from protocols
|
||||
* above the transport layer, which loses information that may be important.
|
||||
* You can read more here:
|
||||
* https://wiki.wireshark.org/SnapLen
|
||||
*/
|
||||
int snapshotLength;
|
||||
|
||||
/**
|
||||
* A c'tor for this struct
|
||||
* @param[in] mode The mode to open the device: promiscuous or non-promiscuous. Default value is promiscuous
|
||||
* @param[in] packetBufferTimeoutMs Buffer timeout in millisecond. Default value is 0 which means set timeout of
|
||||
* 1 or -1 (depends on the platform)
|
||||
* @param[in] packetBufferSize The packet buffer size. Default value is 0 which means use the default value
|
||||
* (varies between different OS's)
|
||||
* @param[in] direction Direction for capturing packets. Default value is INOUT which means capture both incoming
|
||||
* and outgoing packets (not all platforms support this)
|
||||
* @param[in] snapshotLength Snapshot length for capturing packets. Default value is 0 which means use the default value.
|
||||
* A snapshot length of 262144 should be big enough for maximum-size Linux loopback packets (65549) and some USB packets
|
||||
* captured with USBPcap (> 131072, < 262144). A snapshot length of 65535 should be sufficient, on most if not all networks,
|
||||
* to capture all the data available from the packet.
|
||||
*/
|
||||
DeviceConfiguration(DeviceMode mode = Promiscuous, int packetBufferTimeoutMs = 0, int packetBufferSize = 0,
|
||||
PcapDirection direction = PCPP_INOUT, int snapshotLength = 0)
|
||||
{
|
||||
this->mode = mode;
|
||||
this->packetBufferTimeoutMs = packetBufferTimeoutMs;
|
||||
this->packetBufferSize = packetBufferSize;
|
||||
this->direction = direction;
|
||||
this->snapshotLength = snapshotLength;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A destructor for this class
|
||||
*/
|
||||
virtual ~PcapLiveDevice();
|
||||
|
||||
/**
|
||||
* @return The type of the device (libPcap, WinPcap/Npcap or a remote device)
|
||||
*/
|
||||
virtual LiveDeviceType getDeviceType() const { return LibPcapDevice; }
|
||||
|
||||
/**
|
||||
* @return The name of the device (e.g eth0), taken from pcap_if_t->name
|
||||
*/
|
||||
std::string getName() const { return m_Name; }
|
||||
|
||||
/**
|
||||
* @return A human-readable description of the device, taken from pcap_if_t->description. May be NULL in some interfaces
|
||||
*/
|
||||
std::string getDesc() const { return m_Description; }
|
||||
|
||||
/**
|
||||
* @return True if this interface is a loopback interface, false otherwise
|
||||
*/
|
||||
bool getLoopback() const { return m_IsLoopback; }
|
||||
|
||||
/**
|
||||
* @return The device's maximum transmission unit (MTU) in bytes
|
||||
*/
|
||||
virtual uint32_t getMtu() const { return m_DeviceMtu; }
|
||||
|
||||
/**
|
||||
* @return The device's link layer type
|
||||
*/
|
||||
virtual LinkLayerType getLinkType() const { return m_LinkType; }
|
||||
|
||||
/**
|
||||
* @return A vector containing all addresses defined for this interface, each in pcap_addr_t struct
|
||||
*/
|
||||
const std::vector<pcap_addr_t>& getAddresses() const { return m_Addresses; }
|
||||
|
||||
/**
|
||||
* @return The MAC address for this interface
|
||||
*/
|
||||
virtual MacAddress getMacAddress() const { return m_MacAddress; }
|
||||
|
||||
/**
|
||||
* @return The IPv4 address for this interface. If multiple IPv4 addresses are defined for this interface, the first will be picked.
|
||||
* If no IPv4 addresses are defined, a zeroed IPv4 address (IPv4Address#Zero) will be returned
|
||||
*/
|
||||
IPv4Address getIPv4Address() const;
|
||||
|
||||
/**
|
||||
* @return The default gateway defined for this interface. If no default gateway is defined, if it's not IPv4 or if couldn't extract
|
||||
* default gateway IPv4Address#Zero will be returned. If multiple gateways were defined the first one will be returned
|
||||
*/
|
||||
IPv4Address getDefaultGateway() const;
|
||||
|
||||
/**
|
||||
* @return A list of all DNS servers defined for this machine. If this list is empty it means no DNS servers were defined or they
|
||||
* couldn't be extracted from some reason. This list is created in PcapLiveDeviceList class and can be also retrieved from there.
|
||||
* This method exists for convenience - so it'll be possible to get this list from PcapLiveDevice as well
|
||||
*/
|
||||
const std::vector<IPv4Address>& getDnsServers() const;
|
||||
|
||||
/**
|
||||
* Start capturing packets on this network interface (device). Each time a packet is captured the onPacketArrives callback is called.
|
||||
* The capture is done on a new thread created by this method, meaning all callback calls are done in a thread other than the
|
||||
* caller thread. Capture process will stop and this capture thread will be terminated when calling stopCapture(). This method must be
|
||||
* called after the device is opened (i.e the open() method was called), otherwise an error will be returned.
|
||||
* @param[in] onPacketArrives A callback that is called each time a packet is captured
|
||||
* @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to the onPacketArrives callback
|
||||
* each time it is called. This cookie is very useful for transferring objects that give context to the capture callback, for example:
|
||||
* objects that counts packets, manages flow state or manages the application state according to the packet that was captured
|
||||
* @return True if capture started successfully, false if (relevant log error is printed in any case):
|
||||
* - Capture is already running
|
||||
* - Device is not opened
|
||||
* - Capture thread could not be created
|
||||
*/
|
||||
virtual bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie);
|
||||
|
||||
/**
|
||||
* Start capturing packets on this network interface (device) with periodic stats collection. Each time a packet is captured the onPacketArrives
|
||||
* callback is called. In addition, each intervalInSecondsToUpdateStats seconds stats are collected from the device and the onStatsUpdate
|
||||
* callback is called. Both the capture and periodic stats collection are done on new threads created by this method, each on a different thread,
|
||||
* meaning all callback calls are done in threads other than the caller thread. Capture process and stats collection will stop and threads will be
|
||||
* terminated when calling stopCapture(). This method must be called after the device is opened (i.e the open() method was called), otherwise an
|
||||
* error will be returned.
|
||||
* @param[in] onPacketArrives A callback that is called each time a packet is captured
|
||||
* @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to the onPacketArrives callback
|
||||
* each time it is called. This cookie is very useful for transferring objects that give context to the capture callback, for example:
|
||||
* objects that counts packets, manages flow state or manages the application state according to the packet that was captured
|
||||
* @param[in] intervalInSecondsToUpdateStats The interval in seconds to activate periodic stats collection
|
||||
* @param[in] onStatsUpdate A callback that will be called each time intervalInSecondsToUpdateStats expires and stats are collected. This
|
||||
* callback will contain the collected stats
|
||||
* @param[in] onStatsUpdateUserCookie A pointer to a user provided object. This object will be transferred to the onStatsUpdate callback
|
||||
* each time it is called
|
||||
* @return True if capture started successfully, false if (relevant log error is printed in any case):
|
||||
* - Capture is already running
|
||||
* - Device is not opened
|
||||
* - Capture thread could not be created
|
||||
* - Stats collection thread could not be created
|
||||
*/
|
||||
virtual bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie);
|
||||
|
||||
/**
|
||||
* Start capturing packets on this network interface (device) with periodic stats collection only. This means that packets arriving to the
|
||||
* network interface aren't delivered to the user but only counted. Each intervalInSecondsToUpdateStats seconds stats are collected from the
|
||||
* device and the onStatsUpdate callback is called with the updated counters. The periodic stats collection is done on a new thread created
|
||||
* by this method, meaning all callback calls are done in threads other than the caller thread. Stats collection will stop and threads will
|
||||
* be terminated when calling stopCapture(). This method must be called after the device is opened (i.e the open() method was called),
|
||||
* otherwise an error will be returned.
|
||||
* @param[in] intervalInSecondsToUpdateStats The interval in seconds to activate periodic stats collection
|
||||
* @param[in] onStatsUpdate A callback that will be called each time intervalInSecondsToUpdateStats expires and stats are collected. This
|
||||
* callback will contain the collected stats
|
||||
* @param[in] onStatsUpdateUserCookie A pointer to a user provided object. This object will be transferred to the onStatsUpdate callback
|
||||
* each time it is called
|
||||
* @return True if capture started successfully, false if (relevant log error is printed in any case):
|
||||
* - Capture is already running
|
||||
* - Device is not opened
|
||||
* - Stats collection thread could not be created
|
||||
*/
|
||||
virtual bool startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie);
|
||||
|
||||
/**
|
||||
* Start capturing packets on this network interface (device). All captured packets are added to capturedPacketsVector, so at the end of
|
||||
* the capture (when calling stopCapture()) this vector contains pointers to all captured packets in the form of RawPacket. The capture
|
||||
* is done on a new thread created by this method, meaning capturedPacketsVector is updated from another thread other than the caller
|
||||
* thread (so user should avoid changing or iterating this vector while capture is on). Capture process will stop and this capture thread
|
||||
* will be terminated when calling stopCapture(). This method must be called after the device is opened (i.e the open() method was called),
|
||||
* otherwise an error will be returned.
|
||||
* @param[in] capturedPacketsVector A reference to a RawPacketVector, meaning a vector of pointer to RawPacket objects
|
||||
* @return True if capture started successfully, false if (relevant log error is printed in any case):
|
||||
* - Capture is already running
|
||||
* - Device is not opened
|
||||
* - Capture thread could not be created
|
||||
*/
|
||||
virtual bool startCapture(RawPacketVector& capturedPacketsVector);
|
||||
|
||||
/**
|
||||
* Start capturing packets on this network interface (device) in blocking mode, meaning this method blocks and won't return until
|
||||
* the user frees the blocking (via onPacketArrives callback) or until a user defined timeout expires.
|
||||
* Whenever a packets is captured the onPacketArrives callback is called and lets the user handle the packet. In each callback call
|
||||
* the user should return true if he wants to release the block or false if it wants it to keep blocking. Regardless of this callback
|
||||
* a timeout is defined when start capturing. When this timeout expires the method will return.<BR>
|
||||
* Please notice that stopCapture() isn't needed here because when the method returns (after timeout or per user decision) capturing
|
||||
* on the device is stopped
|
||||
* @param[in] onPacketArrives A callback given by the user for handling incoming packets. After handling each packet the user needs to
|
||||
* return a boolean value. True value indicates stop capturing and stop blocking and false value indicates continue capturing and blocking
|
||||
* @param[in] userCookie A pointer to a user provided object. This object will be transferred to the onPacketArrives callback
|
||||
* each time it is called. This cookie is very useful for transferring objects that give context to the capture callback, for example:
|
||||
* objects that counts packets, manages flow state or manages the application state according to the packet that was captured
|
||||
* @param[in] timeout A timeout in seconds for the blocking to stop even if the user didn't return "true" in the onPacketArrives callback
|
||||
* If this timeout is set to 0 or less the timeout will be ignored, meaning the method will keep blocking until the user frees it via
|
||||
* the onPacketArrives callback
|
||||
* @return -1 if timeout expired, 1 if blocking was stopped via onPacketArrives callback or 0 if an error occurred (such as device
|
||||
* not open etc.). When returning 0 an appropriate error message is printed to log
|
||||
*/
|
||||
virtual int startCaptureBlockingMode(OnPacketArrivesStopBlocking onPacketArrives, void* userCookie, int timeout);
|
||||
|
||||
/**
|
||||
* Stop a currently running packet capture. This method terminates gracefully both packet capture thread and periodic stats collection
|
||||
* thread (both if exist)
|
||||
*/
|
||||
void stopCapture();
|
||||
|
||||
/**
|
||||
* Check if a capture thread is running
|
||||
* @return True if a capture thread is currently running
|
||||
*/
|
||||
bool captureActive();
|
||||
|
||||
/**
|
||||
* Checks whether the packetPayloadLength is larger than the device MTU. Logs an error if check fails
|
||||
* @param[in] packetPayloadLength The length of the IP layer of the packet
|
||||
* @return True if the packetPayloadLength is less than or equal to the device MTU
|
||||
*/
|
||||
bool doMtuCheck(int packetPayloadLength);
|
||||
|
||||
/**
|
||||
* Send a RawPacket to the network
|
||||
* @param[in] rawPacket A reference to the raw packet to send. This method treats the raw packet as read-only, it doesn't change anything
|
||||
* in it
|
||||
* @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. If enabled this comes with a small performance penalty.
|
||||
* Default value is false to avoid performance overhead. Set to true if you don't know whether packets fit the live device's MTU and you can afford the overhead.
|
||||
* @return True if packet was sent successfully. False will be returned in the following cases (relevant log error is printed in any case):
|
||||
* - Device is not opened
|
||||
* - Packet length is 0
|
||||
* - Packet length is larger than device MTU
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
bool sendPacket(RawPacket const& rawPacket, bool checkMtu = false);
|
||||
|
||||
/**
|
||||
* Send a buffer containing packet raw data (including all layers) to the network.
|
||||
* This particular version of the sendPacket method should only be used if you already have access to the size of the network layer of the packet,
|
||||
* since it allows you to check the payload size (see packetPayloadLength parameter) MTU of the live device without incurring a parsing overhead.
|
||||
* If the packetPayloadLength is unknown, please use a different implementation of the sendPacket method.
|
||||
* @param[in] packetData The buffer containing the packet raw data
|
||||
* @param[in] packetDataLength The length of the buffer (this is the entire packet, including link layer)
|
||||
* @param[in] packetPayloadLength The length of the payload for the data link layer. This includes all data apart from the header for the
|
||||
* data link layer.
|
||||
* @return True if the packet was sent successfully. False will be returned in the following cases (relevant log error is printed in any case):
|
||||
* - Device is not opened
|
||||
* - Packet data length is 0
|
||||
* - Packet payload length is larger than device MTU
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
bool sendPacket(const uint8_t* packetData, int packetDataLength, int packetPayloadLength);
|
||||
|
||||
/**
|
||||
* Send a buffer containing packet raw data (including all layers) to the network
|
||||
* @param[in] packetData The buffer containing the packet raw data
|
||||
* @param[in] packetDataLength The length of the buffer
|
||||
* @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. If enabled this comes with a small performance penalty.
|
||||
* Default value is false to avoid performance overhead. Set to true if you don't know whether packets fit the live device's MTU and you can afford the overhead.
|
||||
* @param[in] linkType Only used if checkMtu is true. Defines the layer type for parsing the first layer of the packet. Used for parsing the packet to
|
||||
* perform the MTU check. Default value is pcpp::LINKTYPE_ETHERNET. Ensure this parameter matches the linktype of the packet if checkMtu is true.
|
||||
* @return True if packet was sent successfully. False will be returned in the following cases (relevant log error is printed in any case):
|
||||
* - Device is not opened
|
||||
* - Packet length is 0
|
||||
* - Packet length is larger than device MTU and checkMtu is true
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
bool sendPacket(const uint8_t* packetData, int packetDataLength, bool checkMtu = false, pcpp::LinkLayerType linkType = pcpp::LINKTYPE_ETHERNET);
|
||||
|
||||
/**
|
||||
* Send a parsed Packet to the network
|
||||
* @param[in] packet A pointer to the packet to send. This method treats the packet as read-only, it doesn't change anything in it
|
||||
* @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. Default value is true, since the packet
|
||||
* being passed in has already been parsed, so checking the MTU does not incur significant processing overhead.
|
||||
* @return True if packet was sent successfully. False will be returned in the following cases (relevant log error is printed in any case):
|
||||
* - Device is not opened
|
||||
* - Packet length is 0
|
||||
* - Packet length is larger than device MTU and checkMtu is true
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
bool sendPacket(Packet* packet, bool checkMtu = true);
|
||||
|
||||
/**
|
||||
* Send an array of RawPacket objects to the network
|
||||
* @param[in] rawPacketsArr The array of RawPacket objects to send. This method treats all packets as read-only, it doesn't change anything
|
||||
* in them
|
||||
* @param[in] arrLength The length of the array
|
||||
* @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Incurs a parsing overhead.
|
||||
* Default value is false to avoid performance overhead. Set to true if you don't know whether packets fit the live device's MTU and you can afford the overhead.
|
||||
* @return The number of packets sent successfully. Sending a packet can fail if:
|
||||
* - Device is not opened. In this case no packets will be sent, return value will be 0
|
||||
* - Packet length is 0
|
||||
* - Packet length is larger than device MTU and checkMtu is true
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
virtual int sendPackets(RawPacket* rawPacketsArr, int arrLength, bool checkMtu = false);
|
||||
|
||||
/**
|
||||
* Send an array of pointers to Packet objects to the network
|
||||
* @param[in] packetsArr The array of pointers to Packet objects to send. This method treats all packets as read-only, it doesn't change
|
||||
* anything in them
|
||||
* @param[in] arrLength The length of the array
|
||||
* @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Default value is true, since the packets
|
||||
* being passed in has already been parsed, so checking the MTU does not incur significant processing overhead.
|
||||
* @return The number of packets sent successfully. Sending a packet can fail if:
|
||||
* - Device is not opened. In this case no packets will be sent, return value will be 0
|
||||
* - Packet length is 0
|
||||
* - Packet length is larger than device MTU and checkMtu is true
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
virtual int sendPackets(Packet** packetsArr, int arrLength, bool checkMtu = true);
|
||||
|
||||
/**
|
||||
* Send a vector of pointers to RawPacket objects to the network
|
||||
* @param[in] rawPackets The array of pointers to RawPacket objects to send. This method treats all packets as read-only, it doesn't change
|
||||
* anything in them
|
||||
* @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Incurs a parsing overhead.
|
||||
* Default value is false to avoid performance overhead. Set to true if you don't know whether packets fit the live device's MTU and you can afford the overhead.
|
||||
* @return The number of packets sent successfully. Sending a packet can fail if:
|
||||
* - Device is not opened. In this case no packets will be sent, return value will be 0
|
||||
* - Packet length is 0
|
||||
* - Packet length is larger than device MTU and checkMtu is true
|
||||
* - Packet could not be sent due to some error in libpcap/WinPcap/Npcap
|
||||
*/
|
||||
virtual int sendPackets(const RawPacketVector& rawPackets, bool checkMtu = false);
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Open the device using libpcap pcap_open_live. Opening the device only makes the device ready for use, it doesn't start packet capturing.
|
||||
* For packet capturing the user should call startCapture(). This implies that calling this method is a must before calling startCapture()
|
||||
* (otherwise startCapture() will fail with a "device not open" error). The device is opened in promiscuous mode
|
||||
* @return True if the device was opened successfully, false otherwise. When opening the device fails an error will be printed to log
|
||||
* as well
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Enables to open a device in a non-default configuration. Configuration has parameters like packet buffer timeout & size, open in
|
||||
* promiscuous/non-promiscuous mode, etc. Please check DeviceConfiguration for more details
|
||||
* @param[in] config The requested configuration
|
||||
* @return Same as open()
|
||||
*/
|
||||
bool open(const DeviceConfiguration& config);
|
||||
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Clones the current device class
|
||||
* @return Pointer to the copied class
|
||||
*/
|
||||
PcapLiveDevice* clone();
|
||||
|
||||
virtual void getStatistics(IPcapDevice::PcapStats& stats) const;
|
||||
|
||||
protected:
|
||||
pcap_t* doOpen(const DeviceConfiguration& config);
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif
|
||||
121
pcappp/include/pcapplusplus/PcapLiveDeviceList.h
Normal file
121
pcappp/include/pcapplusplus/PcapLiveDeviceList.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifndef PCAPPP_LIVE_DEVICE_LIST
|
||||
#define PCAPPP_LIVE_DEVICE_LIST
|
||||
|
||||
#include "IpAddress.h"
|
||||
#include "PcapLiveDevice.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class PcapLiveDeviceList
|
||||
* A singleton class that creates, stores and provides access to all PcapLiveDevice (on Linux) or WinPcapLiveDevice (on Windows) instances. All live
|
||||
* devices are initialized on startup and wrap the network interfaces installed on the machine. This class enables access to them through
|
||||
* their IP addresses or get a vector of all of them so the user can search them in some other way
|
||||
*/
|
||||
class PcapLiveDeviceList
|
||||
{
|
||||
private:
|
||||
std::vector<PcapLiveDevice*> m_LiveDeviceList;
|
||||
|
||||
std::vector<IPv4Address> m_DnsServers;
|
||||
|
||||
// private c'tor
|
||||
PcapLiveDeviceList();
|
||||
// private copy c'tor
|
||||
PcapLiveDeviceList( const PcapLiveDeviceList& other );
|
||||
PcapLiveDeviceList& operator=(const PcapLiveDeviceList& other);
|
||||
|
||||
void init();
|
||||
|
||||
void setDnsServers();
|
||||
public:
|
||||
/**
|
||||
* The access method to the singleton
|
||||
* @return The singleton instance of this class
|
||||
*/
|
||||
static PcapLiveDeviceList& getInstance()
|
||||
{
|
||||
static PcapLiveDeviceList instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to all live devices currently installed on the machine
|
||||
*/
|
||||
const std::vector<PcapLiveDevice*>& getPcapLiveDevicesList() const { return m_LiveDeviceList; }
|
||||
|
||||
/**
|
||||
* Get a pointer to the live device by its IP address. IP address can be both IPv4 or IPv6
|
||||
* @param[in] ipAddr The IP address defined for the device
|
||||
* @return A pointer to the live device if this IP address exists. NULL otherwise
|
||||
*/
|
||||
PcapLiveDevice* getPcapLiveDeviceByIp(const IPAddress& ipAddr) const;
|
||||
|
||||
/**
|
||||
* Get a pointer to the live device by its IPv4 address
|
||||
* @param[in] ipAddr The IPv4 address defined for the device
|
||||
* @return A pointer to the live device if this IPv4 address exists. NULL otherwise
|
||||
*/
|
||||
PcapLiveDevice* getPcapLiveDeviceByIp(const IPv4Address& ipAddr) const;
|
||||
|
||||
/**
|
||||
* Get a pointer to the live device by its IPv6 address
|
||||
* @param[in] ip6Addr The IPv6 address defined for the device
|
||||
* @return A pointer to the live device if this IPv6 address exists. NULL otherwise
|
||||
*/
|
||||
PcapLiveDevice* getPcapLiveDeviceByIp(const IPv6Address& ip6Addr) const;
|
||||
|
||||
/**
|
||||
* Get a pointer to the live device by its IP address represented as string. IP address can be both IPv4 or IPv6
|
||||
* @param[in] ipAddrAsString The IP address defined for the device as string
|
||||
* @return A pointer to the live device if this IP address is valid and exists. NULL otherwise
|
||||
*/
|
||||
PcapLiveDevice* getPcapLiveDeviceByIp(const std::string& ipAddrAsString) const;
|
||||
|
||||
/**
|
||||
* Get a pointer to the live device by its name
|
||||
* @param[in] name The name of the interface (e.g eth0)
|
||||
* @return A pointer to the live device if this name exists. NULL otherwise
|
||||
*/
|
||||
PcapLiveDevice* getPcapLiveDeviceByName(const std::string& name) const;
|
||||
|
||||
/**
|
||||
* Get a pointer to the live device by its IP address or name
|
||||
* @param[in] ipOrName An IP address or name of the interface
|
||||
* @return A pointer to the live device if exists, NULL otherwise
|
||||
*/
|
||||
PcapLiveDevice* getPcapLiveDeviceByIpOrName(const std::string& ipOrName) const;
|
||||
|
||||
/**
|
||||
* @return A list of all DNS servers defined for this machine. If this list is empty it means no DNS servers were defined or they
|
||||
* couldn't be extracted from some reason
|
||||
*/
|
||||
const std::vector<IPv4Address>& getDnsServers() const { return m_DnsServers; }
|
||||
|
||||
/**
|
||||
* Copies the current live device list
|
||||
* @return A pointer to the cloned device list
|
||||
*/
|
||||
PcapLiveDeviceList* clone();
|
||||
|
||||
/**
|
||||
* Reset the live device list and DNS server list, meaning clear and refetch them
|
||||
*/
|
||||
void reset();
|
||||
|
||||
// d'tor
|
||||
~PcapLiveDeviceList();
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif
|
||||
54
pcappp/include/pcapplusplus/PcapPlusPlusVersion.h
Normal file
54
pcappp/include/pcapplusplus/PcapPlusPlusVersion.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef PCAPPP_VERSION_H
|
||||
#define PCAPPP_VERSION_H
|
||||
|
||||
#include <string>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
#define PCAPPLUSPLUS_VERSION "22.05"
|
||||
#define PCAPPLUSPLUS_VERSION_OFFICIAL "official release"
|
||||
|
||||
#define PCAPPLUSPLUS_VERSION_FULL "v" PCAPPLUSPLUS_VERSION " (" PCAPPLUSPLUS_VERSION_OFFICIAL ")"
|
||||
|
||||
/**
|
||||
* @return PcapPlusPlus current version, e.g: 22.05. Notice that for non-official releases (which were pulled from GitHub) the version will end with a '+'.
|
||||
* For example: '22.05+' means non-official release but '22.05' means official release
|
||||
*/
|
||||
inline std::string getPcapPlusPlusVersion() { return PCAPPLUSPLUS_VERSION; }
|
||||
|
||||
/**
|
||||
* @return PcapPlusPlus long version string which includes the version and info whether it's an official or non-official release. For example: "v22.05+ (non-official release)"
|
||||
* or "v22.05 (official release)"
|
||||
*/
|
||||
inline std::string getPcapPlusPlusVersionFull() { return PCAPPLUSPLUS_VERSION_FULL; }
|
||||
|
||||
/**
|
||||
* @return The build date and time in a format of "Mmm dd yyyy hh:mm:ss"
|
||||
*/
|
||||
inline std::string getBuildDateTime() { return std::string(__DATE__) + " " + std::string(__TIME__); }
|
||||
|
||||
/**
|
||||
* @return The Git commit (revision) the binaries are built from
|
||||
*/
|
||||
std::string getGitCommit();
|
||||
|
||||
/**
|
||||
* @return The Git branch the binaries are built from
|
||||
*/
|
||||
std::string getGitBranch();
|
||||
|
||||
/**
|
||||
* @return Git branch and commit the binaries are built from.
|
||||
* Aggregates data from getGitCommit() and getGitBranch()
|
||||
*/
|
||||
std::string getGitInfo();
|
||||
|
||||
}
|
||||
|
||||
#endif /* PCAPPP_VERSION_H */
|
||||
147
pcappp/include/pcapplusplus/PcapRemoteDevice.h
Normal file
147
pcappp/include/pcapplusplus/PcapRemoteDevice.h
Normal file
@@ -0,0 +1,147 @@
|
||||
#ifndef PCAPPP_PCAP_REMOTE_DEVICE
|
||||
#define PCAPPP_PCAP_REMOTE_DEVICE
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <vector>
|
||||
#include "PcapLiveDevice.h"
|
||||
|
||||
|
||||
/// @file
|
||||
|
||||
struct pcap_rmtauth;
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct PcapRemoteAuthentication
|
||||
* The remote daemon (rpcapd) can be configured to require authentication before allowing a client to connect. This is done for
|
||||
* security reasons of course. This struct wraps the WinPcap/Npcap authentication object (pcap_rmtauth) and can (but not must) be given to
|
||||
* PcapRemoteDeviceList when initiating a connection to the remote daemon
|
||||
*/
|
||||
struct PcapRemoteAuthentication
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A constructor that sets username and password
|
||||
* @param[in] username The username for authentication with the remote daemon
|
||||
* @param[in] password The password for authentication with the remote daemon
|
||||
*/
|
||||
PcapRemoteAuthentication(const std::string username, const std::string password) { userName = username; this->password = password; }
|
||||
|
||||
/**
|
||||
* A copy c'tor for this object
|
||||
* @param[in] other The object to copy from
|
||||
*/
|
||||
PcapRemoteAuthentication(const PcapRemoteAuthentication& other) { userName = other.userName; password = other.password; }
|
||||
|
||||
/**
|
||||
* The username for authentication
|
||||
*/
|
||||
std::string userName;
|
||||
|
||||
/**
|
||||
* The password for authentication
|
||||
*/
|
||||
std::string password;
|
||||
|
||||
/**
|
||||
* A conversion method from PcapRemoteAuthentication to pcap_rmtauth. Note: the char* pointers of the returned pcap_rmtauth points
|
||||
* to the same places in memory as PcapRemoteAuthentication::userName and PcapRemoteAuthentication::password so the user should avoid
|
||||
* freeing this memory
|
||||
* @return A pcap_rmtauth that is converted from this class
|
||||
*/
|
||||
pcap_rmtauth getPcapRmAuth() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PcapRemoteDevice
|
||||
* A class that provides a C++ wrapper for WinPcap/Npcap Remote Capture feature. This feature allows to interact to a remote machine and capture
|
||||
* packets that are being transmitted on the remote network interfaces. This requires a remote daemon (called rpcapd) which performs the
|
||||
* capture and sends data back and the local client (represented by PcapRemoteDevice) that sends the appropriate commands and receives the
|
||||
* captured data. You can read more about this feature in WinPcap Remote Capture manual: https://www.winpcap.org/docs/docs_412/html/group__remote.html<BR>
|
||||
* Since this feature is supported in WinPcap and Npcap only and not in libpcap, PcapRemoteDevice can only be used in Windows only.<BR>
|
||||
* This class provides a wrapper for the local client, meaning it assumes the daemon (rpcapd) is already running on the remote machine and it
|
||||
* tries to connect to it and start receiving/sending packets from/to it. This class assumes rpcapd is in passive mode, meaning
|
||||
* PcapRemoteDevice connects to the remote daemon, sends the appropriate commands to it, and starts capturing packets, rather than letting the
|
||||
* daemon connect to the client by itself. Using PcapRemoteDevice is very similar to using the other live devices (PcapLiveDevice or
|
||||
* WinPcapLiveDevice), meaning the API's are the same and the same logic is used (for example: capturing is done on a different thread,
|
||||
* sending packets are done on the same thread, etc.). For the full API and explanations, please refer to PcapLiveDevice. The reason for the
|
||||
* similar API is that WinPcap/Npcap's API is very similar between Remote Capture and local network interface capture. The things that are different
|
||||
* are some are some implementation details, mainly in making the connection to the remote daemon, and the way the user can get the instance
|
||||
* of PcapRemoteDevice. For more details on that please refer to PcapRemoteDeviceList
|
||||
*/
|
||||
class PcapRemoteDevice : public PcapLiveDevice
|
||||
{
|
||||
friend class PcapRemoteDeviceList;
|
||||
private:
|
||||
IPAddress m_RemoteMachineIpAddress;
|
||||
uint16_t m_RemoteMachinePort;
|
||||
PcapRemoteAuthentication* m_RemoteAuthentication;
|
||||
|
||||
// c'tor is private, as only PcapRemoteDeviceList should create instances of it, and it'll create only one for every remote interface
|
||||
PcapRemoteDevice(pcap_if_t* iface, PcapRemoteAuthentication* remoteAuthentication, const IPAddress& remoteMachineIP, uint16_t remoteMachinePort);
|
||||
|
||||
// private copy c'tor
|
||||
PcapRemoteDevice( const PcapRemoteDevice& other );
|
||||
// private assignment operator
|
||||
PcapRemoteDevice& operator=(const PcapRemoteDevice& other);
|
||||
|
||||
static void* remoteDeviceCaptureThreadMain(void *ptr);
|
||||
|
||||
//overridden methods
|
||||
ThreadStart getCaptureThreadStart();
|
||||
|
||||
public:
|
||||
virtual ~PcapRemoteDevice() {}
|
||||
|
||||
/**
|
||||
* @return The IP address of the remote machine where packets are transmitted from the remote machine to the client machine
|
||||
*/
|
||||
IPAddress getRemoteMachineIpAddress() const { return m_RemoteMachineIpAddress; }
|
||||
|
||||
/**
|
||||
* @return The port of the remote machine where packets are transmitted from the remote machine to the client machine
|
||||
*/
|
||||
uint16_t getRemoteMachinePort() const { return m_RemoteMachinePort; }
|
||||
|
||||
//overridden methods
|
||||
|
||||
virtual LiveDeviceType getDeviceType() const { return RemoteDevice; }
|
||||
|
||||
/**
|
||||
* MTU isn't supported for remote devices
|
||||
* @return 0
|
||||
*/
|
||||
virtual uint32_t getMtu() const;
|
||||
|
||||
/**
|
||||
* MAC address isn't supported for remote devices
|
||||
* @return MacAddress#Zero
|
||||
*/
|
||||
virtual MacAddress getMacAddress() const;
|
||||
|
||||
/**
|
||||
* Open the device using pcap_open. Opening the device makes the connection to the remote daemon (including authentication if needed
|
||||
* and provided). If this methods succeeds it means the connection to the remote daemon succeeded and the device is ready for use.
|
||||
* As in PcapLiveDevice, packet capturing won't start yet. For packet capturing the user should call startCapture(). This implies
|
||||
* that calling this method is a must before calling startCapture() (otherwise startCapture() will fail with a "device not open" error).
|
||||
* The remote daemon is asked to capture packets in promiscuous mode
|
||||
* @return True if the device was opened successfully, false otherwise. When opening the device fails an error will be printed to log
|
||||
* as well, including the WinPcap/Npcap error if exists
|
||||
*/
|
||||
virtual bool open();
|
||||
|
||||
virtual void getStatistics(IPcapDevice::PcapStats& stats) const;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif /* PCAPPP_PCAP_REMOTE_DEVICE */
|
||||
152
pcappp/include/pcapplusplus/PcapRemoteDeviceList.h
Normal file
152
pcappp/include/pcapplusplus/PcapRemoteDeviceList.h
Normal file
@@ -0,0 +1,152 @@
|
||||
#ifndef PCAPP_PCAP_REMOTE_DEVICE_LIST
|
||||
#define PCAPP_PCAP_REMOTE_DEVICE_LIST
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "IpAddress.h"
|
||||
#include "PcapRemoteDevice.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class PcapRemoteDeviceList
|
||||
* A class that creates, stores and provides access to all instances of PcapRemoteDevice for a certain remote machine. To get an instance
|
||||
* of this class use one of the static methods of getRemoteDeviceList(). These methods creates a PcapRemoteDeviceList instance for the
|
||||
* certain remote machine which holds a list of PcapRemoteDevice instances, one for each remote network interface. Note there is
|
||||
* not a public constructor for this class, so the only way to get an instance of it is through getRemoteDeviceList(). After getting
|
||||
* this object, this class provides ways to access the PcapRemoteDevice instances: either through IP address of the remote network interface or
|
||||
* by iterating the PcapRemoteDevice instances (through the PcapRemoteDeviceList#RemoteDeviceListIterator iterator)<BR>
|
||||
* Since Remote Capture is supported in WinPcap and Npcap only, this class is available in Windows only
|
||||
*/
|
||||
class PcapRemoteDeviceList
|
||||
{
|
||||
private:
|
||||
std::vector<PcapRemoteDevice*> m_RemoteDeviceList;
|
||||
IPAddress m_RemoteMachineIpAddress;
|
||||
uint16_t m_RemoteMachinePort;
|
||||
PcapRemoteAuthentication* m_RemoteAuthentication;
|
||||
|
||||
// private c'tor. User should create the list via static methods PcapRemoteDeviceList::getRemoteDeviceList()
|
||||
PcapRemoteDeviceList() : m_RemoteMachinePort(0), m_RemoteAuthentication(NULL) {}
|
||||
// private copy c'tor
|
||||
PcapRemoteDeviceList(const PcapRemoteDeviceList& other);
|
||||
PcapRemoteDeviceList& operator=(const PcapRemoteDeviceList& other);
|
||||
|
||||
void setRemoteMachineIpAddress(const IPAddress& ipAddress);
|
||||
void setRemoteMachinePort(uint16_t port);
|
||||
void setRemoteAuthentication(const PcapRemoteAuthentication* remoteAuth);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Iterator object that can be used for iterating all PcapRemoteDevice in list
|
||||
*/
|
||||
typedef typename std::vector<PcapRemoteDevice*>::iterator RemoteDeviceListIterator;
|
||||
|
||||
/**
|
||||
* Const iterator object that can be used for iterating all PcapRemoteDevice in a constant list
|
||||
*/
|
||||
typedef typename std::vector<PcapRemoteDevice*>::const_iterator ConstRemoteDeviceListIterator;
|
||||
|
||||
~PcapRemoteDeviceList();
|
||||
|
||||
/**
|
||||
* A static method for creating a PcapRemoteDeviceList instance for a certain remote machine. This methods creates the instance, and also
|
||||
* creates a list of PcapRemoteDevice instances stored in it, one for each remote network interface. Notice this method allocates
|
||||
* the PcapRemoteDeviceList instance and returns a pointer to it. It's the user responsibility to free it when done using it<BR>
|
||||
* This method overload is for remote daemons which don't require authentication for accessing them. For daemons which do require authentication
|
||||
* use the other method overload
|
||||
* @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd daemon
|
||||
* @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon
|
||||
* @return A pointer to the newly created PcapRemoteDeviceList, or NULL if (an appropriate error will be printed to log in each case):
|
||||
* - IP address provided is NULL or not valid
|
||||
* - WinPcap/Npcap encountered an error in creating the remote connection string
|
||||
* - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving devices on the remote machine
|
||||
*/
|
||||
static PcapRemoteDeviceList* getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port);
|
||||
|
||||
/**
|
||||
* An overload of the previous getRemoteDeviceList() method but with authentication support. This method is suitable for connecting to
|
||||
* remote daemons which require authentication for accessing them
|
||||
* @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd daemon
|
||||
* @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon
|
||||
* @param[in] remoteAuth A pointer to the authentication object which contains the username and password for connecting to the remote
|
||||
* daemon
|
||||
* @return A pointer to the newly created PcapRemoteDeviceList, or NULL if (an appropriate error will be printed to log in each case):
|
||||
* - IP address provided is NULL or not valid
|
||||
* - WinPcap/Npcap encountered an error in creating the remote connection string
|
||||
* - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving devices on the remote machine
|
||||
*/
|
||||
static PcapRemoteDeviceList* getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication* remoteAuth);
|
||||
|
||||
/**
|
||||
* @return The IP address of the remote machine
|
||||
*/
|
||||
IPAddress getRemoteMachineIpAddress() const { return m_RemoteMachineIpAddress; }
|
||||
|
||||
/**
|
||||
* @return The port of the remote machine where packets are transmitted from the remote machine to the client machine
|
||||
*/
|
||||
uint16_t getRemoteMachinePort() const { return m_RemoteMachinePort; }
|
||||
|
||||
/**
|
||||
* Search a PcapRemoteDevice in the list by its IPv4 address
|
||||
* @param[in] ip4Addr The IPv4 address
|
||||
* @return The PcapRemoteDevice if found, NULL otherwise
|
||||
*/
|
||||
PcapRemoteDevice* getRemoteDeviceByIP(const IPv4Address& ip4Addr) const;
|
||||
|
||||
/**
|
||||
* Search a PcapRemoteDevice in the list by its IPv6 address
|
||||
* @param[in] ip6Addr The IPv6 address
|
||||
* @return The PcapRemoteDevice if found, NULL otherwise
|
||||
*/
|
||||
PcapRemoteDevice* getRemoteDeviceByIP(const IPv6Address& ip6Addr) const;
|
||||
|
||||
/**
|
||||
* Search a PcapRemoteDevice in the list by its IP address (IPv4 or IPv6)
|
||||
* @param[in] ipAddr The IP address
|
||||
* @return The PcapRemoteDevice if found, NULL otherwise
|
||||
*/
|
||||
PcapRemoteDevice* getRemoteDeviceByIP(const IPAddress& ipAddr) const;
|
||||
|
||||
/**
|
||||
* Search a PcapRemoteDevice in the list by its IP address
|
||||
* @param[in] ipAddrAsString The IP address in string format
|
||||
* @return The PcapRemoteDevice if found, NULL otherwise
|
||||
*/
|
||||
PcapRemoteDevice* getRemoteDeviceByIP(const std::string& ipAddrAsString) const;
|
||||
|
||||
/**
|
||||
* @return An iterator object pointing to the first PcapRemoteDevice in list
|
||||
*/
|
||||
RemoteDeviceListIterator begin() { return m_RemoteDeviceList.begin(); }
|
||||
|
||||
/**
|
||||
* @return A const iterator object pointing to the first PcapRemoteDevice in list
|
||||
*/
|
||||
ConstRemoteDeviceListIterator begin() const { return m_RemoteDeviceList.begin(); }
|
||||
|
||||
/**
|
||||
* @return An iterator object pointing to the last PcapRemoteDevice in list
|
||||
*/
|
||||
RemoteDeviceListIterator end() { return m_RemoteDeviceList.end(); }
|
||||
|
||||
/**
|
||||
* @return A const iterator object pointing to the last PcapRemoteDevice in list
|
||||
*/
|
||||
ConstRemoteDeviceListIterator end() const { return m_RemoteDeviceList.end(); }
|
||||
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif /* PCAPP_PCAP_REMOTE_DEVICE_LIST */
|
||||
348
pcappp/include/pcapplusplus/PfRingDevice.h
Normal file
348
pcappp/include/pcapplusplus/PfRingDevice.h
Normal file
@@ -0,0 +1,348 @@
|
||||
#ifndef PCAPPP_PF_RING_DEVICE
|
||||
#define PCAPPP_PF_RING_DEVICE
|
||||
|
||||
#include "Device.h"
|
||||
#include "MacAddress.h"
|
||||
#include "SystemUtils.h"
|
||||
#include "Packet.h"
|
||||
#include <pthread.h>
|
||||
|
||||
/// @file
|
||||
|
||||
// forward declaration of PF_RING structs
|
||||
struct __pfring;
|
||||
typedef struct __pfring pfring;
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
class PfRingDevice;
|
||||
|
||||
typedef void (*OnPfRingPacketsArriveCallback)(RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, PfRingDevice* device, void* userCookie);
|
||||
|
||||
|
||||
/**
|
||||
* @class PfRingDevice
|
||||
* A class representing a PF_RING port
|
||||
*/
|
||||
class PfRingDevice : public IDevice, public IFilterableDevice
|
||||
{
|
||||
friend class PfRingDeviceList;
|
||||
private:
|
||||
|
||||
struct CoreConfiguration
|
||||
{
|
||||
pthread_t RxThread;
|
||||
pfring* Channel;
|
||||
bool IsInUse;
|
||||
bool IsAffinitySet;
|
||||
|
||||
CoreConfiguration();
|
||||
void clear();
|
||||
};
|
||||
|
||||
pfring** m_PfRingDescriptors;
|
||||
uint8_t m_NumOfOpenedRxChannels;
|
||||
std::string m_DeviceName;
|
||||
int m_InterfaceIndex;
|
||||
MacAddress m_MacAddress;
|
||||
int m_DeviceMTU;
|
||||
CoreConfiguration m_CoreConfiguration[MAX_NUM_OF_CORES];
|
||||
bool m_StopThread;
|
||||
OnPfRingPacketsArriveCallback m_OnPacketsArriveCallback;
|
||||
void* m_OnPacketsArriveUserCookie;
|
||||
bool m_ReentrantMode;
|
||||
bool m_HwClockEnabled;
|
||||
bool m_IsFilterCurrentlySet;
|
||||
|
||||
PfRingDevice(const char* deviceName);
|
||||
|
||||
bool initCoreConfigurationByCoreMask(CoreMask coreMask);
|
||||
static void* captureThreadMain(void *ptr);
|
||||
|
||||
int openSingleRxChannel(const char* deviceName, pfring** ring);
|
||||
|
||||
bool getIsHwClockEnable() { setPfRingDeviceAttributes(); return m_HwClockEnabled; }
|
||||
bool setPfRingDeviceClock(pfring* ring);
|
||||
|
||||
void clearCoreConfiguration();
|
||||
int getCoresInUseCount() const;
|
||||
|
||||
void setPfRingDeviceAttributes();
|
||||
|
||||
bool sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues);
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum representing the type of packet distribution between different RX channels
|
||||
*/
|
||||
enum ChannelDistribution
|
||||
{
|
||||
/**
|
||||
* Packets are distributed between channels in a round-robin manner
|
||||
*/
|
||||
RoundRobin,
|
||||
/**
|
||||
* Packets are distributed between channels per flow (each flow goes for different channel)
|
||||
*/
|
||||
PerFlow
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct PfRingStats
|
||||
* A container for PfRingDevice statistics
|
||||
*/
|
||||
struct PfRingStats
|
||||
{
|
||||
/** Number of packets received */
|
||||
uint64_t recv;
|
||||
/** Number of packets dropped */
|
||||
uint64_t drop;
|
||||
};
|
||||
|
||||
/**
|
||||
* A destructor for PfRingDevice class
|
||||
*/
|
||||
~PfRingDevice();
|
||||
|
||||
/**
|
||||
* Get the MAC address of the current device
|
||||
* @return The MAC address of the current device
|
||||
*/
|
||||
MacAddress getMacAddress() { setPfRingDeviceAttributes(); return m_MacAddress; }
|
||||
|
||||
/**
|
||||
* Get PF_RING interface index of the current device
|
||||
* @return PF_RING interface index of the current device
|
||||
*/
|
||||
int getInterfaceIndex() { setPfRingDeviceAttributes(); return m_InterfaceIndex; }
|
||||
|
||||
/**
|
||||
* Get MTU of the current device
|
||||
* @return Upon success return the device MTU, 0 otherwise
|
||||
*/
|
||||
int getMtu() { setPfRingDeviceAttributes(); return m_DeviceMTU; }
|
||||
|
||||
/**
|
||||
* Return true if device supports hardware timestamping. If it does, this feature will be automatically set
|
||||
* for this device. You can read more about this in PF_RING documentation
|
||||
* @return True if device supports hardware timestamping, false otherwise
|
||||
*/
|
||||
bool isHwClockEnabledForDevice() { setPfRingDeviceAttributes(); return m_HwClockEnabled; }
|
||||
|
||||
/**
|
||||
* Gets the interface name (e.g eth0, eth1, etc.)
|
||||
* @return The interface name
|
||||
*/
|
||||
std::string getDeviceName() const { return m_DeviceName; }
|
||||
|
||||
|
||||
/**
|
||||
* Start single-threaded capturing with callback. Works with open() or openSingleRxChannel().
|
||||
* @param[in] onPacketsArrive A callback to call whenever a packet arrives
|
||||
* @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every packet
|
||||
* @return True if this action succeeds, false otherwise
|
||||
*/
|
||||
bool startCaptureSingleThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie);
|
||||
|
||||
/**
|
||||
* Start multi-threaded (multi-core) capturing with callback. Works with openMultiRxChannels().
|
||||
* This method will return an error if the number of opened channels is different than the number of threads/cores
|
||||
* requested
|
||||
* @param[in] onPacketsArrive A callback to call whenever a packet arrives
|
||||
* @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every packet
|
||||
* @param[in] coreMask The cores to be used as mask. For example:
|
||||
* @return True if this action succeeds, false otherwise
|
||||
*/
|
||||
bool startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask);
|
||||
|
||||
/**
|
||||
* Stops capturing packets (works will all type of startCapture*)
|
||||
*/
|
||||
void stopCapture();
|
||||
|
||||
|
||||
/**
|
||||
* Opens a single RX channel (=RX queue) on this interface. All packets will be received on a single thread
|
||||
* without core affinity. If the channel ID requested doesn't exist on this interface, the method will fail
|
||||
* (return false)
|
||||
* @param[in] channelId The requested channel ID
|
||||
* @return True if this action succeeds, false otherwise
|
||||
*/
|
||||
bool openSingleRxChannel(uint8_t channelId);
|
||||
|
||||
/**
|
||||
* Opens a set of RX channels (=RX queues) on this interface, identified by their IDs. All packets will be received on a single thread
|
||||
* without core affinity. If one of the channel IDs requested doesn't exist on this interface, the method will fail
|
||||
* (return false)
|
||||
* @param[in] channelIds An array of channel IDs
|
||||
* @param[in] numOfChannelIds The channel ID array size
|
||||
* @return True if this action succeeds, false otherwise
|
||||
*/
|
||||
bool openMultiRxChannels(const uint8_t* channelIds, int numOfChannelIds);
|
||||
|
||||
/**
|
||||
* Opens numOfRxChannelsToOpen RX channels. If numOfRxChannelsToOpen is larger than available RX queues for this
|
||||
* interface than a number of RX channels will be opened on each RX queue. For example: if the user asks for 10
|
||||
* RX channels but the interface has only 4 RX queues, then 3 RX channels will be opened for RX-queue0 and RX-queue2,
|
||||
* and 2 RX channels will be opened for RX-queue2 and RX-queue3.
|
||||
* Packets will be distributed between different RX queues on per-flow manner, but within multiple RX channels in
|
||||
* the same RX queue packet will be distributed according to distribution requested by "dist"
|
||||
* @param[in] numOfRxChannelsToOpen Number of RX channels to open
|
||||
* @param[in] dist Distribution method
|
||||
* @return True if this action succeeds, false otherwise
|
||||
*/
|
||||
bool openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist);
|
||||
|
||||
/**
|
||||
* Gets the number of RX channels currently open. RX channels aren't necessary interface's RX queues
|
||||
* because in some cases the user asks to open several channels on the same queue. For example: if the user uses
|
||||
* openMultiRxChannels() and asks to open 8 channels but interface has only 4 RX queues, 2 channels will be
|
||||
* opened for each RX queue
|
||||
* @return Number of opened RX channels
|
||||
*/
|
||||
uint8_t getNumOfOpenedRxChannels() const { return m_NumOfOpenedRxChannels; }
|
||||
|
||||
/**
|
||||
* Gets the total number of RX channels (RX queues) this interface has
|
||||
* @return The number of RX channels (queues) for this interface
|
||||
*/
|
||||
uint8_t getTotalNumOfRxChannels() const;
|
||||
|
||||
/**
|
||||
* Gets the core used in the current thread context
|
||||
* @return The system core used in the current thread context
|
||||
*/
|
||||
SystemCore getCurrentCoreId() const;
|
||||
|
||||
/**
|
||||
* Get the statistics of a specific thread/core (=RX channel)
|
||||
* @param[in] core The requested core
|
||||
* @param[out] stats A reference for the stats object where the stats are written. Current values will be overridden
|
||||
*/
|
||||
void getThreadStatistics(SystemCore core, PfRingStats& stats) const;
|
||||
|
||||
/**
|
||||
* Get the statistics of the current thread/core (=RX channel)
|
||||
* @param[out] stats A reference for the stats object where the stats are written. Current values will be overridden
|
||||
*/
|
||||
void getCurrentThreadStatistics(PfRingStats& stats) const;
|
||||
|
||||
/**
|
||||
* Get the statistics for the entire device. If more than 1 RX channel is opened, this method aggregates the stats
|
||||
* of all channels
|
||||
* @param[out] stats A reference for the stats object where the stats are written. Current values will be overridden
|
||||
*/
|
||||
void getStatistics(PfRingStats& stats) const;
|
||||
|
||||
/**
|
||||
* Return true if filter is currently set
|
||||
* @return True if filter is currently set, false otherwise
|
||||
*/
|
||||
bool isFilterCurrentlySet() const;
|
||||
|
||||
/**
|
||||
* Send a raw packet. This packet must be fully specified (the MAC address up)
|
||||
* and it will be transmitted as-is without any further manipulation.
|
||||
* This method doesn't change or manipulate the data in any way (hence the "const" declaration).
|
||||
* Note this method flushes the TX queues after the data is sent. So if you want to send several packets
|
||||
* In the burst please use sendPackets()
|
||||
* @param[in] rawPacket The raw packet to send
|
||||
* @return True if raw packet was sent completely, false otherwise
|
||||
*/
|
||||
bool sendPacket(const RawPacket& rawPacket);
|
||||
|
||||
/**
|
||||
* Send raw data. This data must be a valid and fully specified packet (the MAC address up);
|
||||
* it will be transmitted as-is without any further manipulation.
|
||||
* This method doesn't change or manipulate the data in any way (hence the "const" declaration).
|
||||
* Note this method flushes the TX queues after the data is sent. So if you want to send several packets
|
||||
* in the burst please use sendPackets()
|
||||
* @param[in] packetData The raw data to send
|
||||
* @param[in] packetDataLength the length of packetData
|
||||
* @return True if raw packet was sent completely, false otherwise
|
||||
*
|
||||
*/
|
||||
bool sendPacket(const uint8_t* packetData, int packetDataLength);
|
||||
|
||||
/**
|
||||
* Send a packet. This packet must be fully specified (the MAC address up)
|
||||
* and it will be transmitted as-is without any further manipulation.
|
||||
* This method doesn't change or manipulate the data in any way (hence the "const" declaration).
|
||||
* Note this method flushes the TX queues after the data is sent. So if you want to send several packets
|
||||
* In the burst please use sendPackets()
|
||||
* @param[in] packet The packet to send
|
||||
* @return True if raw packet was sent completely, false otherwise
|
||||
*/
|
||||
bool sendPacket(const Packet& packet);
|
||||
|
||||
/**
|
||||
* Send raw packets. All raw packets must be fully specified (the MAC address up)
|
||||
* and it will be transmitted as-is without any further manipulation.
|
||||
* This method doesn't change or manipulate the raw packets data in any way (hence the "const" declaration).
|
||||
* This method flushes the TX queues only when the last packet is sent
|
||||
* @param[in] rawPacketsArr The RawPacket array
|
||||
* @param[in] arrLength RawPacket array length
|
||||
* @return Number of packets that were sent completely
|
||||
*/
|
||||
int sendPackets(const RawPacket* rawPacketsArr, int arrLength);
|
||||
|
||||
/**
|
||||
* Send packets. All packets must be fully specified (the MAC address up)
|
||||
* and it will be transmitted as-is without any further manipulation.
|
||||
* This method doesn't change or manipulate the packets data in any way (hence the "const" declaration).
|
||||
* This method flushes the TX queues only when the last packet is sent
|
||||
* @param[in] packetsArr An array of pointers to Packet objects
|
||||
* @param[in] arrLength Packet pointers array length
|
||||
* @return Number of packets that were sent completely
|
||||
*/
|
||||
int sendPackets(const Packet** packetsArr, int arrLength);
|
||||
|
||||
/**
|
||||
* Send all raw packets pointed by the RawPacketVector. All packets must be fully specified (the MAC address up)
|
||||
* and it will be transmitted as-is without any further manipulation.
|
||||
* This method doesn't change or manipulate the packets data in any way (hence the "const" declaration).
|
||||
* This method flushes the TX queues only when the last packet is sent
|
||||
* @param[in] rawPackets The raw packet vector
|
||||
* @return Number of raw packets that were sent completely
|
||||
*/
|
||||
int sendPackets(const RawPacketVector& rawPackets);
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
|
||||
/**
|
||||
* Opens the entire device (including all RX channels/queues on this interface). All packets will be received
|
||||
* on a single thread without core affinity
|
||||
* @return True if this action succeeds, false otherwise
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Closes all RX channels currently opened in device
|
||||
*/
|
||||
void close();
|
||||
|
||||
using IFilterableDevice::setFilter;
|
||||
|
||||
/**
|
||||
* Sets a BPF filter to the device
|
||||
* @param[in] filterAsString The BPF filter in string format
|
||||
*/
|
||||
bool setFilter(std::string filterAsString);
|
||||
|
||||
/**
|
||||
* Remove a filter if currently set
|
||||
* @return True if filter was removed successfully or if no filter was set, false otherwise
|
||||
*/
|
||||
bool clearFilter();
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_PF_RING_DEVICE */
|
||||
67
pcappp/include/pcapplusplus/PfRingDeviceList.h
Normal file
67
pcappp/include/pcapplusplus/PfRingDeviceList.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef PCAPPP_PF_RING_DEVICE_LIST
|
||||
#define PCAPPP_PF_RING_DEVICE_LIST
|
||||
|
||||
#include "PfRingDevice.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class PfRingDeviceList
|
||||
* A singleton class that holds all available PF_RING devices. Through this class the user can iterate all PF_RING devices or find a specific
|
||||
* device by name
|
||||
*/
|
||||
class PfRingDeviceList
|
||||
{
|
||||
private:
|
||||
std::vector<PfRingDevice*> m_PfRingDeviceList;
|
||||
std::string m_PfRingVersion;
|
||||
|
||||
PfRingDeviceList();
|
||||
// private copy c'tor
|
||||
PfRingDeviceList(const PfRingDeviceList& other);
|
||||
PfRingDeviceList& operator=(const PfRingDeviceList& other);
|
||||
// private d'tor
|
||||
~PfRingDeviceList();
|
||||
|
||||
void calcPfRingVersion(void* ring);
|
||||
public:
|
||||
/**
|
||||
* A static method that returns the singleton object for PfRingDeviceList
|
||||
* @return PfRingDeviceList singleton
|
||||
*/
|
||||
static PfRingDeviceList& getInstance()
|
||||
{
|
||||
static PfRingDeviceList instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all available PF_RING devices
|
||||
* @return a list of all available PF_RING devices
|
||||
*/
|
||||
const std::vector<PfRingDevice*>& getPfRingDevicesList() const { return m_PfRingDeviceList; }
|
||||
|
||||
/**
|
||||
* Get a PF_RING device by name. The name is the Linux interface name which appears in ifconfig
|
||||
* (e.g eth0, eth1, etc.)
|
||||
* @return A pointer to the PF_RING device
|
||||
*/
|
||||
PfRingDevice* getPfRingDeviceByName(const std::string devName) const;
|
||||
|
||||
/**
|
||||
* Get installed PF_RING version
|
||||
* @return A string representing PF_RING version
|
||||
*/
|
||||
std::string getPfRingVersion() const { return m_PfRingVersion; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_PF_RING_DEVICE_LIST */
|
||||
174
pcappp/include/pcapplusplus/PointerVector.h
Normal file
174
pcappp/include/pcapplusplus/PointerVector.h
Normal file
@@ -0,0 +1,174 @@
|
||||
#ifndef PCAPPP_POINTER_VECTOR
|
||||
#define PCAPPP_POINTER_VECTOR
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class PointerVector
|
||||
* A template class for representing a std::vector of pointers. Once (a pointer to) an element is added to this vector,
|
||||
* the element responsibility moves to the vector, meaning the PointerVector will free the object once it's removed from the vector
|
||||
* This class wraps std::vector and adds the capability of freeing objects once they're removed from it
|
||||
*/
|
||||
template<typename T>
|
||||
class PointerVector
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Iterator object that is used for iterating all elements in the vector
|
||||
*/
|
||||
typedef typename std::vector<T*>::iterator VectorIterator;
|
||||
|
||||
/**
|
||||
* Const iterator object that is used for iterating all elements in a constant vector
|
||||
*/
|
||||
typedef typename std::vector<T*>::const_iterator ConstVectorIterator;
|
||||
|
||||
/**
|
||||
* A constructor that create an empty instance of this object
|
||||
*/
|
||||
PointerVector() { }
|
||||
|
||||
/**
|
||||
* A destructor for this class. The destructor frees all elements that are binded to the vector
|
||||
*/
|
||||
~PointerVector()
|
||||
{
|
||||
for (VectorIterator iter = m_Vector.begin(); iter != m_Vector.end(); iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor. Once a vector is copied from another vector, all elements inside it are copied,
|
||||
* meaning the new vector will contain pointers to copied elements, not pointers to the elements of the original vector
|
||||
*/
|
||||
PointerVector(const PointerVector& other)
|
||||
{
|
||||
for (ConstVectorIterator iter = other.begin(); iter != other.end(); iter++)
|
||||
{
|
||||
T* objCopy = new T(**iter);
|
||||
m_Vector.push_back(objCopy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all elements of the vector while freeing them
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
for (VectorIterator iter = m_Vector.begin(); iter != m_Vector.end(); iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
|
||||
m_Vector.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new (pointer to an) element to the vector
|
||||
*/
|
||||
void pushBack(T* element) { m_Vector.push_back(element); }
|
||||
|
||||
/**
|
||||
* Get the first element of the vector
|
||||
* @return An iterator object pointing to the first element of the vector
|
||||
*/
|
||||
VectorIterator begin() { return m_Vector.begin(); }
|
||||
|
||||
/**
|
||||
* Get the first element of a constant vector
|
||||
* @return A const iterator object pointing to the first element of the vector
|
||||
*/
|
||||
ConstVectorIterator begin() const { return m_Vector.begin(); }
|
||||
|
||||
/**
|
||||
* Get the last element of the vector
|
||||
* @return An iterator object pointing to the last element of the vector
|
||||
*/
|
||||
VectorIterator end() { return m_Vector.end(); }
|
||||
|
||||
/**
|
||||
* Get the last element of a constant vector
|
||||
* @return A const iterator object pointing to the last element of the vector
|
||||
*/
|
||||
ConstVectorIterator end() const { return m_Vector.end(); }
|
||||
|
||||
|
||||
//inline size_t size() { return m_Vector.size(); }
|
||||
|
||||
/**
|
||||
* Get number of elements in the vector
|
||||
* @return The number of elements in the vector
|
||||
*/
|
||||
size_t size() const { return m_Vector.size(); }
|
||||
|
||||
/**
|
||||
* Returns a pointer of the first element in the vector
|
||||
* @return A pointer of the first element in the vector
|
||||
*/
|
||||
T* front() { return m_Vector.front(); }
|
||||
|
||||
/**
|
||||
* Removes from the vector a single element (position). Once the element is erased, it's also freed
|
||||
* @param[in] position The position of the element to erase
|
||||
* @return An iterator pointing to the new location of the element that followed the last element erased by the function call
|
||||
*/
|
||||
VectorIterator erase(VectorIterator position)
|
||||
{
|
||||
delete (*position);
|
||||
return m_Vector.erase(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from the vector without freeing it
|
||||
* param[in] position The position of the element to remove from the vector
|
||||
* @return A pointer to the element which is no longer managed by the vector. It's user responsibility to free it
|
||||
*/
|
||||
T* getAndRemoveFromVector(VectorIterator& position)
|
||||
{
|
||||
T* result = (*position);
|
||||
VectorIterator tempPos = position;
|
||||
tempPos = m_Vector.erase(tempPos);
|
||||
position = tempPos;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the element in a certain index
|
||||
* @param[in] index The index to retrieve the element from
|
||||
* @return The element at the specified position in the vector
|
||||
*/
|
||||
T* at(int index)
|
||||
{
|
||||
return m_Vector.at(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a const pointer to the element in a certain index
|
||||
* @param[in] index The index to retrieve the element from
|
||||
* @return The element at the specified position in the vector
|
||||
*/
|
||||
const T* at(int index) const
|
||||
{
|
||||
return m_Vector.at(index);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T*> m_Vector;
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_POINTER_VECTOR */
|
||||
285
pcappp/include/pcapplusplus/ProtocolType.h
Normal file
285
pcappp/include/pcapplusplus/ProtocolType.h
Normal file
@@ -0,0 +1,285 @@
|
||||
#ifndef PCAPPP_PROTOCOL_TYPES
|
||||
#define PCAPPP_PROTOCOL_TYPES
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @typedef ProtocolType
|
||||
* Representing all protocols supported by PcapPlusPlus
|
||||
*/
|
||||
typedef uint64_t ProtocolType;
|
||||
|
||||
/**
|
||||
* Unknown protocol (or unsupported by PcapPlusPlus)
|
||||
*/
|
||||
const ProtocolType UnknownProtocol = 0x00;
|
||||
|
||||
/**
|
||||
* Ethernet protocol
|
||||
*/
|
||||
const ProtocolType Ethernet = 0x01;
|
||||
|
||||
/**
|
||||
* IPv4 protocol
|
||||
*/
|
||||
const ProtocolType IPv4 = 0x02;
|
||||
|
||||
/**
|
||||
* IPv6 protocol
|
||||
*/
|
||||
const ProtocolType IPv6 = 0x04;
|
||||
|
||||
/**
|
||||
* IP protocol (aggregation bitmask of IPv4 and IPv6 protocols)
|
||||
*/
|
||||
const ProtocolType IP = 0x06;
|
||||
|
||||
/**
|
||||
* TCP protocol
|
||||
*/
|
||||
const ProtocolType TCP = 0x08;
|
||||
|
||||
/**
|
||||
* UDP protocol
|
||||
*/
|
||||
const ProtocolType UDP = 0x10;
|
||||
|
||||
/**
|
||||
* HTTP request protocol
|
||||
*/
|
||||
const ProtocolType HTTPRequest = 0x20;
|
||||
|
||||
/**
|
||||
* HTTP response protocol
|
||||
*/
|
||||
const ProtocolType HTTPResponse = 0x40;
|
||||
|
||||
/**
|
||||
* HTTP protocol (aggregation bitmask of HTTP request and HTTP response protocols)
|
||||
*/
|
||||
const ProtocolType HTTP = 0x60;
|
||||
|
||||
/**
|
||||
* ARP protocol
|
||||
*/
|
||||
const ProtocolType ARP = 0x80;
|
||||
|
||||
/**
|
||||
* VLAN protocol
|
||||
*/
|
||||
const ProtocolType VLAN = 0x100;
|
||||
|
||||
/**
|
||||
* ICMP protocol
|
||||
*/
|
||||
const ProtocolType ICMP = 0x200;
|
||||
|
||||
/**
|
||||
* PPPoE session protocol
|
||||
*/
|
||||
const ProtocolType PPPoESession = 0x400;
|
||||
|
||||
/**
|
||||
* PPPoE discovery protocol
|
||||
*/
|
||||
const ProtocolType PPPoEDiscovery = 0x800;
|
||||
|
||||
/**
|
||||
* PPPoE protocol (aggregation bitmask of PPPoESession and PPPoEDiscovery protocols)
|
||||
*/
|
||||
const ProtocolType PPPoE = 0xc00;
|
||||
|
||||
/**
|
||||
* DNS protocol
|
||||
*/
|
||||
const ProtocolType DNS = 0x1000;
|
||||
|
||||
/**
|
||||
* MPLS protocol
|
||||
*/
|
||||
const ProtocolType MPLS = 0x2000;
|
||||
|
||||
/**
|
||||
* GRE version 0 protocol
|
||||
*/
|
||||
const ProtocolType GREv0 = 0x4000;
|
||||
|
||||
/**
|
||||
* GRE version 1 protocol
|
||||
*/
|
||||
const ProtocolType GREv1 = 0x8000;
|
||||
|
||||
/**
|
||||
* GRE protocol (aggregation bitmask of GREv0 and GREv1 protocols)
|
||||
*/
|
||||
const ProtocolType GRE = 0xc000;
|
||||
|
||||
/**
|
||||
* PPP for PPTP protocol
|
||||
*/
|
||||
const ProtocolType PPP_PPTP = 0x10000;
|
||||
|
||||
/**
|
||||
* SSL/TLS protocol
|
||||
*/
|
||||
const ProtocolType SSL = 0x20000;
|
||||
|
||||
/**
|
||||
* SLL (Linux cooked capture) protocol
|
||||
*/
|
||||
const ProtocolType SLL = 0x40000;
|
||||
|
||||
/**
|
||||
* DHCP/BOOTP protocol
|
||||
*/
|
||||
const ProtocolType DHCP = 0x80000;
|
||||
|
||||
/**
|
||||
* Null/Loopback protocol
|
||||
*/
|
||||
const ProtocolType NULL_LOOPBACK = 0x100000;
|
||||
|
||||
/**
|
||||
* IGMP protocol
|
||||
*/
|
||||
const ProtocolType IGMP = 0xE00000;
|
||||
|
||||
/**
|
||||
* IGMPv1 protocol
|
||||
*/
|
||||
const ProtocolType IGMPv1 = 0x200000;
|
||||
|
||||
/**
|
||||
* IGMPv2 protocol
|
||||
*/
|
||||
const ProtocolType IGMPv2 = 0x400000;
|
||||
|
||||
/**
|
||||
* IGMPv3 protocol
|
||||
*/
|
||||
const ProtocolType IGMPv3 = 0x800000;
|
||||
|
||||
/**
|
||||
* Generic payload (no specific protocol)
|
||||
*/
|
||||
const ProtocolType GenericPayload = 0x1000000;
|
||||
|
||||
/**
|
||||
* VXLAN protocol
|
||||
*/
|
||||
const ProtocolType VXLAN = 0x2000000;
|
||||
|
||||
/**
|
||||
* SIP request protocol
|
||||
*/
|
||||
const ProtocolType SIPRequest = 0x4000000;
|
||||
|
||||
/**
|
||||
* SIP response protocol
|
||||
*/
|
||||
const ProtocolType SIPResponse = 0x8000000;
|
||||
|
||||
/**
|
||||
* SIP protocol (aggregation bitmask of SIPRequest and SIPResponse protocols)
|
||||
*/
|
||||
const ProtocolType SIP = 0xc000000;
|
||||
|
||||
/**
|
||||
* SDP protocol
|
||||
*/
|
||||
const ProtocolType SDP = 0x10000000;
|
||||
|
||||
/**
|
||||
* Packet trailer
|
||||
*/
|
||||
const ProtocolType PacketTrailer = 0x20000000;
|
||||
|
||||
/**
|
||||
* RADIUS protocol
|
||||
*/
|
||||
const ProtocolType Radius = 0x40000000;
|
||||
|
||||
/**
|
||||
* GTPv1 protocol
|
||||
*/
|
||||
const ProtocolType GTPv1 = 0x80000000;
|
||||
|
||||
/**
|
||||
* GTP protocol (currently the same as GTPv1)
|
||||
*/
|
||||
const ProtocolType GTP = 0x80000000;
|
||||
|
||||
/**
|
||||
* IEEE 802.3 Ethernet protocol
|
||||
*/
|
||||
const ProtocolType EthernetDot3 = 0x100000000;
|
||||
|
||||
/**
|
||||
* Border Gateway Protocol (BGP) version 4 protocol
|
||||
*/
|
||||
const ProtocolType BGP = 0x200000000;
|
||||
|
||||
/**
|
||||
* SSH version 2 protocol
|
||||
*/
|
||||
const ProtocolType SSH = 0x400000000;
|
||||
|
||||
/**
|
||||
* IPSec Authentication Header (AH) protocol
|
||||
*/
|
||||
const ProtocolType AuthenticationHeader = 0x800000000;
|
||||
|
||||
/**
|
||||
* IPSec Encapsulating Security Payload (ESP) protocol
|
||||
*/
|
||||
const ProtocolType ESP = 0x1000000000;
|
||||
|
||||
/**
|
||||
* IPSec protocol (aggregation bitmask of AH and ESP protocols)
|
||||
*/
|
||||
const ProtocolType IPSec = 0x1800000000;
|
||||
|
||||
/**
|
||||
* Dynamic Host Configuration Protocol version 6 (DHCPv6) protocol
|
||||
*/
|
||||
const ProtocolType DHCPv6 = 0x2000000000;
|
||||
|
||||
/**
|
||||
* Network Time (NTP) Protocol
|
||||
*/
|
||||
const ProtocolType NTP = 0x4000000000;
|
||||
|
||||
/**
|
||||
* An enum representing OSI model layers
|
||||
*/
|
||||
enum OsiModelLayer
|
||||
{
|
||||
/** Physical layer (layer 1) */
|
||||
OsiModelPhysicalLayer = 1,
|
||||
/** Data link layer (layer 2) */
|
||||
OsiModelDataLinkLayer = 2,
|
||||
/** Network layer (layer 3) */
|
||||
OsiModelNetworkLayer = 3,
|
||||
/** Transport layer (layer 4) */
|
||||
OsiModelTransportLayer = 4,
|
||||
/** Session layer (layer 5) */
|
||||
OsiModelSesionLayer = 5,
|
||||
/** Presentation layer (layer 6) */
|
||||
OsiModelPresentationLayer = 6,
|
||||
/** Application layer (layer 7) */
|
||||
OsiModelApplicationLayer = 7,
|
||||
/** Unknown / null layer */
|
||||
OsiModelLayerUnknown = 8
|
||||
};
|
||||
|
||||
} //namespace pcpp
|
||||
|
||||
#endif
|
||||
349
pcappp/include/pcapplusplus/RadiusLayer.h
Normal file
349
pcappp/include/pcapplusplus/RadiusLayer.h
Normal file
@@ -0,0 +1,349 @@
|
||||
#ifndef PACKETPP_RADIUS_LAYER
|
||||
#define PACKETPP_RADIUS_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct radius_header
|
||||
* Represents a RADIUS protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct radius_header
|
||||
{
|
||||
/** RADIUS message code */
|
||||
uint8_t code;
|
||||
/** RADIUS message ID */
|
||||
uint8_t id;
|
||||
/** RADIUS message length */
|
||||
uint16_t length;
|
||||
/** Used to authenticate the reply from the RADIUS server and to encrypt passwords */
|
||||
uint8_t authenticator[16];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @class RadiusAttribute
|
||||
* A wrapper class for RADIUS attributes. This class does not create or modify RADIUS attribute records, but rather
|
||||
* serves as a wrapper and provides useful methods for retrieving data from them
|
||||
*/
|
||||
class RadiusAttribute : public TLVRecord<uint8_t, uint8_t>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the attribute raw data (byte array)
|
||||
* @param[in] attrRawData A pointer to the attribute raw data
|
||||
*/
|
||||
RadiusAttribute(uint8_t* attrRawData) : TLVRecord(attrRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
virtual ~RadiusAttribute() { }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
return (size_t)m_Data->recordLen;
|
||||
}
|
||||
|
||||
size_t getDataSize() const
|
||||
{
|
||||
return (size_t)m_Data->recordLen - 2*sizeof(uint8_t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class RadiusAttributeBuilder
|
||||
* A class for building RADIUS attributes. This builder receives the attribute parameters in its c'tor,
|
||||
* builds the RADIUS attribute raw buffer and provides a build() method to get a RadiusAttribute object out of it
|
||||
*/
|
||||
class RadiusAttributeBuilder : public TLVRecordBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for building RADIUS attributes which their value is a byte array. The RadiusAttribute object can later
|
||||
* be retrieved by calling build()
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @param[in] attrValue A buffer containing the attribute value. This buffer is read-only and isn't modified in any way
|
||||
* @param[in] attrValueLen Attribute value length in bytes
|
||||
*/
|
||||
RadiusAttributeBuilder(uint8_t attrType, const uint8_t* attrValue, uint8_t attrValueLen) :
|
||||
TLVRecordBuilder(attrType, attrValue, attrValueLen) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building RADIUS attributes which have a 1-byte value. The RadiusAttribute object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @param[in] attrValue A 1-byte attribute value
|
||||
*/
|
||||
RadiusAttributeBuilder(uint8_t attrType, uint8_t attrValue) :
|
||||
TLVRecordBuilder(attrType, attrValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building RADIUS attributes which have a 2-byte value. The RadiusAttribute object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @param[in] attrValue A 2-byte attribute value
|
||||
*/
|
||||
RadiusAttributeBuilder(uint8_t attrType, uint16_t attrValue) :
|
||||
TLVRecordBuilder(attrType, attrValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building RADIUS attributes which have a 4-byte value. The RadiusAttribute object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @param[in] attrValue A 4-byte attribute value
|
||||
*/
|
||||
RadiusAttributeBuilder(uint8_t attrType, uint32_t attrValue) :
|
||||
TLVRecordBuilder(attrType, attrValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building RADIUS attributes which have an IPv4Address value. The RadiusAttribute object can later be
|
||||
* retrieved by calling build()
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @param[in] attrValue The IPv4 address attribute value
|
||||
*/
|
||||
RadiusAttributeBuilder(uint8_t attrType, const IPv4Address& attrValue) :
|
||||
TLVRecordBuilder(attrType, attrValue) { }
|
||||
|
||||
/**
|
||||
* A c'tor for building RADIUS attributes which have a string value. The RadiusAttribute object can later be retrieved
|
||||
* by calling build()
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @param[in] attrValue The string attribute value
|
||||
*/
|
||||
RadiusAttributeBuilder(uint8_t attrType, const std::string& attrValue) :
|
||||
TLVRecordBuilder(attrType, attrValue) { }
|
||||
|
||||
/**
|
||||
* A copy c'tor which copies all the data from another instance of RadiusAttributeBuilder
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
RadiusAttributeBuilder(const RadiusAttributeBuilder& other) :
|
||||
TLVRecordBuilder(other) { }
|
||||
|
||||
/**
|
||||
* Assignment operator that copies all data from another instance of RadiusAttributeBuilder
|
||||
* @param[in] other The instance to assign from
|
||||
*/
|
||||
RadiusAttributeBuilder& operator=(const RadiusAttributeBuilder& other)
|
||||
{
|
||||
TLVRecordBuilder::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the RadiusAttribute object out of the parameters defined in the c'tor
|
||||
* @return The RadiusAttribute object
|
||||
*/
|
||||
RadiusAttribute build() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class RadiusLayer
|
||||
* Represents a RADIUS (Remote Authentication Dial-In User Service) protocol layer
|
||||
*/
|
||||
class RadiusLayer : public Layer
|
||||
{
|
||||
private:
|
||||
|
||||
TLVRecordReader<RadiusAttribute> m_AttributeReader;
|
||||
|
||||
uint8_t* getAttributesBasePtr() const { return m_Data + sizeof(radius_header); }
|
||||
|
||||
RadiusAttribute addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
RadiusLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) :
|
||||
Layer(data, dataLen, prevLayer, packet)
|
||||
{ m_Protocol = Radius; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new layer from scratch
|
||||
* @param[in] code The RADIUS message code
|
||||
* @param[in] id The RADIUS message ID
|
||||
* @param[in] authenticator A pointer to a byte array containing the authenticator value
|
||||
* @param[in] authenticatorArrSize The authenticator byte array size. A valid size of the authenticator field is
|
||||
* 16 bytes. If the provided size is less than that then the byte array will be copied to the packet but the missing
|
||||
* bytes will stay zero. If the size is more than 16 bytes, only the first 16 bytes will be copied to the packet
|
||||
*/
|
||||
RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize);
|
||||
|
||||
/**
|
||||
* A constructor that creates a new layer from scratch
|
||||
* @param[in] code The RADIUS message code
|
||||
* @param[in] id The RADIUS message ID
|
||||
* @param[in] authenticator A hex string representing the authenticator value. A valid size of the authenticator
|
||||
* field is 16 bytes. If the hex string represents an array that is smaller than this then the missing bytes in the
|
||||
* packet's authenticator field will stay zero. If the hex string represents an array that is larger than 16 bytes,
|
||||
* only the first 16 bytes will be copied to the packet
|
||||
*/
|
||||
RadiusLayer(uint8_t code, uint8_t id, const std::string authenticator);
|
||||
|
||||
/**
|
||||
* A d'tor for this layer, currently does nothing
|
||||
*/
|
||||
~RadiusLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the RADIUS header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the radius_header object
|
||||
*/
|
||||
radius_header* getRadiusHeader() const { return (radius_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return A hex string representation of the radius_header#authenticator byte array value
|
||||
*/
|
||||
std::string getAuthenticatorValue() const;
|
||||
|
||||
/**
|
||||
* Setter for radius_header#authenticator
|
||||
* @param[in] authValue A hex string representing the requested authenticator value
|
||||
*/
|
||||
void setAuthenticatorValue(const std::string& authValue);
|
||||
|
||||
/**
|
||||
* A static method that returns the RADIUS message string for a give message code. For example: the string
|
||||
* "Access-Request" will be returned for code 1
|
||||
* @param[in] radiusMessageCode RADIUS message code
|
||||
* @return RADIUS message string
|
||||
*/
|
||||
static std::string getRadiusMessageString(uint8_t radiusMessageCode);
|
||||
|
||||
/**
|
||||
* @return The first RADIUS attribute in the packet. If there are no attributes the returned value will contain
|
||||
* a logical NULL (RadiusAttribute#isNull() == true)
|
||||
*/
|
||||
RadiusAttribute getFirstAttribute() const;
|
||||
|
||||
/**
|
||||
* Get the RADIUS attribute that comes after a given attribute. If the given attribute was the last one, the
|
||||
* returned value will contain a logical NULL (RadiusAttribute#isNull() == true)
|
||||
* @param[in] attr A given attribute
|
||||
* @return A RadiusAttribute object containing the attribute data that comes next, or logical NULL if the given
|
||||
* attribute: (1) was the last one; (2) contains a logical NULL or (3) doesn't belong to this packet
|
||||
*/
|
||||
RadiusAttribute getNextAttribute(RadiusAttribute& attr) const;
|
||||
|
||||
/**
|
||||
* Get a RADIUS attribute by attribute type
|
||||
* @param[in] attrType RADIUS attribute type
|
||||
* @return A RadiusAttribute object containing the first attribute data that matches this type, or logical NULL
|
||||
* (RadiusAttribute#isNull() == true) if no such attribute found
|
||||
*/
|
||||
RadiusAttribute getAttribute(uint8_t attrType) const;
|
||||
|
||||
/**
|
||||
* @return The number of RADIUS attributes in the packet
|
||||
*/
|
||||
size_t getAttributeCount() const;
|
||||
|
||||
/**
|
||||
* Add a new RADIUS attribute at the end of the layer
|
||||
* @param[in] attrBuilder A RadiusAttributeBuilder object that contains the requested attribute data to add
|
||||
* @return A RadiusAttribute object containing the newly added RADIUS attribute data or logical NULL
|
||||
* (RadiusAttribute#isNull() == true) if addition failed
|
||||
*/
|
||||
RadiusAttribute addAttribute(const RadiusAttributeBuilder& attrBuilder);
|
||||
|
||||
/**
|
||||
* Add a new RADIUS attribute after an existing one
|
||||
* @param[in] attrBuilder A RadiusAttributeBuilder object that contains the requested attribute data to add
|
||||
* @param[in] prevAttrType The RADIUS attribute which the newly added attribute will come after
|
||||
* @return A RadiusAttribute object containing the newly added RADIUS attribute data or logical NULL
|
||||
* (RadiusAttribute#isNull() == true) if addition failed
|
||||
*/
|
||||
RadiusAttribute addAttributeAfter(const RadiusAttributeBuilder& attrBuilder, uint8_t prevAttrType);
|
||||
|
||||
/**
|
||||
* Remove an existing RADIUS attribute from the layer
|
||||
* @param[in] attrType The RADIUS attribute type to remove
|
||||
* @return True if the RADIUS attribute was successfully removed or false if type wasn't found or if removal failed
|
||||
*/
|
||||
bool removeAttribute(uint8_t attrType);
|
||||
|
||||
/**
|
||||
* Remove all RADIUS attributes in this layer
|
||||
* @return True if all attributes were successfully removed or false if removal failed for some reason
|
||||
*/
|
||||
bool removeAllAttributes();
|
||||
|
||||
/**
|
||||
* The static method makes validation of UDP data
|
||||
* @param[in] udpData The pointer to the UDP payload data. It points to the first byte of RADIUS header.
|
||||
* @param[in] udpDataLen The payload data size
|
||||
* @return True if the data is valid and can represent the RADIUS packet
|
||||
*/
|
||||
static bool isDataValid(const uint8_t* udpData, size_t udpDataLen);
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as RADIUS
|
||||
* @param[in] port The port number to be checked
|
||||
*/
|
||||
static inline bool isRadiusPort(uint16_t port);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size written in radius_header#length
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
/**
|
||||
* Does nothing for this layer, RADIUS is always last
|
||||
*/
|
||||
void parseNextLayer() {}
|
||||
|
||||
/**
|
||||
* Calculate and store the value of radius_header#length according to the layer size
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; }
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool RadiusLayer::isRadiusPort(uint16_t port)
|
||||
{
|
||||
switch (port)
|
||||
{
|
||||
case 1812:
|
||||
case 1813:
|
||||
case 3799:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} // isRadiusPort
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // PACKETPP_RADIUS_LAYER
|
||||
455
pcappp/include/pcapplusplus/RawPacket.h
Normal file
455
pcappp/include/pcapplusplus/RawPacket.h
Normal file
@@ -0,0 +1,455 @@
|
||||
#ifndef PCAPPP_RAW_PACKET
|
||||
#define PCAPPP_RAW_PACKET
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <WinSock2.h>
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* An enum describing all known link layer type. Taken from: http://www.tcpdump.org/linktypes.html .
|
||||
*/
|
||||
enum LinkLayerType
|
||||
{
|
||||
/** BSD loopback encapsulation */
|
||||
LINKTYPE_NULL = 0,
|
||||
/** IEEE 802.3 Ethernet */
|
||||
LINKTYPE_ETHERNET = 1,
|
||||
/** AX.25 packet */
|
||||
LINKTYPE_AX25 = 3,
|
||||
/** IEEE 802.5 Token Ring */
|
||||
LINKTYPE_IEEE802_5 = 6,
|
||||
/** ARCNET Data Packets */
|
||||
LINKTYPE_ARCNET_BSD = 7,
|
||||
/** SLIP, encapsulated with a LINKTYPE_SLIP header */
|
||||
LINKTYPE_SLIP = 8,
|
||||
/** PPP, as per RFC 1661 and RFC 1662 */
|
||||
LINKTYPE_PPP = 9,
|
||||
/** FDDI, as specified by ANSI INCITS 239-1994 */
|
||||
LINKTYPE_FDDI = 10,
|
||||
/** Raw IP */
|
||||
LINKTYPE_DLT_RAW1 = 12,
|
||||
/** Raw IP (OpenBSD) */
|
||||
LINKTYPE_DLT_RAW2 = 14,
|
||||
/** PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547 */
|
||||
LINKTYPE_PPP_HDLC = 50,
|
||||
/** PPPoE */
|
||||
LINKTYPE_PPP_ETHER = 51,
|
||||
/** RFC 1483 LLC/SNAP-encapsulated ATM */
|
||||
LINKTYPE_ATM_RFC1483 = 100,
|
||||
/** Raw IP */
|
||||
LINKTYPE_RAW = 101,
|
||||
/** Cisco PPP with HDLC framing */
|
||||
LINKTYPE_C_HDLC = 104,
|
||||
/** IEEE 802.11 wireless LAN */
|
||||
LINKTYPE_IEEE802_11 = 105,
|
||||
/** Frame Relay */
|
||||
LINKTYPE_FRELAY = 107,
|
||||
/** OpenBSD loopback encapsulation */
|
||||
LINKTYPE_LOOP = 108,
|
||||
/** Linux "cooked" capture encapsulation */
|
||||
LINKTYPE_LINUX_SLL = 113,
|
||||
/** Apple LocalTalk */
|
||||
LINKTYPE_LTALK = 114,
|
||||
/** OpenBSD pflog */
|
||||
LINKTYPE_PFLOG = 117,
|
||||
/** Prism monitor mode information followed by an 802.11 header */
|
||||
LINKTYPE_IEEE802_11_PRISM = 119,
|
||||
/** RFC 2625 IP-over-Fibre Channel */
|
||||
LINKTYPE_IP_OVER_FC = 122,
|
||||
/** ATM traffic, encapsulated as per the scheme used by SunATM devices */
|
||||
LINKTYPE_SUNATM = 123,
|
||||
/** Radiotap link-layer information followed by an 802.11 header */
|
||||
LINKTYPE_IEEE802_11_RADIOTAP = 127,
|
||||
/** ARCNET Data Packets, as described by the ARCNET Trade Association standard ATA 878.1-1999 */
|
||||
LINKTYPE_ARCNET_LINUX = 129,
|
||||
/** Apple IP-over-IEEE 1394 cooked header */
|
||||
LINKTYPE_APPLE_IP_OVER_IEEE1394 = 138,
|
||||
/** Signaling System 7 Message Transfer Part Level 2 */
|
||||
LINKTYPE_MTP2_WITH_PHDR = 139,
|
||||
/** Signaling System 7 Message Transfer Part Level 2 */
|
||||
LINKTYPE_MTP2 = 140,
|
||||
/** Signaling System 7 Message Transfer Part Level 3 */
|
||||
LINKTYPE_MTP3 = 141,
|
||||
/** Signaling System 7 Signalling Connection Control Part */
|
||||
LINKTYPE_SCCP = 142,
|
||||
/** Signaling System 7 Signalling Connection Control Part */
|
||||
LINKTYPE_DOCSIS = 143,
|
||||
/** Linux-IrDA packets */
|
||||
LINKTYPE_LINUX_IRDA = 144,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER0 = 147,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER1 = 148,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER2 = 149,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER3 = 150,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER4 = 151,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER5 = 152,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER6 = 153,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER7 = 154,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER8 = 155,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER9 = 156,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER10 = 157,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER11 = 158,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER12 = 159,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER13 = 160,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER14 = 161,
|
||||
/** Reserved for private use */
|
||||
LINKTYPE_USER15 = 162,
|
||||
/** AVS monitor mode information followed by an 802.11 header */
|
||||
LINKTYPE_IEEE802_11_AVS = 163,
|
||||
/** BACnet MS/TP frames */
|
||||
LINKTYPE_BACNET_MS_TP = 165,
|
||||
/** PPP in HDLC-like encapsulation, like LINKTYPE_PPP_HDLC, but with the 0xff address byte replaced by a direction indication - 0x00 for incoming and 0x01 for outgoing */
|
||||
LINKTYPE_PPP_PPPD = 166,
|
||||
/** General Packet Radio Service Logical Link Control */
|
||||
LINKTYPE_GPRS_LLC = 169,
|
||||
/** Transparent-mapped generic framing procedure */
|
||||
LINKTYPE_GPF_T = 170,
|
||||
/** Frame-mapped generic framing procedure */
|
||||
LINKTYPE_GPF_F = 171,
|
||||
/** Link Access Procedures on the D Channel (LAPD) frames */
|
||||
LINKTYPE_LINUX_LAPD = 177,
|
||||
/** Bluetooth HCI UART transport layer */
|
||||
LINKTYPE_BLUETOOTH_HCI_H4 = 187,
|
||||
/** USB packets, beginning with a Linux USB header */
|
||||
LINKTYPE_USB_LINUX = 189,
|
||||
/** Per-Packet Information information */
|
||||
LINKTYPE_PPI = 192,
|
||||
/** IEEE 802.15.4 wireless Personal Area Network */
|
||||
LINKTYPE_IEEE802_15_4 = 195,
|
||||
/** Various link-layer types, with a pseudo-header, for SITA */
|
||||
LINKTYPE_SITA = 196,
|
||||
/** Various link-layer types, with a pseudo-header, for Endace DAG cards; encapsulates Endace ERF record */
|
||||
LINKTYPE_ERF = 197,
|
||||
/** Bluetooth HCI UART transport layer */
|
||||
LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR = 201,
|
||||
/** AX.25 packet, with a 1-byte KISS header containing a type indicator */
|
||||
LINKTYPE_AX25_KISS = 202,
|
||||
/** Link Access Procedures on the D Channel (LAPD) frames */
|
||||
LINKTYPE_LAPD = 203,
|
||||
/** PPP, as per RFC 1661 and RFC 1662, preceded with a one-byte pseudo-header with a zero value meaning "received by this host" and a non-zero value meaning "sent by this host" */
|
||||
LINKTYPE_PPP_WITH_DIR = 204,
|
||||
/** Cisco PPP with HDLC framing */
|
||||
LINKTYPE_C_HDLC_WITH_DIR = 205,
|
||||
/** Frame Relay */
|
||||
LINKTYPE_FRELAY_WITH_DIR = 206,
|
||||
/** IPMB over an I2C circuit */
|
||||
LINKTYPE_IPMB_LINUX = 209,
|
||||
/** IEEE 802.15.4 wireless Personal Area Network */
|
||||
LINKTYPE_IEEE802_15_4_NONASK_PHY = 215,
|
||||
/** USB packets, beginning with a Linux USB header */
|
||||
LINKTYPE_USB_LINUX_MMAPPED = 220,
|
||||
/** Fibre Channel FC-2 frames, beginning with a Frame_Header */
|
||||
LINKTYPE_FC_2 = 224,
|
||||
/** Fibre Channel FC-2 frames */
|
||||
LINKTYPE_FC_2_WITH_FRAME_DELIMS = 225,
|
||||
/** Solaris ipnet pseudo-header */
|
||||
LINKTYPE_IPNET = 226,
|
||||
/** CAN (Controller Area Network) frames, with a pseudo-header as supplied by Linux SocketCAN */
|
||||
LINKTYPE_CAN_SOCKETCAN = 227,
|
||||
/** Raw IPv4; the packet begins with an IPv4 header */
|
||||
LINKTYPE_IPV4 = 228,
|
||||
/** Raw IPv6; the packet begins with an IPv6 header */
|
||||
LINKTYPE_IPV6 = 229,
|
||||
/** IEEE 802.15.4 wireless Personal Area Network, without the FCS at the end of the frame */
|
||||
LINKTYPE_IEEE802_15_4_NOFCS = 230,
|
||||
/** Raw D-Bus messages, starting with the endianness flag, followed by the message type, etc., but without the authentication handshake before the message sequence */
|
||||
LINKTYPE_DBUS = 231,
|
||||
/** DVB-CI (DVB Common Interface for communication between a PC Card module and a DVB receiver), with the message format specified by the PCAP format for DVB-CI specification */
|
||||
LINKTYPE_DVB_CI = 235,
|
||||
/** Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but not the same as, 27.010) */
|
||||
LINKTYPE_MUX27010 = 236,
|
||||
/** D_PDUs as described by NATO standard STANAG 5066, starting with the synchronization sequence, and including both header and data CRCs */
|
||||
LINKTYPE_STANAG_5066_D_PDU = 237,
|
||||
/** Linux netlink NETLINK NFLOG socket log messages */
|
||||
LINKTYPE_NFLOG = 239,
|
||||
/** Pseudo-header for Hilscher Gesellschaft für Systemautomation mbH netANALYZER devices, followed by an Ethernet frame, beginning with the MAC header and ending with the FCS */
|
||||
LINKTYPE_NETANALYZER = 240,
|
||||
/** Pseudo-header for Hilscher Gesellschaft für Systemautomation mbH netANALYZER devices, followed by an Ethernet frame, beginning with the preamble, SFD, and MAC header, and ending with the FCS */
|
||||
LINKTYPE_NETANALYZER_TRANSPARENT = 241,
|
||||
/** IP-over-InfiniBand, as specified by RFC 4391 section 6 */
|
||||
LINKTYPE_IPOIB = 242,
|
||||
/** MPEG-2 Transport Stream transport packets, as specified by ISO 13818-1/ITU-T Recommendation H.222.0 */
|
||||
LINKTYPE_MPEG_2_TS = 243,
|
||||
/** Pseudo-header for ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as used by their ng40 protocol tester */
|
||||
LINKTYPE_NG40 = 244,
|
||||
/** Pseudo-header for NFC LLCP packet captures, followed by frame data for the LLCP Protocol as specified by NFCForum-TS-LLCP_1.1 */
|
||||
LINKTYPE_NFC_LLCP = 245,
|
||||
/** Raw InfiniBand frames, starting with the Local Routing Header */
|
||||
LINKTYPE_INFINIBAND = 247,
|
||||
/** SCTP packets, as defined by RFC 4960, with no lower-level protocols such as IPv4 or IPv6 */
|
||||
LINKTYPE_SCTP = 248,
|
||||
/** USB packets, beginning with a USBPcap header */
|
||||
LINKTYPE_USBPCAP = 249,
|
||||
/** Serial-line packet header for the Schweitzer Engineering Laboratories "RTAC" product */
|
||||
LINKTYPE_RTAC_SERIAL = 250,
|
||||
/** Bluetooth Low Energy air interface Link Layer packets */
|
||||
LINKTYPE_BLUETOOTH_LE_LL = 251,
|
||||
/** Linux Netlink capture encapsulation */
|
||||
LINKTYPE_NETLINK = 253,
|
||||
/** Bluetooth Linux Monitor encapsulation of traffic for the BlueZ stack */
|
||||
LINKTYPE_BLUETOOTH_LINUX_MONITOR = 254,
|
||||
/** Bluetooth Basic Rate and Enhanced Data Rate baseband packets */
|
||||
LINKTYPE_BLUETOOTH_BREDR_BB = 255,
|
||||
/** Bluetooth Low Energy link-layer packets */
|
||||
LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR = 256,
|
||||
/** PROFIBUS data link layer packets, as specified by IEC standard 61158-6-3 */
|
||||
LINKTYPE_PROFIBUS_DL = 257,
|
||||
/** Apple PKTAP capture encapsulation */
|
||||
LINKTYPE_PKTAP = 258,
|
||||
/** Ethernet-over-passive-optical-network packets */
|
||||
LINKTYPE_EPON = 259,
|
||||
/** IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format" in the PICMG HPM.2 specification */
|
||||
LINKTYPE_IPMI_HPM_2 = 260,
|
||||
/** Per Joshua Wright <jwright@hasborg.com>, formats for Z-Wave RF profiles R1 and R2 captures */
|
||||
LINKTYPE_ZWAVE_R1_R2 = 261,
|
||||
/** Per Joshua Wright <jwright@hasborg.com>, formats for Z-Wave RF profile R3 captures */
|
||||
LINKTYPE_ZWAVE_R3 = 262,
|
||||
/** Formats for WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol common packet structure captures */
|
||||
LINKTYPE_WATTSTOPPER_DLM = 263,
|
||||
/** Messages between ISO 14443 contactless smartcards (Proximity Integrated Circuit Card, PICC) and card readers (Proximity Coupling Device, PCD), with the message format specified by the PCAP format for ISO14443 specification */
|
||||
LINKTYPE_ISO_14443 = 264
|
||||
};
|
||||
|
||||
/**
|
||||
* Max packet size supported
|
||||
*/
|
||||
#define PCPP_MAX_PACKET_SIZE 65536
|
||||
|
||||
/**
|
||||
* @class RawPacket
|
||||
* This class holds the packet as raw (not parsed) data. The data is held as byte array. In addition to the data itself
|
||||
* every instance also holds a timestamp representing the time the packet was received by the NIC.
|
||||
* RawPacket instance isn't read only. The user can change the packet data, add or remove data, etc.
|
||||
*/
|
||||
class RawPacket
|
||||
{
|
||||
protected:
|
||||
uint8_t* m_RawData;
|
||||
int m_RawDataLen;
|
||||
int m_FrameLength;
|
||||
timespec m_TimeStamp;
|
||||
bool m_DeleteRawDataAtDestructor;
|
||||
bool m_RawPacketSet;
|
||||
LinkLayerType m_LinkLayerType;
|
||||
void init(bool deleteRawDataAtDestructor = true);
|
||||
void copyDataFrom(const RawPacket& other, bool allocateData = true);
|
||||
public:
|
||||
/**
|
||||
* A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually used when packet
|
||||
* is captured using a packet capturing engine (like libPcap. WinPcap, Npcap, PF_RING, etc.). The capturing engine allocates the raw data
|
||||
* memory and give the user a pointer to it + a timestamp it has arrived to the device
|
||||
* @param[in] pRawData A pointer to the raw data
|
||||
* @param[in] rawDataLen The raw data length in bytes
|
||||
* @param[in] timestamp The timestamp packet was received by the NIC (in usec precision)
|
||||
* @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance is freed or not. If set
|
||||
* to 'true' than pRawData will be freed when instanced is being freed
|
||||
* @param[in] layerType The link layer type of this raw packet. The default is Ethernet
|
||||
*/
|
||||
RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET);
|
||||
|
||||
/**
|
||||
* A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually used when packet
|
||||
* is captured using a packet capturing engine (like libPcap. WinPcap, Npcap, PF_RING, etc.). The capturing engine allocates the raw data
|
||||
* memory and give the user a pointer to it + a timestamp it has arrived to the device
|
||||
* @param[in] pRawData A pointer to the raw data
|
||||
* @param[in] rawDataLen The raw data length in bytes
|
||||
* @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision)
|
||||
* @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance is freed or not. If set
|
||||
* to 'true' than pRawData will be freed when instanced is being freed
|
||||
* @param[in] layerType The link layer type of this raw packet. The default is Ethernet
|
||||
*/
|
||||
RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET);
|
||||
|
||||
/**
|
||||
* A default constructor that initializes class'es attributes to default value:
|
||||
* - data pointer is set to NULL
|
||||
* - data length is set to 0
|
||||
* - deleteRawDataAtDestructor is set to 'true'
|
||||
* @todo timestamp isn't set here to a default value
|
||||
*/
|
||||
RawPacket();
|
||||
|
||||
/**
|
||||
* A destructor for this class. Frees the raw data if deleteRawDataAtDestructor was set to 'true'
|
||||
*/
|
||||
virtual ~RawPacket();
|
||||
|
||||
/**
|
||||
* A copy constructor that copies all data from another instance. Notice all raw data is copied (using memcpy), so when the original or
|
||||
* the other instance are freed, the other won't be affected
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
RawPacket(const RawPacket& other);
|
||||
|
||||
/**
|
||||
* Assignment operator overload for this class. When using this operator on an already initialized RawPacket instance,
|
||||
* the original raw data is freed first. Then the other instance is copied to this instance, the same way the copy constructor works
|
||||
* @todo free raw data only if deleteRawDataAtDestructor was set to 'true'
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
RawPacket& operator=(const RawPacket& other);
|
||||
|
||||
/**
|
||||
* @return RawPacket object type. Each derived class should return a different value
|
||||
*/
|
||||
virtual uint8_t getObjectType() const { return 0; }
|
||||
|
||||
/**
|
||||
* Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be freed first
|
||||
* @param[in] pRawData A pointer to the new raw data
|
||||
* @param[in] rawDataLen The new raw data length in bytes
|
||||
* @param[in] timestamp The timestamp packet was received by the NIC (in usec precision)
|
||||
* @param[in] layerType The link layer type for this raw data
|
||||
* @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the actual packet length. This parameter represents the packet
|
||||
* length. This parameter is optional, if not set or set to -1 it is assumed both lengths are equal
|
||||
* @return True if raw data was set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
|
||||
|
||||
/**
|
||||
* Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be freed first
|
||||
* @param[in] pRawData A pointer to the new raw data
|
||||
* @param[in] rawDataLen The new raw data length in bytes
|
||||
* @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision)
|
||||
* @param[in] layerType The link layer type for this raw data
|
||||
* @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the actual packet length. This parameter represents the packet
|
||||
* length. This parameter is optional, if not set or set to -1 it is assumed both lengths are equal
|
||||
* @return True if raw data was set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1);
|
||||
|
||||
/**
|
||||
* Get raw data pointer
|
||||
* @return A read-only pointer to the raw data
|
||||
*/
|
||||
const uint8_t* getRawData() const { return m_RawData; }
|
||||
|
||||
/**
|
||||
* Get the link layer type
|
||||
* @return the type of the link layer
|
||||
*/
|
||||
LinkLayerType getLinkLayerType() const { return m_LinkLayerType; }
|
||||
|
||||
/**
|
||||
* This static method validates whether a link type integer value is valid
|
||||
* @param[in] linkTypeValue Link type integer value
|
||||
* @return True if the link type value is valid and can be casted into LinkLayerType enum, false otherwise
|
||||
*/
|
||||
static bool isLinkTypeValid(int linkTypeValue);
|
||||
|
||||
/**
|
||||
* Get raw data length in bytes
|
||||
* @return Raw data length in bytes
|
||||
*/
|
||||
int getRawDataLen() const { return m_RawDataLen; }
|
||||
|
||||
/**
|
||||
* Get frame length in bytes
|
||||
* @return frame length in bytes
|
||||
*/
|
||||
int getFrameLength() const { return m_FrameLength; }
|
||||
/**
|
||||
* Get raw data timestamp
|
||||
* @return Raw data timestamp
|
||||
*/
|
||||
timespec getPacketTimeStamp() const { return m_TimeStamp; }
|
||||
|
||||
/**
|
||||
* Set raw packet timestamp with usec precision
|
||||
* @param[in] timestamp The timestamp to set (with usec precision)
|
||||
* @return True if timestamp was set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setPacketTimeStamp(timeval timestamp);
|
||||
|
||||
/**
|
||||
* Set raw packet timestamp with nsec precision
|
||||
* @param[in] timestamp The timestamp to set (with nsec precision)
|
||||
* @return True if timestamp was set successfully, false otherwise
|
||||
*/
|
||||
virtual bool setPacketTimeStamp(timespec timestamp);
|
||||
|
||||
/**
|
||||
* Get an indication whether raw data was already set for this instance.
|
||||
* @return True if raw data was set for this instance. Raw data can be set using the non-default constructor, using setRawData(), using
|
||||
* the copy constructor or using the assignment operator. Returns false otherwise, for example: if the instance was created using the
|
||||
* default constructor or clear() was called
|
||||
*/
|
||||
bool isPacketSet() const { return m_RawPacketSet; }
|
||||
|
||||
/**
|
||||
* Clears all members of this instance, meaning setting raw data to NULL, raw data length to 0, etc. Currently raw data is always freed,
|
||||
* even if deleteRawDataAtDestructor was set to 'false'
|
||||
* @todo deleteRawDataAtDestructor was set to 'true', don't free the raw data
|
||||
* @todo set timestamp to a default value as well
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Append data to the end of current data. This method works without allocating more memory, it just uses memcpy() to copy dataToAppend at
|
||||
* the end of the current data. This means that the method assumes this memory was already allocated by the user. If it isn't the case then
|
||||
* this method will cause memory corruption
|
||||
* @param[in] dataToAppend A pointer to the data to append to current raw data
|
||||
* @param[in] dataToAppendLen Length in bytes of dataToAppend
|
||||
*/
|
||||
virtual void appendData(const uint8_t* dataToAppend, size_t dataToAppendLen);
|
||||
|
||||
/**
|
||||
* Insert new data at some index of the current data and shift the remaining old data to the end. This method works without allocating more memory,
|
||||
* it just copies dataToAppend at the relevant index and shifts the remaining data to the end. This means that the method assumes this memory was
|
||||
* already allocated by the user. If it isn't the case then this method will cause memory corruption
|
||||
* @param[in] atIndex The index to insert the new data to
|
||||
* @param[in] dataToInsert A pointer to the new data to insert
|
||||
* @param[in] dataToInsertLen Length in bytes of dataToInsert
|
||||
*/
|
||||
virtual void insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen);
|
||||
|
||||
/**
|
||||
* Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be shifted back
|
||||
* @param[in] atIndex The index to start removing bytes from
|
||||
* @param[in] numOfBytesToRemove Number of bytes to remove
|
||||
* @return True if all bytes were removed successfully, or false if atIndex+numOfBytesToRemove is out-of-bounds of the raw data buffer
|
||||
*/
|
||||
virtual bool removeData(int atIndex, size_t numOfBytesToRemove);
|
||||
|
||||
/**
|
||||
* Re-allocate raw packet buffer meaning add size to it without losing the current packet data. This method allocates the required buffer size as instructed
|
||||
* by the use and then copies the raw data from the current allocated buffer to the new one. This method can become useful if the user wants to insert or
|
||||
* append data to the raw data, and the previous allocated buffer is too small, so the user wants to allocate a larger buffer and get RawPacket instance to
|
||||
* point to it
|
||||
* @param[in] newBufferLength The new buffer length as required by the user. The method is responsible to allocate the memory
|
||||
* @return True if data was reallocated successfully, false otherwise
|
||||
*/
|
||||
virtual bool reallocateData(size_t newBufferLength);
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif
|
||||
164
pcappp/include/pcapplusplus/RawSocketDevice.h
Normal file
164
pcappp/include/pcapplusplus/RawSocketDevice.h
Normal file
@@ -0,0 +1,164 @@
|
||||
#ifndef PCAPPP_RAW_SOCKET_DEVICE
|
||||
#define PCAPPP_RAW_SOCKET_DEVICE
|
||||
|
||||
/// @file
|
||||
|
||||
#include "IpAddress.h"
|
||||
#include "Device.h"
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @class RawSocketDevice
|
||||
* A class that wraps the raw socket functionality. A raw socket is a network socket that allows direct sending and receiving
|
||||
* of IP packets without any protocol-specific transport layer formatting
|
||||
* (taken from Wikipedia: https://en.wikipedia.org/wiki/Network_socket#Raw_socket).
|
||||
* This wrapper class enables creation of a raw socket, binding it to a network interface, and then receiving and sending
|
||||
* packets on it. Current implementation supports only Windows and Linux because other platforms provide poor support for raw
|
||||
* sockets making them practically unusable. There are also major differences between Linux and Windows in raw socket
|
||||
* implementation, let's mention some of the:
|
||||
* - On Windows administrative privileges are required for raw sockets creation, meaning the process running the code
|
||||
* has to have these privileges. In Linux 'sudo' is required
|
||||
* - On Windows raw sockets are implemented in L3, meaning the L2 (Ethernet) layer is omitted by the socket and only L3 and
|
||||
* up are visible to the user. On Linux raw sockets are implemented on L2, meaning all layers (including the Ethernet
|
||||
* data) are visible to the user.
|
||||
* - On Windows sending packets is not supported, a raw socket can only receive packets. On Linux both send and receive are
|
||||
* supported
|
||||
* - Linux doesn't require binding to a specific network interface for receiving packets, but it does require binding
|
||||
* for sending packets. Windows requires binding for receiving packets. For the sake of keeping a unified and simple cross-platform interface
|
||||
* this class requires binding for both Linux and Windows, on both send and receive
|
||||
*
|
||||
* More details about opening the raw socket, receiving and sending packets are explained in the corresponding class methods.
|
||||
* Raw sockets are supported for both IPv4 and IPv6, so you can create and bind raw sockets to each of the two.
|
||||
* Also, there is no limit on the number of sockets opened for a specific IP address or network interface, so you can
|
||||
* create multiple instances of this class and bind all of them to the same interface and IP address.
|
||||
*/
|
||||
class RawSocketDevice : public IDevice
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum for reporting packet receive results
|
||||
*/
|
||||
enum RecvPacketResult
|
||||
{
|
||||
/** Receive success */
|
||||
RecvSuccess = 0,
|
||||
/** Receive timeout - timeout expired without any packets being captured */
|
||||
RecvTimeout = 1,
|
||||
/** Receive would block - in non-blocking mode if there are no packets in the rx queue the receive method will return immediately with this return value */
|
||||
RecvWouldBlock = 2,
|
||||
/** Receive error, usually will be followed by an error log */
|
||||
RecvError = 3
|
||||
};
|
||||
|
||||
/*
|
||||
* A c'tor for this class. This c'tor doesn't create the raw socket, but rather initializes internal structures. The actual
|
||||
* raw socket creation is done in the open() method. Each raw socket is bound to a network interface which means
|
||||
* packets will be received and sent from only from this network interface only
|
||||
* @param[in] interfaceIP The network interface IP to bind the raw socket to. It can be either an IPv4 or IPv6 address
|
||||
* (both are supported in raw sockets)
|
||||
*/
|
||||
RawSocketDevice(const IPAddress& interfaceIP);
|
||||
|
||||
/**
|
||||
* A d'tor for this class. It closes the raw socket if not previously closed by calling close()
|
||||
*/
|
||||
~RawSocketDevice();
|
||||
|
||||
/**
|
||||
* Receive a packet on the raw socket. This method has several modes of operation:
|
||||
* - Blocking/non-blocking - in blocking mode the method will not return until a packet is received on the socket
|
||||
* or until the timeout expires. In non-blocking mode it will return immediately and in case no packets are on the
|
||||
* receive queue RawSocketDevice#RecvWouldBlock will be returned. Unless specified otherwise, the default value is
|
||||
* blocking mode
|
||||
* - Receive timeout - in blocking mode, the user can set a timeout to wait until a packet is received. If the timeout
|
||||
* expires and no packets were received, the method will return RawSocketDevice#RecvTimeout. The default value is a
|
||||
* negative value which means no timeout
|
||||
*
|
||||
* There is a slight difference on this method's behavior between Windows and Linux around how packets are received.
|
||||
* On Linux the received packet contains all layers starting from the L2 (Ethernet). However on Windows raw socket are
|
||||
* integrated in L3 level so the received packet contains only L3 (IP) layer and up.
|
||||
* @param[out] rawPacket An empty packet instance where the received packet data will be written to
|
||||
* @param[in] blocking Indicates whether to run in blocking or non-blocking mode. Default value is blocking
|
||||
* @param[in] timeout When in blocking mode, specifies the timeout [in seconds] to wait for a packet. If timeout expired
|
||||
* and no packets were captured the method will return RawSocketDevice#RecvTimeout. Zero or negative values mean no
|
||||
* timeout. The default value is no timeout
|
||||
* @return The method returns one on the following values:
|
||||
* - RawSocketDevice#RecvSuccess is returned if a packet was received successfully
|
||||
* - RawSocketDevice#RecvTimeout is returned if in blocking mode and timeout expired
|
||||
* - RawSocketDevice#RecvWouldBlock is returned if in non-blocking mode and no packets were captured
|
||||
* - RawSocketDevice#RecvError is returned if an error occurred such as device is not opened or the recv operation
|
||||
* returned some error. A log message will be followed specifying the error and error code
|
||||
*/
|
||||
RecvPacketResult receivePacket(RawPacket& rawPacket, bool blocking = true, int timeout = -1);
|
||||
|
||||
/**
|
||||
* Receive packets into a packet vector for a certain amount of time. This method starts a timer and invokes the
|
||||
* receivePacket() method in blocking mode repeatedly until the timeout expires. All packets received successfully are
|
||||
* put into a packet vector
|
||||
* @param[out] packetVec The packet vector to add the received packet to
|
||||
* @param[in] timeout Timeout in seconds to receive packets on the raw socket
|
||||
* @param[out] failedRecv Number of receive attempts that failed
|
||||
* @return The number of packets received successfully
|
||||
*/
|
||||
int receivePackets(RawPacketVector& packetVec, int timeout, int& failedRecv);
|
||||
|
||||
/**
|
||||
* Send an Ethernet packet to the network. L2 protocols other than Ethernet are not supported in raw sockets.
|
||||
* The entire packet is sent as is, including the original Ethernet and IP data.
|
||||
* This method is only supported in Linux as Windows doesn't allow sending packets from raw sockets. Using
|
||||
* it from other platforms will also return "false" with a corresponding error log message
|
||||
* @param[in] rawPacket The packet to send
|
||||
* @return True if packet was sent successfully or false if the socket is not open, if the packet is not Ethernet or
|
||||
* if there was a failure sending the packet
|
||||
*/
|
||||
bool sendPacket(const RawPacket* rawPacket);
|
||||
|
||||
/**
|
||||
* Send a set of Ethernet packets to the network. L2 protocols other than Ethernet are not supported by raw sockets.
|
||||
* The entire packet is sent as is, including the original Ethernet and IP data.
|
||||
* This method is only supported in Linux as Windows doesn't allow sending packets from raw sockets. Using it from
|
||||
* other platforms will return "false" with an appropriate error log message
|
||||
* @param[in] packetVec The set of packets to send
|
||||
* @return The number of packets sent successfully. For packets that weren't sent successfully there will be a
|
||||
* corresponding error message printed to log
|
||||
*/
|
||||
int sendPackets(const RawPacketVector& packetVec);
|
||||
|
||||
// overridden methods
|
||||
|
||||
/**
|
||||
* Open the device by creating a raw socket and binding it to the network interface specified in the c'tor
|
||||
* @return True if device was opened successfully, false otherwise with a corresponding error log message
|
||||
*/
|
||||
virtual bool open();
|
||||
|
||||
/**
|
||||
* Close the raw socket
|
||||
*/
|
||||
virtual void close();
|
||||
|
||||
private:
|
||||
|
||||
enum SocketFamily
|
||||
{
|
||||
Ethernet = 0,
|
||||
IPv4 = 1,
|
||||
IPv6 = 2
|
||||
};
|
||||
|
||||
SocketFamily m_SockFamily;
|
||||
void* m_Socket;
|
||||
IPAddress m_InterfaceIP;
|
||||
|
||||
RecvPacketResult getError(int& errorCode) const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PCAPPP_RAW_SOCKET_DEVICE
|
||||
430
pcappp/include/pcapplusplus/SSHLayer.h
Normal file
430
pcappp/include/pcapplusplus/SSHLayer.h
Normal file
@@ -0,0 +1,430 @@
|
||||
#ifndef PACKETPP_SSH_LAYER
|
||||
#define PACKETPP_SSH_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file introduces classes and structures that represent the SSH (Secure Shell) protocol.
|
||||
*
|
||||
* An overview of this protocol can be found here: https://en.wikipedia.org/wiki/Ssh_(Secure_Shell)
|
||||
*
|
||||
* For more details please refer to RFC 4253: https://tools.ietf.org/html/rfc4253
|
||||
*
|
||||
* These current implementation supports parsing of SSH packets when possible (meaning when they are not encrypted).
|
||||
* Creation and editing of SSH packets is currently __not supported__.
|
||||
*
|
||||
* SSH typically uses TCP port 22 so PcapPlusPlus assumes all traffic on this port is SSH traffic.
|
||||
* PcapPlusPlus uses some heuristics to determine the type of the SSH message (which will be covered later).
|
||||
* If it doesn't find a match to one of the other SSH messages, it assumes it is an encrypted SSH message.
|
||||
*
|
||||
* Following is an overview of the SSH protocol classes currently supported in PcapPlusPlus. They cover the different messages of the SSH protocol:
|
||||
*
|
||||
@verbatim
|
||||
|
||||
+----------------------------+ SSH version identification
|
||||
+---| SSHIdentificationMessage | ===> as described here:
|
||||
| +----------------------------+ https://tools.ietf.org/html/rfc4253#section-4.2
|
||||
|
|
||||
+------------+ | +----------------------------+ SSH handshake message
|
||||
| SSHLayer |-------------+---| SSHHandshakeMessage | ===> which is typically one of the messages described here:
|
||||
| (abstract) | | +----------------------------+ https://tools.ietf.org/html/rfc4253#section-12
|
||||
+------------+ | |
|
||||
| | +----------------------------+ SSH Key Exchange message
|
||||
| +-----| SSHKeyExchangeInitMessage | ===> as described here:
|
||||
| +----------------------------+ https://tools.ietf.org/html/rfc4253#section-7
|
||||
|
|
||||
| +----------------------------+
|
||||
+---| SSHEncryptedMessage | ===> An encrypted SSH message
|
||||
+----------------------------+
|
||||
|
||||
@endverbatim
|
||||
|
||||
* The following points describe the heuristics for deciding the message type for each packet:
|
||||
* 1. If the data starts with the characters "SSH-" and ends with "\n" (or "\r\n") it's assumed the message is of type
|
||||
* pcpp#SSHIdentificationMessage
|
||||
* 2. Try to determine if this is a non-encrypted SSH handshake message:
|
||||
* - Look at the first 4 bytes of the data which may contain the packet length and see if the value is smaller of equal
|
||||
* than the entire layer length
|
||||
* - The next byte contains the padding length, check if it's smaller or equal than the packet length
|
||||
* - The next byte contains the message type, check if the value is a valid message type as described in:
|
||||
* <https://tools.ietf.org/html/rfc4253#section-12>
|
||||
*
|
||||
* If all of these condition are met, this message is either pcpp#SSHKeyExchangeInitMessage (if message type is
|
||||
* pcpp#SSHHandshakeMessage#SSH_MSG_KEX_INIT) or pcpp#SSHHandshakeMessage (for all other message types)
|
||||
* 3. If non of these conditions are met, it is assumed this is an encrypted message (pcpp#SSHEncryptedMessage)
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class SSHLayer
|
||||
* This is the base class for the SSH layer. It is an abstract class that cannot be instantiated.
|
||||
* It holds some common functionality, but its most important method is createSSHMessage()
|
||||
* which takes raw data and creates an SSH message according to the heuristics described
|
||||
* in the SSHLayer.h file description
|
||||
*/
|
||||
class SSHLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A static method that takes raw packet data and uses the heuristics described in the
|
||||
* SSHLayer.h file description to create an SSH layer instance. This method assumes the data is
|
||||
* indeed SSH data and not some other arbitrary data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
* @return An instance of one of the classes that inherit SSHLayer as described in the
|
||||
* SSHLayer.h file description
|
||||
*/
|
||||
static SSHLayer* createSSHMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A static method that takes src and dst ports and determines whether it's SSH traffic or not.
|
||||
* @param[in] portSrc The source TCP port to examine
|
||||
* @param[in] portDst The dest TCP port to examine
|
||||
* @return Currently the implementation is very simple and returns "true" if either src or dst ports
|
||||
* are equal to 22, "false" otherwise
|
||||
*/
|
||||
static bool isSSHPort(uint16_t portSrc, uint16_t portDst) { return portSrc == 22 || portDst == 22; }
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Several SSH records can reside in a single packets. This method examins the remaining data and creates additional
|
||||
* SSH records if applicable
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
|
||||
|
||||
protected:
|
||||
// protected c'tor, this class cannot be instantiated
|
||||
SSHLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = SSH; }
|
||||
|
||||
private:
|
||||
// this layer supports only parsing
|
||||
SSHLayer();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class SSHIdentificationMessage
|
||||
* A class that represents SSH identification message as described in RFC 4253: <https://tools.ietf.org/html/rfc4253#section-4.2>
|
||||
*
|
||||
* The message content is typically a string that contains the protocol version, software version and a few more details.
|
||||
* This string can be retrieved using the getIdentificationMessage() method
|
||||
*/
|
||||
class SSHIdentificationMessage : public SSHLayer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @return The SSH identification message which is typically the content of this message
|
||||
*/
|
||||
std::string getIdentificationMessage();
|
||||
|
||||
/**
|
||||
* A static method that takes raw data and tries to parse it as an SSH identification message using the heuristics described
|
||||
* in the SSHLayer.h file description. It returns a SSHIdentificationMessage instance if such a message can be identified or NULL
|
||||
* otherwise.
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
* @return An instance of SSHIdentificationMessage or NULL if this is not an identification message
|
||||
*/
|
||||
static SSHIdentificationMessage* tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size of the identification message
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
// this layer supports only parsing
|
||||
SSHIdentificationMessage();
|
||||
|
||||
// private c'tor, this class cannot be instantiated
|
||||
SSHIdentificationMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class SSHHandshakeMessage
|
||||
* A class representing all of the non-encrypted SSH handshake messages.
|
||||
* An handshake message typically has the following structure:
|
||||
*
|
||||
@verbatim
|
||||
0 1 2 3 4 5 6
|
||||
+---------+---------+---------+---------+---------+---------+----------- ---------+
|
||||
| Packet Length | Padding | Message | Message .... Padding |
|
||||
| | Length | Type | Content .... |
|
||||
+---------------------------------------+---------+---------+----------- ---------+
|
||||
@endverbatim
|
||||
*
|
||||
* The first 4 bytes hold the packet length, followed by 1 byte that holds the padding length (which comes at the end of the message),
|
||||
* then 1 byte that holds the message type (which can be of type SSHHandshakeMessage#SSHHandshakeMessageType) and then the message content.
|
||||
* At the end of the content there is typically padding.
|
||||
*
|
||||
* This class provides access to all of these values. The message content itself is not parse with the exception of SSHKeyExchangeInitMessage
|
||||
* which inherits from this class and provides parsing of the Key Exchange Init message.
|
||||
*/
|
||||
class SSHHandshakeMessage : public SSHLayer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* An enum that represents SSH non-encrypted message types
|
||||
*/
|
||||
enum SSHHandshakeMessageType
|
||||
{
|
||||
/** Key Exchange Init message */
|
||||
SSH_MSG_KEX_INIT = 20,
|
||||
/** New Keys message */
|
||||
SSH_MSG_NEW_KEYS = 21,
|
||||
/** Diffie-Hellman Key Exchange Init message */
|
||||
SSH_MSG_KEX_DH_INIT = 30,
|
||||
/** message */
|
||||
SSH_MSG_KEX_DH_REPLY = 31,
|
||||
/** Diffie-Hellman Group Exchange Init message */
|
||||
SSH_MSG_KEX_DH_GEX_INIT = 32,
|
||||
/** "Diffie-Hellman Group Exchange Reply message */
|
||||
SSH_MSG_KEX_DH_GEX_REPLY = 33,
|
||||
/** Diffie-Hellman Group Exchange Request message */
|
||||
SSH_MSG_KEX_DH_GEX_REQUEST = 34,
|
||||
/** Unknown message */
|
||||
SSH_MSG_UNKNOWN = 999
|
||||
};
|
||||
|
||||
/**
|
||||
* @return The message type
|
||||
*/
|
||||
SSHHandshakeMessageType getMessageType() const;
|
||||
|
||||
/**
|
||||
* @return A string representation of the message type
|
||||
*/
|
||||
std::string getMessageTypeStr() const;
|
||||
|
||||
/**
|
||||
* @return A raw byte stream of the message content
|
||||
*/
|
||||
uint8_t* getSSHHandshakeMessage() const;
|
||||
|
||||
/**
|
||||
* @return The message content length in [bytes] which is calculated by the overall packet length
|
||||
* minus the message header (which includes packet length, padding length and message type) and
|
||||
* minus the padding bytes
|
||||
*/
|
||||
size_t getSSHHandshakeMessageLength() const;
|
||||
|
||||
/**
|
||||
* @return The padding length in [bytes]
|
||||
*/
|
||||
size_t getPaddingLength() const;
|
||||
|
||||
/**
|
||||
* A static method that takes raw packet data and uses some heuristics described in the
|
||||
* SSHLayer.h file description to parse it as SSH handshake message instance
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
* @return Upon successful parsing the return value would be an instance of SSHKeyExchangeInitMessage
|
||||
* for Key Exchange Init message or SSHHandshakeMessage for any other message type. If parsing fails NULL
|
||||
* will be returned
|
||||
*/
|
||||
static SSHHandshakeMessage* tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size of the SSH handshake message including the padding and message header
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* An internal struct representing the SSH handshake message header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ssh_message_base
|
||||
{
|
||||
uint32_t packetLength;
|
||||
uint8_t paddingLength;
|
||||
uint8_t messageCode;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// this layer supports only parsing
|
||||
SSHHandshakeMessage();
|
||||
|
||||
// private c'tor, this class cannot be instantiated
|
||||
SSHHandshakeMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
ssh_message_base* getMsgBaseHeader() const { return (ssh_message_base*)m_Data; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class SSHKeyExchangeInitMessage
|
||||
* A class representing the SSH Key Exchange Init message. This is a non-encrypted message that contains information
|
||||
* about the algorithms used for key exchange, encryption, MAC and compression. This class provides methods to access
|
||||
* these details
|
||||
*/
|
||||
class SSHKeyExchangeInitMessage : public SSHHandshakeMessage
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A c'tor for this class that accepts raw message data. Please avoid using it as it's used internally
|
||||
* when parsing SSH handshake messages in SSHHandshakeMessage#tryParse()
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SSHKeyExchangeInitMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* Each SSH Key Exchange Init message contains a random 16-byte value generated by the sender.
|
||||
* This method returns a pointer to this 16-byte cookie. To get the value as a hex string
|
||||
* please refer to getCookieAsHexStream()
|
||||
* @return A pointer to the 16-byte cookie value or NULL if the message is malformed
|
||||
*/
|
||||
uint8_t* getCookie();
|
||||
|
||||
/**
|
||||
* Each SSH Key Exchange Init message contains a random 16-byte value generated by the sender.
|
||||
* This method returns the 16-byte cookie as a hex stream. To get the raw data please refer to
|
||||
* getCookie()
|
||||
* @return A hex stream of the 16-byte cookie value or an empty string if the message is malformed
|
||||
*/
|
||||
std::string getCookieAsHexStream();
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of the key exchange algorithms used in this session.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getKeyExchangeAlgorithms() { return getFieldValue(0); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of the algorithms supported for the server host key.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getServerHostKeyAlgorithms() { return getFieldValue(1); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of acceptable symmetric encryption algorithms (also known as ciphers)
|
||||
* from the client to the server. Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getEncryptionAlgorithmsClientToServer() { return getFieldValue(2); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of acceptable symmetric encryption algorithms (also known as ciphers)
|
||||
* from the server to the client. Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getEncryptionAlgorithmsServerToClient() { return getFieldValue(3); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of acceptable MAC algorithms from the client to the server.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getMacAlgorithmsClientToServer() { return getFieldValue(4); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of acceptable MAC algorithms from the server to the client.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getMacAlgorithmsServerToClient() { return getFieldValue(5); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of acceptable compression algorithms from the client to the server.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getCompressionAlgorithmsClientToServer() { return getFieldValue(6); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of acceptable compression algorithms from the server to the client.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getCompressionAlgorithmsServerToClient() { return getFieldValue(7); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of language tags from the client to the server.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getLanguagesClientToServer() { return getFieldValue(8); }
|
||||
|
||||
/**
|
||||
* @return A comma-separated list of language tags from the server to the client.
|
||||
* Can be empty if the value is missing or the message is malformed
|
||||
*/
|
||||
std::string getLanguagesServerToClient() { return getFieldValue(9); }
|
||||
|
||||
/**
|
||||
* @return Indicates whether a guessed key exchange packet follows. If a
|
||||
* guessed packet will be sent, the return value is true. If no guessed
|
||||
* packet will be sent or if this value is missing, the return value is false.
|
||||
*/
|
||||
bool isFirstKexPacketFollows();
|
||||
|
||||
private:
|
||||
size_t m_FieldOffsets[11];
|
||||
bool m_OffsetsInitialized;
|
||||
|
||||
void parseMessageAndInitOffsets();
|
||||
|
||||
std::string getFieldValue(int fieldOffsetIndex);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class SSHEncryptedMessage
|
||||
* A class representing an SSH encrypted message. In such messages there is very little information to extract from the packet,
|
||||
* hence this class doesn't expose any methods or getters, other than the ones inherited from parent classes.
|
||||
*
|
||||
* It is assumed that any SSH message which does not fit to any of the other SSH message types, according to the heuristics described in
|
||||
* the SSHLayer.h file description, is considered as an encrypted message.
|
||||
*/
|
||||
class SSHEncryptedMessage : public SSHLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class that accepts raw message data. Please avoid using it as it's used internally
|
||||
* when parsing SSH messagess in SSHLayer#createSSHMessage()
|
||||
*/
|
||||
SSHEncryptedMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The size of the message which is equal to the size of the layer
|
||||
*/
|
||||
size_t getHeaderLen() const { return m_DataLen; }
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_SSH_LAYER
|
||||
612
pcappp/include/pcapplusplus/SSLCommon.h
Normal file
612
pcappp/include/pcapplusplus/SSLCommon.h
Normal file
@@ -0,0 +1,612 @@
|
||||
#ifndef PACKETPP_SSL_LAYER_COMMON
|
||||
#define PACKETPP_SSL_LAYER_COMMON
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* See detailed explanation of the TLS/SSL protocol support in PcapPlusPlus in SSLLayer.h
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct ssl_tls_record_layer
|
||||
* The common part of all SSL/TLS messages
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ssl_tls_record_layer
|
||||
{
|
||||
/** Message (record) type (one of ::SSLRecordType) */
|
||||
uint8_t recordType;
|
||||
/** Message (record) version (one of SSLVersion::SSLVersionEnum) */
|
||||
uint16_t recordVersion;
|
||||
/** Message (record) length in bytes */
|
||||
uint16_t length;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct ssl_tls_handshake_layer
|
||||
* The common part of all SSL/TLS handshake message types
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ssl_tls_handshake_layer
|
||||
{
|
||||
/** Type of the handshake message (one of ::SSLHandshakeType) */
|
||||
uint8_t handshakeType;
|
||||
/** Length of the message. Length is 3-Byte long, This is the MSB byte */
|
||||
uint8_t length1;
|
||||
/** Length of the message. Length is 3-Byte long, This is the 2 LSB bytes */
|
||||
uint16_t length2;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct ssl_tls_client_server_hello
|
||||
* The common header part of client-hello and server-hello handshake messages
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ssl_tls_client_server_hello : ssl_tls_handshake_layer
|
||||
{
|
||||
/** SSL/TLS handshake version (one of SSLVersion::SSLVersionEnum) */
|
||||
uint16_t handshakeVersion;
|
||||
/** 32-bytes random number */
|
||||
uint8_t random[32];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct ssl_tls_change_cipher_spec
|
||||
* SSL/TLS change-cipher-spec message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ssl_tls_change_cipher_spec
|
||||
{
|
||||
/** Unused byte */
|
||||
uint8_t changeCipherSpec;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @struct ssl_tls_alert
|
||||
* SSL/TLS alert message structure
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct ssl_tls_alert
|
||||
{
|
||||
/** Alert level (one of ::SSLAlertLevel) */
|
||||
uint8_t alertLevel;
|
||||
/** Alert description (one of ::SSLAlertDescription) */
|
||||
uint8_t alertDescription;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* SSL/TLS message types
|
||||
*/
|
||||
enum SSLRecordType
|
||||
{
|
||||
/** Change-cipher-spec message */
|
||||
SSL_CHANGE_CIPHER_SPEC = 20,
|
||||
/** SSL alert message */
|
||||
SSL_ALERT = 21,
|
||||
/** SSL handshake message */
|
||||
SSL_HANDSHAKE = 22,
|
||||
/** SSL data message */
|
||||
SSL_APPLICATION_DATA = 23
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class SSLVersion
|
||||
* A wrapper class for SSL/TLS versions. The SSL/TLS version is typically represented by a 2-byte number,
|
||||
* for example TLS 1.2 is represented by 0x0303.
|
||||
* This class wraps the numeric value and provides methods to convert it into an enum, string, etc.
|
||||
*/
|
||||
class SSLVersion
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* SSL/TLS versions enum
|
||||
*/
|
||||
enum SSLVersionEnum
|
||||
{
|
||||
/** SSL 2.0 */
|
||||
SSL2 = 0x0200,
|
||||
/** SSL 3.0 */
|
||||
SSL3 = 0x0300,
|
||||
/** TLS 1.0 */
|
||||
TLS1_0 = 0x0301,
|
||||
/** TLS 1.1 */
|
||||
TLS1_1 = 0x0302,
|
||||
/** TLS 1.2 */
|
||||
TLS1_2 = 0x0303,
|
||||
/** TLS 1.3 */
|
||||
TLS1_3 = 0x0304,
|
||||
/** TLS 1.3 (draft 14) */
|
||||
TLS1_3_D14 = 0x7f0e,
|
||||
/** TLS 1.3 (draft 15) */
|
||||
TLS1_3_D15 = 0x7f0f,
|
||||
/** TLS 1.3 (draft 16) */
|
||||
TLS1_3_D16 = 0x7f10,
|
||||
/** TLS 1.3 (draft 17) */
|
||||
TLS1_3_D17 = 0x7f11,
|
||||
/** TLS 1.3 (draft 18) */
|
||||
TLS1_3_D18 = 0x7f12,
|
||||
/** TLS 1.3 (draft 19) */
|
||||
TLS1_3_D19 = 0x7f13,
|
||||
/** TLS 1.3 (draft 20) */
|
||||
TLS1_3_D20 = 0x7f14,
|
||||
/** TLS 1.3 (draft 21) */
|
||||
TLS1_3_D21 = 0x7f15,
|
||||
/** TLS 1.3 (draft 22) */
|
||||
TLS1_3_D22 = 0x7f16,
|
||||
/** TLS 1.3 (draft 23) */
|
||||
TLS1_3_D23 = 0x7f17,
|
||||
/** TLS 1.3 (draft 24) */
|
||||
TLS1_3_D24 = 0x7f18,
|
||||
/** TLS 1.3 (draft 25) */
|
||||
TLS1_3_D25 = 0x7f19,
|
||||
/** TLS 1.3 (draft 26) */
|
||||
TLS1_3_D26 = 0x7f1a,
|
||||
/** TLS 1.3 (draft 27) */
|
||||
TLS1_3_D27 = 0x7f1b,
|
||||
/** TLS 1.3 (draft 28) */
|
||||
TLS1_3_D28 = 0x7f1c,
|
||||
/** TLS 1.3 (Facebook draft 23) */
|
||||
TLS1_3_FBD23 = 0xfb17,
|
||||
/** TLS 1.3 (Facebook draft 26) */
|
||||
TLS1_3_FBD26 = 0xfb1a,
|
||||
/** Unknown value */
|
||||
Unknown = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for this class.
|
||||
* @param[in] sslVersionValue The numeric value representing this SSL/TLS version. For example:
|
||||
* for TLS 1.2 this would be 0x0303.
|
||||
*/
|
||||
SSLVersion(uint16_t sslVersionValue) { m_SSLVersionValue = sslVersionValue; }
|
||||
|
||||
/**
|
||||
* @return An enum value of type SSLVersion::SSLVersionEnum representing the SSL/TLS version.
|
||||
* If the numeric value is an invalid SSL/TLS version SSLVersion::Unknown will be returned.
|
||||
* @param[in] countTlsDraftsAs1_3 A flag indicating whether to return the enum value SSLVersion::TLS1_3 for all TLS 1.3 drafts. If set to "true"
|
||||
* all TLS 1.3 draft values (i.e 0x7f0e - 0x7f1c, 0xfb17, 0xfb1a) will return SSLVersion::TLS1_3, otherwise the corresponding enum values will be
|
||||
* returned. The default value is "false".
|
||||
*/
|
||||
SSLVersionEnum asEnum(bool countTlsDraftsAs1_3 = false);
|
||||
|
||||
/**
|
||||
* @return The numeric value of the SSL/TLs version
|
||||
*/
|
||||
uint16_t asUInt() { return m_SSLVersionValue; }
|
||||
|
||||
/**
|
||||
* @return A string representation of the SSL/TLS version. For example: for TLS 1.2 the string "TLS 1.2" is returned.
|
||||
* If the numeric value is an invalid SSL/TLS version the string "Unknown" will be returned.
|
||||
* @param[in] countTlsDraftsAs1_3 A flag indicating whether to return the string value "TLS 1.3" for all TLS 1.3 drafts. If set to "true"
|
||||
* all TLS 1.3 draft values (i.e 0x7f0e - 0x7f1c, 0xfb17, 0xfb1a) will return "TLS 1.3", otherwise the corresponding string values will be
|
||||
* returned. The default value is "false".
|
||||
*/
|
||||
std::string toString(bool countTlsDraftsAs1_3 = false);
|
||||
|
||||
private:
|
||||
uint16_t m_SSLVersionValue;
|
||||
|
||||
// unimplemented empty c'tor
|
||||
SSLVersion();
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS handshake message types
|
||||
*/
|
||||
enum SSLHandshakeType
|
||||
{
|
||||
/** Hello-request message type */
|
||||
SSL_HELLO_REQUEST = 0,
|
||||
/** Client-hello message type */
|
||||
SSL_CLIENT_HELLO = 1,
|
||||
/** Server-hello message type */
|
||||
SSL_SERVER_HELLO = 2,
|
||||
/** New-session-ticket message type */
|
||||
SSL_NEW_SESSION_TICKET = 4,
|
||||
/** End-of-early-data message type (TLS 1.3) */
|
||||
SSL_END_OF_EARLY_DATE = 5,
|
||||
/** Encrypted-extensions message type (TLS 1.3) */
|
||||
SSL_ENCRYPTED_EXTENSIONS = 8,
|
||||
/** Certificate message type */
|
||||
SSL_CERTIFICATE = 11,
|
||||
/** Server-key-exchange message type */
|
||||
SSL_SERVER_KEY_EXCHANGE = 12,
|
||||
/** Certificate-request message type */
|
||||
SSL_CERTIFICATE_REQUEST = 13,
|
||||
/** Server-hello-done message type */
|
||||
SSL_SERVER_DONE = 14,
|
||||
/** Certificate-verify message type */
|
||||
SSL_CERTIFICATE_VERIFY = 15,
|
||||
/** Client-key-exchange message type */
|
||||
SSL_CLIENT_KEY_EXCHANGE = 16,
|
||||
/** Finish message type */
|
||||
SSL_FINISHED = 20,
|
||||
/** Key-update message type (TLS 1.3) */
|
||||
SSL_KEY_UPDATE = 24,
|
||||
/** Unknown SSL handshake message */
|
||||
SSL_HANDSHAKE_UNKNOWN = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS alert levels
|
||||
*/
|
||||
enum SSLAlertLevel
|
||||
{
|
||||
/** Warning level alert */
|
||||
SSL_ALERT_LEVEL_WARNING = 1,
|
||||
/** Fatal level alert */
|
||||
SSL_ALERT_LEVEL_FATAL = 2,
|
||||
/** For encrypted alerts the level is unknown so this type will be returned */
|
||||
SSL_ALERT_LEVEL_ENCRYPTED = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS alert description types
|
||||
*/
|
||||
enum SSLAlertDescription
|
||||
{
|
||||
/** Close notify alert */
|
||||
SSL_ALERT_CLOSE_NOTIFY = 0,
|
||||
/** Unexpected message alert */
|
||||
SSL_ALERT_UNEXPECTED_MESSAGE = 10,
|
||||
/** Bad record MAC alert */
|
||||
SSL_ALERT_BAD_RECORD_MAC = 20,
|
||||
/** Decryption failed alert */
|
||||
SSL_ALERT_DECRYPTION_FAILED = 21,
|
||||
/** */
|
||||
SSL_ALERT_RECORD_OVERFLOW = 22,
|
||||
/** Decompression failure alert */
|
||||
SSL_ALERT_DECOMPRESSION_FAILURE = 30,
|
||||
/** Handshake failure alert */
|
||||
SSL_ALERT_HANDSHAKE_FAILURE = 40,
|
||||
/** No certificate alert */
|
||||
SSL_ALERT_NO_CERTIFICATE = 41,
|
||||
/** Bad certificate alert */
|
||||
SSL_ALERT_BAD_CERTIFICATE = 42,
|
||||
/** Unsupported certificate */
|
||||
SSL_ALERT_UNSUPPORTED_CERTIFICATE = 43,
|
||||
/** Certificate revoked alert */
|
||||
SSL_ALERT_CERTIFICATE_REVOKED = 44,
|
||||
/** Certificate expired alert */
|
||||
SSL_ALERT_CERTIFICATE_EXPIRED = 45,
|
||||
/** Certificate unknown alert */
|
||||
SSL_ALERT_CERTIFICATE_UNKNOWN = 46,
|
||||
/** Illegal parameter alert */
|
||||
SSL_ALERT_ILLEGAL_PARAMETER = 47,
|
||||
/** Unknown CA alert */
|
||||
SSL_ALERT_UNKNOWN_CA = 48,
|
||||
/** Access denied alert */
|
||||
SSL_ALERT_ACCESS_DENIED = 49,
|
||||
/** Decode error alert */
|
||||
SSL_ALERT_DECODE_ERROR = 50,
|
||||
/** Decrypt error alert */
|
||||
SSL_ALERT_DECRYPT_ERROR = 51,
|
||||
/** Export restriction alert */
|
||||
SSL_ALERT_EXPORT_RESTRICTION = 60,
|
||||
/** Protocol version alert */
|
||||
SSL_ALERT_PROTOCOL_VERSION = 70,
|
||||
/** Insufficient security alert */
|
||||
SSL_ALERT_INSUFFICIENT_SECURITY = 71,
|
||||
/** Internal error alert */
|
||||
SSL_ALERT_INTERNAL_ERROR = 80,
|
||||
/** User cancelled alert */
|
||||
SSL_ALERT_USER_CANCELLED = 90,
|
||||
/** No negotiation alert */
|
||||
SSL_ALERT_NO_RENEGOTIATION = 100,
|
||||
/** Unsupported extension alert */
|
||||
SSL_ALERT_UNSUPPORTED_EXTENSION = 110,
|
||||
/** Encrtpyed alert (cannot determine its type) */
|
||||
SSL_ALERT_ENCRYPTED = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS key exchange algorithms
|
||||
*/
|
||||
enum SSLKeyExchangeAlgorithm
|
||||
{
|
||||
/** NULL value */
|
||||
SSL_KEYX_NULL,
|
||||
/** RSA (Rivest-Shamir-Adleman) */
|
||||
SSL_KEYX_RSA,
|
||||
/** Diffie-Hellman */
|
||||
SSL_KEYX_DH,
|
||||
/** Diffie-Hellman ephemeral */
|
||||
SSL_KEYX_DHE,
|
||||
/** Elliptic curve Diffie<69>Hellman */
|
||||
SSL_KEYX_ECDH,
|
||||
/** Elliptic curve Diffie<69>Hellman ephemeral */
|
||||
SSL_KEYX_ECDHE,
|
||||
/** Fortezza Crypto Card */
|
||||
SSL_KEYX_FORTEZZA,
|
||||
/** Kerberos 5 */
|
||||
SSL_KEYX_KRB5,
|
||||
/** Pre-Shared Key */
|
||||
SSL_KEYX_PSK,
|
||||
/** GOST */
|
||||
SSL_KEYX_GOST,
|
||||
/** Secure Remote Password */
|
||||
SSL_KEYX_SRP,
|
||||
/** PCT */
|
||||
SSL_KEYX_PCT,
|
||||
/** Unknown algorithm */
|
||||
SSL_KEYX_Unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS authentication algorithms
|
||||
*/
|
||||
enum SSLAuthenticationAlgorithm
|
||||
{
|
||||
/** NULL value */
|
||||
SSL_AUTH_NULL,
|
||||
/** RSA (Rivest-Shamir-Adleman) */
|
||||
SSL_AUTH_RSA,
|
||||
/** Digital Signature Standard */
|
||||
SSL_AUTH_DSS,
|
||||
/** Anonymous */
|
||||
SSL_AUTH_anon,
|
||||
/** Diffie-Hellman based key-exchange protocol */
|
||||
SSL_AUTH_KEA,
|
||||
/** Kerberos 5 */
|
||||
SSL_AUTH_KRB5,
|
||||
/** Pre-Shared Key */
|
||||
SSL_AUTH_PSK,
|
||||
/** Elliptic Curve Digital Signature Algorithm */
|
||||
SSL_AUTH_ECDSA,
|
||||
/** GOST */
|
||||
SSL_AUTH_GOST,
|
||||
/** SHA-1 (Secure Hash Algorithm) */
|
||||
SSL_AUTH_SHA,
|
||||
/** PCT */
|
||||
SSL_AUTH_PCT,
|
||||
/** Diffie-Hellman ephemeral */
|
||||
SSL_AUTH_DHE,
|
||||
/** Unknown algorithm */
|
||||
SSL_AUTH_Unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS symmetric encryption algorithms
|
||||
*/
|
||||
enum SSLSymetricEncryptionAlgorithm
|
||||
{
|
||||
/** NULL value */
|
||||
SSL_SYM_NULL,
|
||||
/** RC4_40 */
|
||||
SSL_SYM_RC4_40,
|
||||
/** RC4_128 */
|
||||
SSL_SYM_RC4_128,
|
||||
/** RC2_CBC_40 */
|
||||
SSL_SYM_RC2_CBC_40,
|
||||
/** IDEA_CBC */
|
||||
SSL_SYM_IDEA_CBC,
|
||||
/** DES40_CBC */
|
||||
SSL_SYM_DES40_CBC,
|
||||
/** DES_CBC */
|
||||
SSL_SYM_DES_CBC,
|
||||
/** 3DES_EDE_CBC */
|
||||
SSL_SYM_3DES_EDE_CBC,
|
||||
/** FORTEZZA_CBC */
|
||||
SSL_SYM_FORTEZZA_CBC,
|
||||
/** DES_CBC_40 */
|
||||
SSL_SYM_DES_CBC_40,
|
||||
/** AES_128_CBC */
|
||||
SSL_SYM_AES_128_CBC,
|
||||
/** AES_256_CBC */
|
||||
SSL_SYM_AES_256_CBC,
|
||||
/** CAMELLIA_128_CBC */
|
||||
SSL_SYM_CAMELLIA_128_CBC,
|
||||
/** CAMELLIA_128_GCM */
|
||||
SSL_SYM_CAMELLIA_128_GCM,
|
||||
/** CAMELLIA_256_GCM */
|
||||
SSL_SYM_CAMELLIA_256_GCM,
|
||||
/** RC4_56 */
|
||||
SSL_SYM_RC4_56,
|
||||
/** RC2_CBC_56 */
|
||||
SSL_SYM_RC2_CBC_56,
|
||||
/** GOST28147 */
|
||||
SSL_SYM_GOST28147,
|
||||
/** CAMELLIA_256_CBC */
|
||||
SSL_SYM_CAMELLIA_256_CBC,
|
||||
/** SEED_CBC */
|
||||
SSL_SYM_SEED_CBC,
|
||||
/** AES_128 */
|
||||
SSL_SYM_AES_128,
|
||||
/** AES_256 */
|
||||
SSL_SYM_AES_256,
|
||||
/** SSL_SYM_AES_128_GCM */
|
||||
SSL_SYM_AES_128_GCM,
|
||||
/** AES_256_GCM */
|
||||
SSL_SYM_AES_256_GCM,
|
||||
/** RC4_128_EXPORT40 */
|
||||
SSL_SYM_RC4_128_EXPORT40,
|
||||
/** RC2_CBC_128_CBC */
|
||||
SSL_SYM_RC2_CBC_128_CBC,
|
||||
/** IDEA_128_CBC */
|
||||
SSL_SYM_IDEA_128_CBC,
|
||||
/** DES_64_CBC */
|
||||
SSL_SYM_DES_64_CBC,
|
||||
/** DES_192_EDE3_CBC */
|
||||
SSL_SYM_DES_192_EDE3_CBC,
|
||||
/** RC4_64 */
|
||||
SSL_SYM_RC4_64,
|
||||
/** ARIA_128_CBC*/
|
||||
SSL_SYM_ARIA_128_CBC,
|
||||
/** ARIA_256_CBC */
|
||||
SSL_SYM_ARIA_256_CBC,
|
||||
/** ARIA_128_GCM */
|
||||
SSL_SYM_ARIA_128_GCM,
|
||||
/** ARIA_256_GCM */
|
||||
SSL_SYM_ARIA_256_GCM,
|
||||
/** CHACHA20_POLY1305 */
|
||||
SSL_SYM_CHACHA20_POLY1305,
|
||||
/** AES_128_CCM */
|
||||
SSL_SYM_AES_128_CCM,
|
||||
/** AES_128_CCM_8 */
|
||||
SSL_SYM_AES_128_CCM_8,
|
||||
/** Unknown algorithm */
|
||||
SSL_SYM_Unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS hashing algorithms
|
||||
*/
|
||||
enum SSLHashingAlgorithm
|
||||
{
|
||||
/** NULL value */
|
||||
SSL_HASH_NULL,
|
||||
/** Message-Digest Algorithm */
|
||||
SSL_HASH_MD5,
|
||||
/** SHA-1 (Secure Hash Algorithm) */
|
||||
SSL_HASH_SHA,
|
||||
/** SHA-256 (Secure Hash Algorithm) */
|
||||
SSL_HASH_SHA256,
|
||||
/** GOST 28147 */
|
||||
SSL_HASH_GOST28147,
|
||||
/** GOST R 34.11 */
|
||||
SSL_HASH_GOSTR3411,
|
||||
/** SHA-384 (Secure Hash Algorithm) */
|
||||
SSL_HASH_SHA384,
|
||||
/** CCM mode (Counter with CBC-MAC) */
|
||||
SSL_HASH_CCM,
|
||||
/** CCM mode (Counter with CBC-MAC) */
|
||||
SSL_HASH_CCM_8,
|
||||
/** Unknown algorithm */
|
||||
SSL_HASH_Unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS extension types
|
||||
*/
|
||||
enum SSLExtensionType
|
||||
{
|
||||
/** Server Name Indication extension */
|
||||
SSL_EXT_SERVER_NAME = 0,
|
||||
/** Maximum Fragment Length Negotiation extension */
|
||||
SSL_EXT_MAX_FRAGMENT_LENGTH = 1,
|
||||
/** Client Certificate URLs extension */
|
||||
SSL_EXT_CLIENT_CERTIFICATE_URL = 2,
|
||||
/** Trusted CA Indication extension */
|
||||
SSL_EXT_TRUSTED_CA_KEYS = 3,
|
||||
/** Truncated HMAC extension */
|
||||
SSL_EXT_TRUNCATED_HMAC = 4,
|
||||
/** Certificate Status Request extension */
|
||||
SSL_EXT_STATUS_REQUEST = 5,
|
||||
/** TLS User Mapping extension */
|
||||
SSL_EXT_USER_MAPPING = 6,
|
||||
/** Client Authorization extension */
|
||||
SSL_EXT_CLIENT_AUTHZ = 7,
|
||||
/** Server Authorization extension */
|
||||
SSL_EXT_SERVER_AUTHZ = 8,
|
||||
/** Certificate Type extension */
|
||||
SSL_EXT_CERT_TYPE = 9,
|
||||
/** Supported Groups extension (renamed from "elliptic curves") */
|
||||
SSL_EXT_SUPPORTED_GROUPS = 10,
|
||||
/** Elliptic Curves Point Format extension */
|
||||
SSL_EXT_EC_POINT_FORMATS = 11,
|
||||
/** Secure Remote Password extension */
|
||||
SSL_EXT_SRP = 12,
|
||||
/** Signature Algorithms extension */
|
||||
SSL_EXT_SIGNATURE_ALGORITHMS = 13,
|
||||
/** Use Secure Real-time Transport Protocol extension */
|
||||
SSL_EXT_USE_SRTP = 14,
|
||||
/** TLS Heartbit extension */
|
||||
SSL_EXT_HEARTBEAT = 15,
|
||||
/** Application Layer Protocol Negotiation (ALPN) extension */
|
||||
SSL_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION = 16,
|
||||
/** Status Request extension */
|
||||
SSL_EXT_STATUS_REQUEST_V2 = 17,
|
||||
/** Signed Certificate Timestamp extension */
|
||||
SSL_EXT_SIGNED_CERTIFICATE_TIMESTAMP = 18,
|
||||
/** Client Certificate Type extension */
|
||||
SSL_EXT_CLIENT_CERTIFICATE_TYPE = 19,
|
||||
/** Server Certificate Type extension */
|
||||
SSL_EXT_SERVER_CERTIFICATE_TYPE = 20,
|
||||
/** ClientHello Padding extension */
|
||||
SSL_EXT_PADDING = 21,
|
||||
/** Encrypt-then-MAC extension */
|
||||
SSL_EXT_ENCRYPT_THEN_MAC = 22,
|
||||
/** Extended Master Secret extension */
|
||||
SSL_EXT_EXTENDED_MASTER_SECRET = 23,
|
||||
/** Token Binding extension */
|
||||
SSL_EXT_TOKEN_BINDING = 24,
|
||||
/** SessionTicket TLS extension */
|
||||
SSL_EXT_SESSIONTICKET_TLS = 35,
|
||||
/** Pre-shared key (PSK) extension (TLS 1.3) */
|
||||
SSL_EXT_PRE_SHARED_KEY = 41,
|
||||
/** Early data extension (TLS 1.3) */
|
||||
SSL_EXT_EARLY_DATA = 42,
|
||||
/** Supported versions extension (TLS 1.3) */
|
||||
SSL_EXT_SUPPORTED_VERSIONS = 43,
|
||||
/** Cookie extension (TLS 1.3) */
|
||||
SSL_EXT_COOKIE = 44,
|
||||
/** Pre-Shared Key Exchange Modes extension (TLS 1.3) */
|
||||
SSL_EXT_PSK_KEY_EXCHANGE_MODES = 45,
|
||||
/** Certificate authorities extension (TLS 1.3) */
|
||||
SSL_EXT_CERTIFICATE_AUTHORITIES = 47,
|
||||
/** Old filters extension (TLS 1.3) */
|
||||
SSL_EXT_OLD_FILTERS = 48,
|
||||
/** Post handshake auth extension (TLS 1.3) */
|
||||
SSL_EXT_POST_HANDSHAKE_AUTH = 49,
|
||||
/** Signature algorithm cert extension (TLS 1.3) */
|
||||
SSL_EXT_SIGNATURE_ALGORITHM_CERT = 50,
|
||||
/** Key share extension (TLS 1.3) */
|
||||
SSL_EXT_KEY_SHARE = 51,
|
||||
/** Renegotiation Indication extension */
|
||||
SSL_EXT_RENEGOTIATION_INFO = 65281,
|
||||
/** Unknown extension */
|
||||
SSL_EXT_Unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* SSL/TLS client certificate types
|
||||
*/
|
||||
enum SSLClientCertificateType
|
||||
{
|
||||
/** RSA_SIGN */
|
||||
SSL_CCT_RSA_SIGN = 1,
|
||||
/** DSS_SIGN */
|
||||
SSL_CCT_DSS_SIGN = 2,
|
||||
/** RSA_FIXED_DH */
|
||||
SSL_CCT_RSA_FIXED_DH = 3,
|
||||
/** DSS_FIXED_DH */
|
||||
SSL_CCT_DSS_FIXED_DH = 4,
|
||||
/** RSA_EPHEMERAL_DH_RESERVED */
|
||||
SSL_CCT_RSA_EPHEMERAL_DH_RESERVED = 5,
|
||||
/** DSS_EPHEMERAL_DH_RESERVED */
|
||||
SSL_CCT_DSS_EPHEMERAL_DH_RESERVED = 6,
|
||||
/** FORTEZZA_DMS_RESERVED */
|
||||
SSL_CCT_FORTEZZA_DMS_RESERVED = 20,
|
||||
/** ECDSA_SIGN */
|
||||
SSL_CCT_ECDSA_SIGN = 64,
|
||||
/** FIXED_ECDH */
|
||||
SSL_CCT_RSA_FIXED_ECDH = 65,
|
||||
/** ECDSA_FIXED_ECDH */
|
||||
SSL_CCT_ECDSA_FIXED_ECDH = 66,
|
||||
/** Unknown client certificate type */
|
||||
SSL_CCT_UNKNOWN
|
||||
};
|
||||
|
||||
} //namespace pcpp
|
||||
|
||||
#endif // PACKETPP_SSL_LAYER_COMMON
|
||||
1170
pcappp/include/pcapplusplus/SSLHandshake.h
Normal file
1170
pcappp/include/pcapplusplus/SSLHandshake.h
Normal file
File diff suppressed because it is too large
Load Diff
558
pcappp/include/pcapplusplus/SSLLayer.h
Normal file
558
pcappp/include/pcapplusplus/SSLLayer.h
Normal file
@@ -0,0 +1,558 @@
|
||||
#ifndef PACKETPP_SSL_LAYER
|
||||
#define PACKETPP_SSL_LAYER
|
||||
|
||||
#include "PointerVector.h"
|
||||
#include "Layer.h"
|
||||
#include "SSLCommon.h"
|
||||
#include "SSLHandshake.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file as well as SSLCommon.h and SSLHandshake.h provide structures that represent SSL/TLS protocol.
|
||||
* Main features:
|
||||
* - All common SSL/TLS version are supported from SSL 3.0 to TLS 1.3
|
||||
* - All SSL/TLS message types are supported (at least the message types that are not encrypted)
|
||||
* - More than 300 cipher-suites are supported
|
||||
* - Only parsing capabilities exist, editing and creation of messages are not supported
|
||||
* - X509 certificate parsing is not supported
|
||||
*
|
||||
* <BR><BR>
|
||||
*
|
||||
* __SSL Records:__ <BR>
|
||||
*
|
||||
* The SSL/TLS protocol has 4 types of records:
|
||||
* - Handshake record type
|
||||
* - Change cipher spec record type
|
||||
* - Alert record type
|
||||
* - Application data record type
|
||||
*
|
||||
* Each record type corresponds to a layer class, and these classes inherit from one base class which is pcpp::SSLLayer.
|
||||
* The pcpp::SSLLayer is an abstract class which cannot be instantiated. Only its 4 derived classes can be instantiated.
|
||||
* This means you'll never see a layer of type pcpp::SSLLayer, you'll only see the type of the derived classes.
|
||||
* A basic class diagram looks like this:
|
||||
@verbatim
|
||||
+----------------------------+
|
||||
+---| SSLHandshakeLayer | ===> Handshake record type
|
||||
| +----------------------------+
|
||||
|
|
||||
| +----------------------------+
|
||||
+---| SSLChangeCipherSpecLayer | ===> Change cipher spec record type
|
||||
| +----------------------------+
|
||||
|
|
||||
+------------+ | +----------------------------+
|
||||
| SSLLayer |-------------+---| SSLAlertLayer | ===> Alert record type
|
||||
| (abstract) | | +----------------------------+
|
||||
+------------+ |
|
||||
| +----------------------------+
|
||||
+---| SSLApplicationDataLayer | ===> Application data record type
|
||||
+----------------------------+
|
||||
|
||||
@endverbatim
|
||||
*
|
||||
* A single packet may include several SSL/TLS records, meaning several layer instances of these types, for example:
|
||||
*
|
||||
@verbatim
|
||||
|
||||
+--------------------------+
|
||||
| EthLayer |
|
||||
+--------------------------+
|
||||
| IPv4Layer |
|
||||
+--------------------------+
|
||||
| TcpLayer |
|
||||
+--------------------------+
|
||||
| SSLHandshakeLayer | \
|
||||
+--------------------------+ \
|
||||
| SSLChangeCipherSpecLayer | -------- 3 SSL/TLS records in the same packet!
|
||||
+--------------------------+ /
|
||||
| SSLHandshakeLayer | /
|
||||
+--------------------------+
|
||||
|
||||
@endverbatim
|
||||
*
|
||||
* <BR><BR>
|
||||
*
|
||||
* __SSL/TLS Handshake records:__ <BR>
|
||||
*
|
||||
* The SSL/TLS handshake records are the most complex ones. These type of records encapsulate all messages between
|
||||
* client and server during SSL/TLS connection establishment. To accomplish that a SSL/TLS handshake record holds
|
||||
* zero or more handshake messages (usually it holds 1 message). These messages form the handshake negotiation between
|
||||
* the client and the server. There are several types of handshake messages. Some of the are sent from client to server
|
||||
* and some from server to client. PcapPlusPlus supports 11 of these types (definitely the most common ones). For each
|
||||
* message there is a designated class which parses the message and exposes its attributes in an easy-to-use manner.
|
||||
* Here are the list of supported messages:
|
||||
* - Client-hello
|
||||
* - Server-hello
|
||||
* - Certificate
|
||||
* - Hello-request
|
||||
* - Server-key-exchange
|
||||
* - Client-key-exchange
|
||||
* - Certificate-request
|
||||
* - Server-hello-done
|
||||
* - Certificate-verify
|
||||
* - Finished
|
||||
* - New-session-ticket
|
||||
*
|
||||
* All handshake messages classes inherit from a base abstract class: pcpp::SSLHandshakeMessage which cannot be instantiated.
|
||||
* Also, all of them reside in SSLHandshake.h. Following is a simple diagram of these classes:
|
||||
*
|
||||
@verbatim
|
||||
|
||||
SSLHandshakeMessage
|
||||
|
|
||||
+-------------------------------+ |--- SSLClientHelloMessage ==> Client-hello message
|
||||
| SSLHandshakeLayer | |
|
||||
+-------------------------------+ |--- SSLServerHelloMessage ==> Server-hello message
|
||||
| -List of SSLHandshakeMessage | |
|
||||
| Message1 | |---SSLCertificateMessage ==> Certificate message
|
||||
| Message2 | |
|
||||
| ... | |---SSLHelloRequestMessage ==> Hello-request message
|
||||
| | |
|
||||
+-------------------------------+ |---SSLServerKeyExchangeMessage ==> Server-key-exchange message
|
||||
|
|
||||
|---SSLClientKeyExchangeMessage ==> Client-key-exchange message
|
||||
|
|
||||
|---SSLCertificateRequestMessage ==> Certificate-request message
|
||||
|
|
||||
|---SSLServerHelloDoneMessage ==> Server-hello-done message
|
||||
|
|
||||
|---SSLCertificateVerifyMessage ==> Certificate-verify message
|
||||
|
|
||||
|---SSLFinishedMessage ==> Finished message
|
||||
|
|
||||
|---SSLNewSessionTicketMessage ==> New-session-ticket message
|
||||
|
||||
@endverbatim
|
||||
*
|
||||
* In addition, for all handshake messages which aren't supported in PcapPlusPlus or for encrypted handshake messages
|
||||
* There is another class: pcpp::SSLUnknownMessage
|
||||
*
|
||||
* <BR><BR>
|
||||
*
|
||||
* __Cipher suites:__ <BR>
|
||||
*
|
||||
* Cipher suites are named combinations of authentication, encryption, message authentication code (MAC) and key exchange
|
||||
* algorithms used to negotiate the security settings for a network connection using SSL/TLS.
|
||||
* There are many known cipher-suites. PcapPlusPlus support above 300 of them, according to this list:
|
||||
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
||||
* There is a designated class in PcapPlusPlus called pcpp::SSLCipherSuite which represents the cipher-suites and provides
|
||||
* access to their attributes. Then there is a static instance of this class for each one of the supported cipher-suites.
|
||||
* This means there are 300+ static instances of pcpp::SSLCipherSuite representing the different cipher suites. The user can
|
||||
* access them through static methods in pcpp::SSLCipherSuite or from client-hello and server-hello messages where they appear
|
||||
*
|
||||
* <BR><BR>
|
||||
*
|
||||
* __SSL/TLS extensions:__ <BR>
|
||||
*
|
||||
* SSL/TLS handshake messages, specifically client-hello and server-hello usually include extensions. There are various
|
||||
* types of extensions - some are more broadly used, some are less. In PcapPlusPlus there is a base class for all
|
||||
* extensions: pcpp::SSLExtension. This class is instantiable and represents a generic extension, which means extension data
|
||||
* isn't parsed and given to the user as raw data. Currently there are only two extension that are fully parsed which are
|
||||
* server-name-indication (pcpp::SSLServerNameIndicationExtension) and SupportedVersions (pcpp::SSLSupportedVersionsExtension).
|
||||
* Both inherit from pcpp::SSLExtension and add additional parsing relevant for the specific extension.
|
||||
* All other extensions aren't parsed and are represented by instance of pcpp::SSLExtension.
|
||||
* Access to extensions is done through the handshake messages classes, specifically pcpp::SSLClientHelloMessage and pcpp::SSLServerHelloMessage
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class SSLLayer
|
||||
* The base class for the 4 record type classes. Each record type is represented as a layer. See SSLLayer.h for
|
||||
* detailed explanation of the TLS/SSL protocol support in PcapPlusPlus.
|
||||
* This class provides the common functionality used by all record types and also contains static methods for identifying
|
||||
* an creating SSL/TLS record type layers
|
||||
*/
|
||||
class SSLLayer : public Layer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as SSL/TLS
|
||||
* @param[in] port The port number to be checked
|
||||
*/
|
||||
static inline bool isSSLPort(uint16_t port);
|
||||
|
||||
/**
|
||||
* A static methods that gets raw data of a layer and checks whether this data is a SSL/TLS record or not. This check is
|
||||
* done using the source/dest port and matching of a legal record type in the raw data. The list of ports identified
|
||||
* as SSL/TLS is hard-coded and includes the following ports:
|
||||
* - Port 443 [HTTPS]
|
||||
* - Port 261 [NSIIOPS]
|
||||
* - Port 448 [DDM-SSL]
|
||||
* - Port 563 [NNTPS]
|
||||
* - Port 614 [SSHELL]
|
||||
* - Port 465 [SMTPS]
|
||||
* - Port 636 [LDAPS]
|
||||
* - Port 989 [FTPS - data]
|
||||
* - Port 990 [FTPS - control]
|
||||
* - Port 992 [Telnet over TLS/SSL]
|
||||
* - Port 993 [IMAPS]
|
||||
* - Port 994 [IRCS]
|
||||
* - Port 995 [POP3S]
|
||||
* @param[in] srcPort The source port of the packet that contains the raw data. Source port (or dest port) are a
|
||||
* criteria to identify SSL/TLS packets
|
||||
* @param[in] dstPort The dest port of the packet that contains the raw data. Dest port (or source port) are a
|
||||
* criteria to identify SSL/TLS packets
|
||||
* @param[in] data The data to check
|
||||
* @param[in] dataLen Length (in bytes) of the data
|
||||
* @param[in] ignorePorts SSL/TLS ports are only relevant for parsing the first SSL/TLS message, but are not relevant
|
||||
* for parsing subsequent messages. This parameter can be set to "true" to skip SSL/TLS ports check. This is an
|
||||
* optional parameter and its default is "false"
|
||||
*/
|
||||
static bool IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, bool ignorePorts = false);
|
||||
|
||||
/**
|
||||
* A static method that creates SSL/TLS layers by raw data. This method parses the raw data, finds if and which
|
||||
* SSL/TLS record it is and creates the corresponding record layer. It's the responsibility of the user to free
|
||||
* the created object when done using it
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
* @return A pointer to the newly created record layer. If no SSL/TLS record could be identified from the raw data
|
||||
* NULL is returned
|
||||
*/
|
||||
static SSLLayer* createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* Get a pointer to the record header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref ssl_tls_record_layer
|
||||
*/
|
||||
ssl_tls_record_layer* getRecordLayer() const { return (ssl_tls_record_layer*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The SSL/TLS version used in this record (parsed from the record)
|
||||
*/
|
||||
SSLVersion getRecordVersion() const;
|
||||
|
||||
/**
|
||||
* @return The SSL/TLS record type as parsed from the record
|
||||
*/
|
||||
SSLRecordType getRecordType() const;
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* @return The record size as extracted from the record data (in ssl_tls_record_layer#length)
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
/**
|
||||
* Several SSL/TLS records can reside in a single packets. So this method checks the remaining data and if it's
|
||||
* identified as SSL/TLS it creates another SSL/TLS record layer as the next layer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelPresentationLayer; }
|
||||
|
||||
protected:
|
||||
SSLLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = SSL; }
|
||||
|
||||
}; // class SSLLayer
|
||||
|
||||
|
||||
/**
|
||||
* @class SSLHandshakeLayer
|
||||
* Represents SSL/TLS handshake layer. This layer may contain one or more handshake messages (all of them inherit from
|
||||
* the base class SSLHandshakeMessage) which are the SSL/TLS handshake message sent between a client and a server until
|
||||
* they establish a secure connection (e.g client-hello, server-hello, certificate, client-key-exchange,
|
||||
* server-key-exchange, etc.). Usually this layer will contain just one message (as the first example below
|
||||
* demonstrates). But there are cases a layer may contain more than 1 message. To better explain this layer structure
|
||||
* we'll use 2 examples. The first will be client-hello message. The layer structure will look like this:
|
||||
@verbatim
|
||||
|
||||
|------------------- SSLHandshakeLayer ----------------------|
|
||||
+----------------------+-------------------------------------+
|
||||
| ssl_tls_record_layer | SSLClientHelloMessage |
|
||||
| struct | |
|
||||
+----------------------+-------------------------------------+
|
||||
/ | \ | \ \ \
|
||||
/ version \ | handshake \ \ \
|
||||
/ TLS1_0 \ type \ \ rest of
|
||||
type \ | SSL_CLIENT_HELLO \ \ message fields...
|
||||
SSL_HANDSHAKE length handshake \
|
||||
(22) xxx | version message
|
||||
TLS1_2 length
|
||||
| yyy
|
||||
@endverbatim
|
||||
|
||||
* Second example is a multiple-message handshake layer comprises of server-hello, certificate and server-key-exchange
|
||||
* messages:
|
||||
|
||||
@verbatim
|
||||
|
||||
|---------------------------------------------- SSLHandshakeLayer -----------------------------------------------------|
|
||||
+----------------------+-------------------------------------+---------------------------+-----------------------------+
|
||||
| ssl_tls_record_layer | SSLServerHelloMessage | SSLCertificateMessage | SSLServerKeyExchangeMessage |
|
||||
| struct | | | |
|
||||
+----------------------+-------------------------------------+---------------------------+-----------------------------+
|
||||
/ | \ | \ \ | \ | \
|
||||
/ version \ | handshake \ rest of | | rest | | rest
|
||||
/ TLS1_0 \ type \ message handshake of fields... handshake of fields...
|
||||
type \ | SSL_SERVER_HELLO \ fields...| type | type
|
||||
SSL_HANDSHAKE length handshake SSL_CERTIFICATE SSL_SERVER_KEY_EXCHANGE
|
||||
(22) xxx | version,length | |
|
||||
|
||||
| | |
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
class SSLHandshakeLayer: public SSLLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* C'tor for this class that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SSLHandshakeLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* @return The number of messages in this layer instance
|
||||
*/
|
||||
size_t getHandshakeMessagesCount() const { return m_MessageList.size(); }
|
||||
|
||||
/**
|
||||
* Get a pointer to an handshake message by index. The message are numbered according to their order of appearance
|
||||
* in the layer. If index is out of bounds (less than 0 or larger than total amount of message) NULL will be
|
||||
* returned
|
||||
* @param[in] index The index of the message to return
|
||||
* @return The pointer to the message object or NULL if index is out of bounds
|
||||
*/
|
||||
SSLHandshakeMessage* getHandshakeMessageAt(int index) const;
|
||||
|
||||
/**
|
||||
* A templated method to get a message of a certain type. If no message of such type is found, NULL is returned
|
||||
* @return A pointer to the message of the requested type, NULL if not found
|
||||
*/
|
||||
template<class THandshakeMessage>
|
||||
THandshakeMessage* getHandshakeMessageOfType() const;
|
||||
|
||||
/**
|
||||
* A templated method to get the first message of a certain type, starting to search from a certain message.
|
||||
* For example: if the layer looks like: HelloRequest(1) -> HelloRequest(2)
|
||||
* and the user put HelloRequest(1) as a parameter and wishes to search for an HelloRequest message, the
|
||||
* HelloRequest(2) will be returned.<BR>
|
||||
* If no layer of such type is found, NULL is returned
|
||||
* @param[in] after A pointer to the message to start search from
|
||||
* @return A pointer to the message of the requested type, NULL if not found
|
||||
*/
|
||||
template<class THandshakeMessage>
|
||||
THandshakeMessage* getNextHandshakeMessageOfType(SSLHandshakeMessage* after) const;
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* There are no calculated fields for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
private:
|
||||
PointerVector<SSLHandshakeMessage> m_MessageList;
|
||||
}; // class SSLHandshakeLayer
|
||||
|
||||
|
||||
/**
|
||||
* @class SSLChangeCipherSpecLayer
|
||||
* Represents SSL/TLS change-cipher-spec layer. This layer has no additional fields besides common fields described in
|
||||
* SSLLayer
|
||||
*/
|
||||
class SSLChangeCipherSpecLayer : public SSLLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* C'tor for this class that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SSLChangeCipherSpecLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: SSLLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
~SSLChangeCipherSpecLayer() {}
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* There are no calculated fields for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
}; // class SSLChangeCipherSpecLayer
|
||||
|
||||
|
||||
/**
|
||||
* @class SSLAlertLayer
|
||||
* Represents SSL/TLS alert layer. Inherits from SSLLayer and adds parsing functionality such as retrieving the alert
|
||||
* level and description
|
||||
*/
|
||||
class SSLAlertLayer : public SSLLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* C'tor for this class that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SSLAlertLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: SSLLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
~SSLAlertLayer() {}
|
||||
|
||||
/**
|
||||
* @return SSL/TLS alert level. Will return ::SSL_ALERT_LEVEL_ENCRYPTED if alert is encrypted
|
||||
*/
|
||||
SSLAlertLevel getAlertLevel() const;
|
||||
|
||||
/**
|
||||
* @return SSL/TLS alert description. Will return ::SSL_ALERT_ENCRYPTED if alert is encrypted
|
||||
*/
|
||||
SSLAlertDescription getAlertDescription();
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* There are no calculated fields for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
}; // class SSLAlertLayer
|
||||
|
||||
|
||||
/**
|
||||
* @class SSLApplicationDataLayer
|
||||
* Represents SSL/TLS application data layer. This message contains the encrypted data transferred from client to
|
||||
* server and vice-versa after the SSL/TLS handshake was completed successfully
|
||||
*/
|
||||
class SSLApplicationDataLayer : public SSLLayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* C'tor for this class that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SSLApplicationDataLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
|
||||
: SSLLayer(data, dataLen, prevLayer, packet) {}
|
||||
|
||||
~SSLApplicationDataLayer() {}
|
||||
|
||||
/**
|
||||
* @return A pointer to the encrypted data. This data can be decrypted only if you have the symmetric key
|
||||
* that was agreed between the client and the server during SSL/TLS handshake process
|
||||
*/
|
||||
uint8_t* getEncryptedData() const;
|
||||
|
||||
/**
|
||||
* @return The length in bytes of the encrypted data returned in getEncryptedData()
|
||||
*/
|
||||
size_t getEncryptedDataLen() const;
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* There are no calculated fields for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
}; // class SSLApplicationDataLayer
|
||||
|
||||
|
||||
template<class THandshakeMessage>
|
||||
THandshakeMessage* SSLHandshakeLayer::getHandshakeMessageOfType() const
|
||||
{
|
||||
size_t vecSize = m_MessageList.size();
|
||||
for (size_t i = 0; i < vecSize; i++)
|
||||
{
|
||||
SSLHandshakeMessage* curElem = const_cast<SSLHandshakeMessage*>(m_MessageList.at(i));
|
||||
if (dynamic_cast<THandshakeMessage*>(curElem) != NULL)
|
||||
return (THandshakeMessage*)curElem;
|
||||
}
|
||||
|
||||
// element not found
|
||||
return NULL;
|
||||
} // getHandshakeMessageOfType
|
||||
|
||||
|
||||
template<class THandshakeMessage>
|
||||
THandshakeMessage* SSLHandshakeLayer::getNextHandshakeMessageOfType(SSLHandshakeMessage* after) const
|
||||
{
|
||||
size_t vecSize = m_MessageList.size();
|
||||
size_t afterIndex;
|
||||
|
||||
// find the index of "after"
|
||||
for (afterIndex = 0; afterIndex < vecSize; afterIndex++)
|
||||
{
|
||||
SSLHandshakeMessage* curElem = const_cast<SSLHandshakeMessage*>(m_MessageList.at(afterIndex));
|
||||
if (curElem == after)
|
||||
break;
|
||||
}
|
||||
|
||||
// "after" not found
|
||||
if (afterIndex == vecSize)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = afterIndex+1; i < vecSize; i++)
|
||||
{
|
||||
SSLHandshakeMessage* curElem = const_cast<SSLHandshakeMessage*>(m_MessageList.at(i));
|
||||
if (dynamic_cast<THandshakeMessage*>(curElem) != NULL)
|
||||
return (THandshakeMessage*)curElem;
|
||||
}
|
||||
|
||||
// element not found
|
||||
return NULL;
|
||||
} // getNextHandshakeMessageOfType
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool SSLLayer::isSSLPort(uint16_t port)
|
||||
{
|
||||
if (port == 443) // HTTPS, this is likely case
|
||||
return true;
|
||||
|
||||
switch (port)
|
||||
{
|
||||
case 261: // NSIIOPS
|
||||
case 448: // DDM-SSL
|
||||
case 465: // SMTPS
|
||||
case 563: // NNTPS
|
||||
case 614: // SSHELL
|
||||
case 636: // LDAPS
|
||||
case 989: // FTPS - data
|
||||
case 990: // FTPS - control
|
||||
case 992: // Telnet over TLS/SSL
|
||||
case 993: // IMAPS
|
||||
case 994: // IRCS
|
||||
case 995: // POP3S
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} // isSSLPort
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_SSL_LAYER */
|
||||
169
pcappp/include/pcapplusplus/SdpLayer.h
Normal file
169
pcappp/include/pcapplusplus/SdpLayer.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef PACKETPP_SDP_LAYER
|
||||
#define PACKETPP_SDP_LAYER
|
||||
|
||||
#include "IpAddress.h"
|
||||
#include "TextBasedProtocol.h"
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/** Protocol version (v) */
|
||||
#define PCPP_SDP_PROTOCOL_VERSION_FIELD "v"
|
||||
/** Originator and session identifier (o) */
|
||||
#define PCPP_SDP_ORIGINATOR_FIELD "o"
|
||||
/** Session name (s) */
|
||||
#define PCPP_SDP_SESSION_NAME_FIELD "s"
|
||||
/** Session title, media title or short information (i) */
|
||||
#define PCPP_SDP_INFO_FIELD "i"
|
||||
/** URI of description (u) */
|
||||
#define PCPP_SDP_URI_FIELD "u"
|
||||
/** Email address with optional name of contacts (e) */
|
||||
#define PCPP_SDP_EMAIL_FIELD "e"
|
||||
/** Phone number with optional name of contacts (p) */
|
||||
#define PCPP_SDP_PHONE_FIELD "p"
|
||||
/** Connection information (c) */
|
||||
#define PCPP_SDP_CONNECTION_INFO_FIELD "c"
|
||||
/** Bandwidth information (b) */
|
||||
#define PCPP_SDP_BANDWIDTH_FIELD "b"
|
||||
/** Time the session is active (t) */
|
||||
#define PCPP_SDP_TIME_FIELD "t"
|
||||
/** Repeat times (r) */
|
||||
#define PCPP_SDP_REPEAT_TIMES_FIELD "r"
|
||||
/** Time zone adjustments (z) */
|
||||
#define PCPP_SDP_TIME_ZONE_FIELD "z"
|
||||
/** Encryption key (k) */
|
||||
#define PCPP_SDP_ENCRYPTION_KEY_FIELD "k"
|
||||
/** Media attribute (a) */
|
||||
#define PCPP_SDP_MEDIA_ATTRIBUTE_FIELD "a"
|
||||
/** Media name and transport address (m) */
|
||||
#define PCPP_SDP_MEDIA_NAME_FIELD "m"
|
||||
|
||||
/**
|
||||
* @class SdpLayer
|
||||
* Represents a SDP (Session Description Protocol) message. SDP is a text-based protocol described by a series of fields, one per line (lines are separated by CRLF).
|
||||
* The form of each field is as follows:<BR>
|
||||
* @code
|
||||
* [character]=[value]
|
||||
* @endcode
|
||||
* Each character represents a certain type of field. All field type are represented as macros in SdpLayer.h file
|
||||
* (for example: PCPP_SDP_ORIGINATOR_FIELD is a macro for the originator field (o=) ).<BR>
|
||||
* For more details about SDP structure please refer to its Wikipedia page: https://en.wikipedia.org/wiki/Session_Description_Protocol
|
||||
*/
|
||||
class SdpLayer : public TextBasedProtocolMessage
|
||||
{
|
||||
public:
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* An empty c'tor which initialize an empty message with no fields
|
||||
*/
|
||||
SdpLayer();
|
||||
|
||||
/**
|
||||
* A c'tor which initializes a message with the minimum required fields.<BR>
|
||||
* After this c'tor the message will look like this:
|
||||
*
|
||||
* @code
|
||||
* v=0
|
||||
* o=[username] [sessionID] [sessionVersion] IN IP4 [ipAddress]
|
||||
* s=[sessionName]
|
||||
* c=IN IP4 [ipAddress]
|
||||
* t=[startTime] [endTime]
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] username User's login on the originating host
|
||||
* @param[in] sessionID A globally unique identifier for the session
|
||||
* @param[in] sessionVersion A version number for this session description
|
||||
* @param[in] ipAddress The address of the machine from which the session is created
|
||||
* @param[in] sessionName A textual session name
|
||||
* @param[in] startTime The start time of the session
|
||||
* @param[in] stopTime The stop time of the session
|
||||
*/
|
||||
SdpLayer(std::string username, long sessionID, long sessionVersion, IPv4Address ipAddress, std::string sessionName, long startTime, long stopTime);
|
||||
|
||||
~SdpLayer() {}
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer. Inherits the base copy constructor and doesn't add
|
||||
* anything else
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
SdpLayer(const SdpLayer& other) : TextBasedProtocolMessage(other) {}
|
||||
|
||||
/**
|
||||
* An assignment operator overload for this layer. Inherits the base assignment operator
|
||||
* and doesn't add anything else
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
SdpLayer& operator=(const SdpLayer& other) { TextBasedProtocolMessage::operator=(other); return *this; }
|
||||
|
||||
/**
|
||||
* The 'originator' field (o=) contains the IP address of the the machine from which the session is created.
|
||||
* This IP address can be used to track the RTP data relevant for the call. This method extracts this IP address from the 'originator' field and returns it.
|
||||
* A value of IPv4Address#Zero will be returned in the following cases: (1) if 'originator' field doesn't exist; (2) if it doesn't contain the IP address;
|
||||
* (3) if it contains a non-IPv4 address
|
||||
* @return The IP address of the the machine from which the session is created
|
||||
*/
|
||||
IPv4Address getOwnerIPv4Address() const;
|
||||
|
||||
/**
|
||||
* The 'media-description' field (m=) contains the transport port to which the media stream is sent. This port can be used to track the RTP data relevant for the call.
|
||||
* This method extracts this port from the 'media-description' field and returns it. Since a SDP message can contain several 'media-description' fields, one for each media type
|
||||
* (e.g audio, image, etc.), the user is required to provide the media type. A value of 0 will be returned in the following cases: (1) if 'media-description' field doesn't
|
||||
* exist; (2) if provided media type was not found; (3) if 'media-description' field didn't contain a port
|
||||
* @param[in] mediaType The media type to search in
|
||||
* @return The transport port to which the media stream is sent
|
||||
*/
|
||||
uint16_t getMediaPort(std::string mediaType) const;
|
||||
|
||||
/**
|
||||
* Adds a 'media-description' field (m=) with all necessary data and attribute fields (a=) with data relevant for this media.<BR>
|
||||
* After this method is run the following block of fields will be added at the end of the message:
|
||||
*
|
||||
* @code
|
||||
* m=[mediaType] [mediaPort] [mediaProtocol] [mediaFormat]
|
||||
* a=[1st media attribute]
|
||||
* a=[2nd media attribute]
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] mediaType The media type, usually "audio", "video", "text" or "image"
|
||||
* @param[in] mediaPort The transport port to which the media stream is sent
|
||||
* @param[in] mediaProtocol The transport protocol, usually "udp", "RTP/AVP" or "RTP/SAVP"
|
||||
* @param[in] mediaFormat A space-separated list of media format description. For example: "8 96"
|
||||
* @param[in] mediaAttributes A vector of media attributes. Each string in this vector will be
|
||||
* translated into a 'media-attribute' field (a=)
|
||||
* @return True if all fields were added properly or false if at least one field was failed to be added
|
||||
*/
|
||||
bool addMediaDescription(std::string mediaType, uint16_t mediaPort, std::string mediaProtocol, std::string mediaFormat, std::vector<std::string> mediaAttributes);
|
||||
|
||||
// overridden methods
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; }
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
// implementation of abstract methods
|
||||
char getHeaderFieldNameValueSeparator() const { return '='; }
|
||||
bool spacesAllowedBetweenHeaderFieldNameAndValue() const { return false; }
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PACKETPP_SDP_LAYER
|
||||
677
pcappp/include/pcapplusplus/SipLayer.h
Normal file
677
pcappp/include/pcapplusplus/SipLayer.h
Normal file
@@ -0,0 +1,677 @@
|
||||
#ifndef PACKETPP_SIP_LAYER
|
||||
#define PACKETPP_SIP_LAYER
|
||||
|
||||
#include "TextBasedProtocol.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
// some popular SIP header fields
|
||||
|
||||
/** From field */
|
||||
#define PCPP_SIP_FROM_FIELD "From"
|
||||
/** To field */
|
||||
#define PCPP_SIP_TO_FIELD "To"
|
||||
/** Via field */
|
||||
#define PCPP_SIP_VIA_FIELD "Via"
|
||||
/** Call-ID field */
|
||||
#define PCPP_SIP_CALL_ID_FIELD "Call-ID"
|
||||
/** Content-Type field */
|
||||
#define PCPP_SIP_CONTENT_TYPE_FIELD "Content-Type"
|
||||
/** Content-Length field */
|
||||
#define PCPP_SIP_CONTENT_LENGTH_FIELD "Content-Length"
|
||||
/** Content-Disposition field */
|
||||
#define PCPP_SIP_CONTENT_DISPOSITION_FIELD "Content-Disposition"
|
||||
/** Content-Encoding field */
|
||||
#define PCPP_SIP_CONTENT_ENCODING_FIELD "Content-Encoding"
|
||||
/** Content-Language field */
|
||||
#define PCPP_SIP_CONTENT_LANGUAGE_FIELD "Content-Language"
|
||||
/** CSeq field */
|
||||
#define PCPP_SIP_CSEQ_FIELD "CSeq"
|
||||
/** Contact field */
|
||||
#define PCPP_SIP_CONTACT_FIELD "Contact"
|
||||
/** Max-Forwards field */
|
||||
#define PCPP_SIP_MAX_FORWARDS_FIELD "Max-Forwards"
|
||||
/** User-Agent field */
|
||||
#define PCPP_SIP_USER_AGENT_FIELD "User-Agent"
|
||||
/** Accept field */
|
||||
#define PCPP_SIP_ACCEPT_FIELD "Accept"
|
||||
/** Accept-Encoding field */
|
||||
#define PCPP_SIP_ACCEPT_ENCODING_FIELD "Accept-Encoding"
|
||||
/** Accept-Language field */
|
||||
#define PCPP_SIP_ACCEPT_LANGUAGE_FIELD "Accept-Language"
|
||||
/** Allow field */
|
||||
#define PCPP_SIP_ALLOW_FIELD "Allow"
|
||||
/** Authorization field */
|
||||
#define PCPP_SIP_AUTHORIZATION_FIELD "Authorization"
|
||||
/** Date field */
|
||||
#define PCPP_SIP_DATE_FIELD "Date"
|
||||
/** MIME-Version field */
|
||||
#define PCPP_SIP_MIME_VERSION_FIELD "MIME-Version"
|
||||
/** Reason field */
|
||||
#define PCPP_SIP_REASON_FIELD "Reason"
|
||||
/** Supported field */
|
||||
#define PCPP_SIP_SUPPORTED_FIELD "Supported"
|
||||
/** Server field */
|
||||
#define PCPP_SIP_SERVER_FIELD "Server"
|
||||
/** WWW-Authenticate fild */
|
||||
#define PCPP_SIP_WWW_AUTHENTICATE_FIELD "WWW-Authenticate"
|
||||
/** Retry-After field */
|
||||
#define PCPP_SIP_RETRY_AFTER_FIELD "Retry-After"
|
||||
/** Record-Route field */
|
||||
#define PCPP_SIP_RECORD_ROUTE_FIELD "Record-Route"
|
||||
|
||||
|
||||
/**
|
||||
* @class SipLayer
|
||||
* Represents a general SIP message. It's an abstract class and cannot be instantiated. It's inherited by SipRequestLayer and SipResponseLayer
|
||||
*/
|
||||
class SipLayer : public TextBasedProtocolMessage
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* The length of the body of many SIP response messages is determined by a SIP header field called "Content-Length". This method
|
||||
* parses this field, extracts its value and return it. If this field doesn't exist 0 is returned
|
||||
* @return SIP response body length determined by "Content-Length" field
|
||||
*/
|
||||
int getContentLength() const;
|
||||
|
||||
/**
|
||||
* The length of the body of many SIP messages is determined by a header field called "Content-Length". This method sets
|
||||
* The content-length field value. The method supports several cases:
|
||||
* - If the "Content-Length" field exists - the method will only replace the existing value with the new value
|
||||
* - If the "Content-Length" field doesn't exist - the method will create this field and put the value in it. Here are also 2 cases:
|
||||
* - If prevFieldName is specified - the new "Content-Length" field will be created after it
|
||||
* - If prevFieldName isn't specified or doesn't exist - the new "Content-Length" field will be created as the last field before
|
||||
* end-of-header field
|
||||
*
|
||||
* @param[in] contentLength The content length value to set
|
||||
* @param[in] prevFieldName Optional parameter, if specified and "Content-Length" field doesn't exist, it will be created after this field
|
||||
* @return A pointer to the "Content-Length" field, or NULL if creation failed
|
||||
*/
|
||||
HeaderField* setContentLength(int contentLength, const std::string prevFieldName = "");
|
||||
|
||||
// Overridden methods
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; }
|
||||
|
||||
/**
|
||||
* Currently identifies only SDP if content-length field exists and set to a value greater than zero.
|
||||
* If content-length field doesn't exist or set to zero and still there is data after this layer, a PayloadLayer will be created
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* Set the content-length only if a content-length field already exists and if its current value is different than the total length of the next layer(s)
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as SIP
|
||||
* @param[in] port The port number to be checked
|
||||
*/
|
||||
static bool isSipPort(uint16_t port) { return port == 5060 || port == 5061; }
|
||||
|
||||
protected:
|
||||
SipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) {}
|
||||
SipLayer() : TextBasedProtocolMessage() {}
|
||||
SipLayer(const SipLayer& other) : TextBasedProtocolMessage(other) {}
|
||||
SipLayer& operator=(const SipLayer& other) { TextBasedProtocolMessage::operator=(other); return *this; }
|
||||
|
||||
// implementation of abstract methods
|
||||
char getHeaderFieldNameValueSeparator() const { return ':'; }
|
||||
bool spacesAllowedBetweenHeaderFieldNameAndValue() const { return true; }
|
||||
};
|
||||
|
||||
|
||||
class SipRequestFirstLine;
|
||||
|
||||
|
||||
/**
|
||||
* @class SipRequestLayer
|
||||
* Represents a SIP request header and inherits all basic functionality of SipLayer and TextBasedProtocolMessage.
|
||||
* The functionality that is added for this class is the SIP first line concept. A SIP request has the following first line:
|
||||
* <i>INVITE sip:bla@bla.com:12345 SIP/2.0</i>
|
||||
* Since it's not an "ordinary" header field, it requires a special treatment and gets a class of it's own: SipRequestFirstLine.
|
||||
* In most cases a SIP request will be contained in a single packet but for cases it is not, only the first packet will be identified as SIP
|
||||
* request layer. You can find out whether the header is complete by using SipLayer#isHeaderComplete()
|
||||
*/
|
||||
class SipRequestLayer : public SipLayer
|
||||
{
|
||||
friend class SipRequestFirstLine;
|
||||
|
||||
public:
|
||||
/**
|
||||
* SIP request methods
|
||||
*/
|
||||
enum SipMethod
|
||||
{
|
||||
/** INVITE */
|
||||
SipINVITE,
|
||||
/** ACK */
|
||||
SipACK,
|
||||
/** BYE */
|
||||
SipBYE,
|
||||
/** CANCEL */
|
||||
SipCANCEL,
|
||||
/** REFISTER */
|
||||
SipREGISTER,
|
||||
/** PRACK */
|
||||
SipPRACK,
|
||||
/** OPTIONS */
|
||||
SipOPTIONS,
|
||||
/** SUBSCRIBE */
|
||||
SipSUBSCRIBE,
|
||||
/** NOTIFY */
|
||||
SipNOTIFY,
|
||||
/** PUBLISH */
|
||||
SipPUBLISH,
|
||||
/** INFO */
|
||||
SipINFO,
|
||||
/** REFER */
|
||||
SipREFER,
|
||||
/** MESSAGE */
|
||||
SipMESSAGE,
|
||||
/** UPDATE */
|
||||
SipUPDATE,
|
||||
/** Unknown SIP method */
|
||||
SipMethodUnknown
|
||||
};
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SipRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new SIP request with only the first line filled. The request will be created without further fields.
|
||||
* The user can then add fields using addField() or insertField() methods
|
||||
* @param[in] method The SIP method to be used in this SIP request
|
||||
* @param[in] requestUri The URI of the request
|
||||
* @param[in] version SIP version to be used in this request. Default is "SIP/2.0"
|
||||
*/
|
||||
SipRequestLayer(SipMethod method, std::string requestUri, std::string version = "SIP/2.0");
|
||||
|
||||
~SipRequestLayer();
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer. Inherits base copy constructor SipLayer and adds the functionality
|
||||
* of copying the first line
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
SipRequestLayer(const SipRequestLayer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator overload for this layer. This method inherits base assignment operator SipLayer#operator=() and adds the functionality
|
||||
* of copying the first line
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
SipRequestLayer& operator=(const SipRequestLayer& other);
|
||||
|
||||
/**
|
||||
* @return A pointer to the first line instance for this message
|
||||
*/
|
||||
SipRequestFirstLine* getFirstLine() const { return m_FirstLine; }
|
||||
|
||||
// implement Layer's abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
SipRequestFirstLine* m_FirstLine;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class SipResponseFirstLine;
|
||||
|
||||
|
||||
/**
|
||||
* @class SipResponseLayer
|
||||
* Represents an SIP response message and inherits all basic functionality of SipLayer and TextBasedProtocolMessage.
|
||||
* The functionality that is added for this class is the SIP first line concept. A SIP response has the following first line:
|
||||
* <i>200 OK SIP/2.0</i>
|
||||
* Since it's not an "ordinary" header field, it requires a special treatment and gets a class of it's own: SipResponseFirstLine.
|
||||
* In most cases a SIP response will be contained in a single packet but for cases it is not, only the first packet will be identified as SIP
|
||||
* response layer. You can find out whether the header is complete by using SipLayer#isHeaderComplete()
|
||||
*/
|
||||
class SipResponseLayer : public SipLayer
|
||||
{
|
||||
friend class SipResponseFirstLine;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Enum for SIP response status codes. List is taken from Wikipedia: https://en.wikipedia.org/wiki/List_of_SIP_response_codes
|
||||
*/
|
||||
enum SipResponseStatusCode
|
||||
{
|
||||
/** Extended search being performed may take a significant time so a forking proxy must send a 100 Trying response */
|
||||
Sip100Trying,
|
||||
/** Destination user agent received INVITE, and is alerting user of call */
|
||||
Sip180Ringing,
|
||||
/** Servers can optionally send this response to indicate a call is being forwarded */
|
||||
Sip181CallisBeingForwarded,
|
||||
/** Indicates that the destination was temporarily unavailable, so the server has queued the call until the destination is available. A server may send multiple 182 responses to update progress of the queue */
|
||||
Sip182Queued,
|
||||
/** This response may be used to send extra information for a call which is still being set up */
|
||||
Sip183SessioninProgress,
|
||||
/** Can be used by User Agent Server to indicate to upstream SIP entities (including the User Agent Client (UAC)) that an early dialog has been terminated */
|
||||
Sip199EarlyDialogTerminated,
|
||||
/** Indicates the request was successful */
|
||||
Sip200OK,
|
||||
/** Indicates that the request has been accepted for processing, but the processing has not been completed */
|
||||
Sip202Accepted,
|
||||
/** Indicates the request was successful, but the corresponding response will not be received */
|
||||
Sip204NoNotification,
|
||||
/** The address resolved to one of several options for the user or client to choose between, which are listed in the message body or the message's Contact fields */
|
||||
Sip300MultipleChoices,
|
||||
/** The original Request-URI is no longer valid, the new address is given in the Contact header field, and the client should update any records of the original Request-URI with the new value */
|
||||
Sip301MovedPermanently,
|
||||
/** The client should try at the address in the Contact field. If an Expires field is present, the client may cache the result for that period of time */
|
||||
Sip302MovedTemporarily,
|
||||
/** The Contact field details a proxy that must be used to access the requested destination */
|
||||
Sip305UseProxy,
|
||||
/** The call failed, but alternatives are detailed in the message body */
|
||||
Sip380AlternativeService,
|
||||
/** The request could not be understood due to malformed syntax */
|
||||
Sip400BadRequest,
|
||||
/** The request requires user authentication. This response is issued by UASs and registrars */
|
||||
Sip401Unauthorized,
|
||||
/** Reserved for future use */
|
||||
Sip402PaymentRequired,
|
||||
/** The server understood the request, but is refusing to fulfill it */
|
||||
Sip403Forbidden,
|
||||
/** The server has definitive information that the user does not exist at the domain specified in the Request-URI. This status is also returned if the domain in the Request-URI does not match any of the domains handled by the recipient of the request */
|
||||
Sip404NotFound,
|
||||
/** The method specified in the Request-Line is understood, but not allowed for the address identified by the Request-URI */
|
||||
Sip405MethodNotAllowed,
|
||||
/** The resource identified by the request is only capable of generating response entities that have content characteristics but not acceptable according to the Accept header field sent in the request */
|
||||
Sip406NotAcceptable,
|
||||
/** The request requires user authentication. This response is issued by proxys */
|
||||
Sip407ProxyAuthenticationRequired,
|
||||
/** Couldn't find the user in time. The server could not produce a response within a suitable amount of time, for example, if it could not determine the location of the user in time. The client MAY repeat the request without modifications at any later time */
|
||||
Sip408RequestTimeout,
|
||||
/** User already registered */
|
||||
Sip409Conflict,
|
||||
/** The user existed once, but is not available here any more */
|
||||
Sip410Gone,
|
||||
/** The server will not accept the request without a valid Content-Length */
|
||||
Sip411LengthRequired,
|
||||
/** The given precondition has not been met */
|
||||
Sip412ConditionalRequestFailed,
|
||||
/** Request body too large */
|
||||
Sip413RequestEntityTooLarge,
|
||||
/** The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret */
|
||||
Sip414RequestURITooLong,
|
||||
/** Request body in a format not supported */
|
||||
Sip415UnsupportedMediaType,
|
||||
/** Request-URI is unknown to the server */
|
||||
Sip416UnsupportedURIScheme,
|
||||
/** There was a resource-priority option tag, but no Resource-Priority header */
|
||||
Sip417UnknownResourcePriority,
|
||||
/** Bad SIP Protocol Extension used, not understood by the server */
|
||||
Sip420BadExtension,
|
||||
/** The server needs a specific extension not listed in the Supported header */
|
||||
Sip421ExtensionRequired,
|
||||
/** The received request contains a Session-Expires header field with a duration below the minimum timer */
|
||||
Sip422SessionIntervalTooSmall,
|
||||
/** Expiration time of the resource is too short */
|
||||
Sip423IntervalTooBrief,
|
||||
/** The request's location content was malformed or otherwise unsatisfactory */
|
||||
Sip424BadLocationInformation,
|
||||
/** The server policy requires an Identity header, and one has not been provided */
|
||||
Sip428UseIdentityHeader,
|
||||
/** The server did not receive a valid Referred-By token on the request */
|
||||
Sip429ProvideReferrerIdentity,
|
||||
/** A specific flow to a user agent has failed, although other flows may succeed. This response is intended for use between proxy devices, and should not be seen by an endpoint (and if it is seen by one, should be treated as a 400 Bad Request response) */
|
||||
Sip430FlowFailed,
|
||||
/** The request has been rejected because it was anonymous */
|
||||
Sip433AnonymityDisallowed,
|
||||
/** The request has an Identity-Info header, and the URI scheme in that header cannot be dereferenced */
|
||||
Sip436BadIdentityInfo,
|
||||
/** The server was unable to validate a certificate for the domain that signed the request */
|
||||
Sip437UnsupportedCertificate,
|
||||
/** The server obtained a valid certificate that the request claimed was used to sign the request, but was unable to verify that signature */
|
||||
Sip438InvalidIdentityHeader,
|
||||
/** The first outbound proxy the user is attempting to register through does not support the "outbound" feature of RFC 5626, although the registrar does */
|
||||
Sip439FirstHopLacksOutboundSupport,
|
||||
/** If a SIP proxy determines a response context has insufficient Incoming Max-Breadth to carry out a desired parallel fork, and the proxy is unwilling/unable to compensate by forking serially or sending a redirect, that proxy MUST return a 440 response. A client receiving a 440 response can infer that its request did not reach all possible destinations */
|
||||
Sip440MaxBreadthExceeded,
|
||||
/** If a SIP UA receives an INFO request associated with an Info Package that the UA has not indicated willingness to receive, the UA MUST send a 469 response, which contains a Recv-Info header field with Info Packages for which the UA is willing to receive INFO requests */
|
||||
Sip469BadInfoPackage,
|
||||
/** The source of the request did not have the permission of the recipient to make such a request */
|
||||
Sip470ConsentNeeded,
|
||||
/** Callee currently unavailable */
|
||||
Sip480TemporarilyUnavailable,
|
||||
/** Server received a request that does not match any dialog or transaction */
|
||||
Sip481Call_TransactionDoesNotExist,
|
||||
/** Server has detected a loop */
|
||||
Sip482LoopDetected,
|
||||
/** Max-Forwards header has reached the value '0' */
|
||||
Sip483TooManyHops,
|
||||
/** Request-URI incomplete */
|
||||
Sip484AddressIncomplete,
|
||||
/** Request-URI is ambiguous */
|
||||
Sip485Ambiguous,
|
||||
/** Callee is busy */
|
||||
Sip486BusyHere,
|
||||
/** Request has terminated by bye or cancel */
|
||||
Sip487RequestTerminated,
|
||||
/** Some aspect of the session description or the Request-URI is not acceptable */
|
||||
Sip488NotAcceptableHere,
|
||||
/** The server did not understand an event package specified in an Event header field */
|
||||
Sip489BadEvent,
|
||||
/** Server has some pending request from the same dialog */
|
||||
Sip491RequestPending,
|
||||
/** Request contains an encrypted MIME body, which recipient can not decrypt */
|
||||
Sip493Undecipherable,
|
||||
/** The server has received a request that requires a negotiated security mechanism, and the response contains a list of suitable security mechanisms for the requester to choose between, or a digest authentication challenge */
|
||||
Sip494SecurityAgreementRequired,
|
||||
/** The server could not fulfill the request due to some unexpected condition */
|
||||
Sip500ServerInternalError,
|
||||
/** The server does not have the ability to fulfill the request, such as because it does not recognize the request method. (Compare with 405 Method Not Allowed, where the server recognizes the method but does not allow or support it.) */
|
||||
Sip501NotImplemented,
|
||||
/** The server is acting as a gateway or proxy, and received an invalid response from a downstream server while attempting to fulfill the request */
|
||||
Sip502BadGateway,
|
||||
/** The server is undergoing maintenance or is temporarily overloaded and so cannot process the request. A "Retry-After" header field may specify when the client may reattempt its request */
|
||||
Sip503ServiceUnavailable,
|
||||
/** The server attempted to access another server in attempting to process the request, and did not receive a prompt response */
|
||||
Sip504ServerTimeout,
|
||||
/** The SIP protocol version in the request is not supported by the server */
|
||||
Sip505VersionNotSupported,
|
||||
/** The request message length is longer than the server can process */
|
||||
Sip513MessageTooLarge,
|
||||
/** The server is unable or unwilling to meet some constraints specified in the offer */
|
||||
Sip580PreconditionFailure,
|
||||
/** All possible destinations are busy. Unlike the 486 response, this response indicates the destination knows there are no alternative destinations (such as a voicemail server) able to accept the call */
|
||||
Sip600BusyEverywhere,
|
||||
/** The destination does not wish to participate in the call, or cannot do so, and additionally the destination knows there are no alternative destinations (such as a voicemail server) willing to accept the call */
|
||||
Sip603Decline,
|
||||
/** The server has authoritative information that the requested user does not exist anywhere */
|
||||
Sip604DoesNotExistAnywhere,
|
||||
/** The user's agent was contacted successfully but some aspects of the session description such as the requested media, bandwidth, or addressing style were not acceptable */
|
||||
Sip606NotAcceptable,
|
||||
/** The called party did not want this call from the calling party. Future attempts from the calling party are likely to be similarly rejected */
|
||||
Sip607Unwanted,
|
||||
/** Unknown SIP status code */
|
||||
SipStatusCodeUnknown
|
||||
};
|
||||
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
SipResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new SIP response with only the first line filled. The request will be created without further fields.
|
||||
* The user can then add fields using addField() or insertField() methods
|
||||
* @param[in] statusCode SIP status code to set
|
||||
* @param[in] statusCodeString Most status codes have their default string, e.g 200 is usually "OK" etc.
|
||||
* But the user can set a non-default status code string and it will be written in the header first line. Empty string ("") means using the
|
||||
* default status code string. Also, the default is using the default status code string
|
||||
* @param[in] sipVersion SIP version to set, default is SIP/2.0
|
||||
*
|
||||
*/
|
||||
SipResponseLayer(SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString = "", std::string sipVersion = "SIP/2.0");
|
||||
|
||||
virtual ~SipResponseLayer();
|
||||
|
||||
/**
|
||||
* A copy constructor for this layer. This copy constructor inherits base copy constructor SipLayer and adds the functionality
|
||||
* of copying the first line as well
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
SipResponseLayer(const SipResponseLayer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator overload for this layer. This method inherits base assignment operator SipLayer#operator=() and adds the functionality
|
||||
* of copying the first line as well
|
||||
* @param[in] other The instance to copy from
|
||||
*/
|
||||
SipResponseLayer& operator=(const SipResponseLayer& other);
|
||||
|
||||
/**
|
||||
* @return A pointer to the first line instance for this message
|
||||
*/
|
||||
SipResponseFirstLine* getFirstLine() const { return m_FirstLine; }
|
||||
|
||||
// implement Layer's abstract methods
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
SipResponseFirstLine* m_FirstLine;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class SipRequestFirstLine
|
||||
* Represents an SIP request first line. The first line includes 3 parameters: SIP method (e.g INVITE, ACK, BYE, etc.),
|
||||
* URI (e.g sip:bla@bla.com:12345) and SIP version (usually SIP/2.0). All these parameters are included in this class, and the user
|
||||
* can retrieve or set them.
|
||||
* This class cannot be instantiated by users, it's created inside SipRequestLayer and user can get a pointer to an instance of it. All "getters"
|
||||
* of this class retrieve the actual data of the SIP request and the "setters" actually change the packet data.
|
||||
* Since SIP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So many "setter" methods
|
||||
* of this class may need to shorten or extend the data in SipRequestLayer. These methods will return a false value if this action failed
|
||||
*/
|
||||
class SipRequestFirstLine
|
||||
{
|
||||
friend class SipRequestLayer;
|
||||
public:
|
||||
|
||||
/**
|
||||
* @return The SIP request method
|
||||
*/
|
||||
SipRequestLayer::SipMethod getMethod() const { return m_Method; }
|
||||
|
||||
/**
|
||||
* Set the SIP request method
|
||||
* @param[in] newMethod The method to set
|
||||
* @return False if newMethod is SipRequestLayer#SipMethodUnknown or if shortening/extending the SipRequestLayer data failed. True otherwise
|
||||
*/
|
||||
bool setMethod(SipRequestLayer::SipMethod newMethod);
|
||||
|
||||
/**
|
||||
* @return A copied version of the URI (notice changing the return value won't change the actual data of the packet)
|
||||
*/
|
||||
std::string getUri() const;
|
||||
|
||||
/**
|
||||
* Set the URI
|
||||
* @param[in] newUri The URI to set
|
||||
* @return False if shortening/extending the SipRequestLayer data failed. True otherwise
|
||||
*/
|
||||
bool setUri(std::string newUri);
|
||||
|
||||
/**
|
||||
* @return The SIP version
|
||||
*/
|
||||
std::string getVersion() const { return m_Version; }
|
||||
|
||||
/**
|
||||
* A static method for parsing the SIP method out of raw data
|
||||
* @param[in] data The raw data
|
||||
* @param[in] dataLen The raw data length
|
||||
* @return The parsed SIP method
|
||||
*/
|
||||
static SipRequestLayer::SipMethod parseMethod(char* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* @return The size in bytes of the SIP request first line
|
||||
*/
|
||||
int getSize() const { return m_FirstLineEndOffset; }
|
||||
|
||||
/**
|
||||
* As explained in SipRequestLayer, a SIP message can sometimes spread over more than 1 packet, so when looking at a single packet
|
||||
* the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication
|
||||
* whether the first line is partial
|
||||
* @return False if the first line is partial, true if it's complete
|
||||
*/
|
||||
bool isComplete() const { return m_IsComplete; }
|
||||
|
||||
/**
|
||||
* @class SipRequestFirstLineException
|
||||
* This exception can be thrown while constructing SipRequestFirstLine (the constructor is private, so the construction happens
|
||||
* only in SipRequestLayer). This kind of exception is thrown if trying to construct with SIP method of
|
||||
* SipRequestLayer#SipMethodUnknown or with empty SIP version
|
||||
*/
|
||||
class SipRequestFirstLineException : public std::exception
|
||||
{
|
||||
public:
|
||||
~SipRequestFirstLineException() throw() {}
|
||||
void setMessage(std::string message) { m_Message = message; }
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
private:
|
||||
std::string m_Message;
|
||||
};
|
||||
|
||||
private:
|
||||
SipRequestFirstLine(SipRequestLayer* sipRequest);
|
||||
SipRequestFirstLine(SipRequestLayer* sipRequest, SipRequestLayer::SipMethod method, std::string version, std::string uri);
|
||||
//throw(SipRequestFirstLineException); // Deprecated in C++17
|
||||
|
||||
void parseVersion();
|
||||
|
||||
SipRequestLayer* m_SipRequest;
|
||||
SipRequestLayer::SipMethod m_Method;
|
||||
std::string m_Version;
|
||||
int m_VersionOffset;
|
||||
int m_UriOffset;
|
||||
int m_FirstLineEndOffset;
|
||||
bool m_IsComplete;
|
||||
SipRequestFirstLineException m_Exception;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class SipResponseFirstLine
|
||||
* Represents an SIP response message first line. The first line includes 2 parameters: status code (e.g 100 Trying ,200 OK, etc.),
|
||||
* and SIP version (usually SIP/2.0). These 2 parameters are included in this class, and the user can retrieve or set them.
|
||||
* This class cannot be instantiated by users, it's created inside SipResponseLayer and user can get a pointer to an instance of it. The "getter"
|
||||
* methods of this class will retrieve the actual data of the SIP response and the "setter" methods will change the packet data.
|
||||
* Since SIP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "setter" methods
|
||||
* of this class may need to shorten or extend the data in SipResponseLayer. These methods will return a false value if this action failed
|
||||
*/
|
||||
class SipResponseFirstLine
|
||||
{
|
||||
friend class SipResponseLayer;
|
||||
public:
|
||||
/**
|
||||
* @return The status code as SipResponseLayer#SipResponseStatusCode enum
|
||||
*/
|
||||
SipResponseLayer::SipResponseStatusCode getStatusCode() const { return m_StatusCode; }
|
||||
|
||||
/**
|
||||
* @return The status code number as integer (e.g 200, 100, etc.)
|
||||
*/
|
||||
int getStatusCodeAsInt() const;
|
||||
|
||||
/**
|
||||
* @return The status code message (e.g "OK", "Trying", etc.)
|
||||
*/
|
||||
std::string getStatusCodeString() const;
|
||||
|
||||
/**
|
||||
* Set the status code
|
||||
* @param[in] newStatusCode The new status code to set
|
||||
* @param[in] statusCodeString An optional parameter: set a non-default status code message (e.g "Bla Bla" instead of "Not Found"). If
|
||||
* this parameter isn't supplied or supplied as empty string (""), the default message for the status code will be set
|
||||
*/
|
||||
bool setStatusCode(SipResponseLayer::SipResponseStatusCode newStatusCode, std::string statusCodeString = "");
|
||||
|
||||
/**
|
||||
* @return The SIP version
|
||||
*/
|
||||
std::string getVersion() const { return m_Version; }
|
||||
|
||||
/**
|
||||
* Set the SIP version. The version to set is expected to be in the format of SIP/x.y otherwise an error will be written to log
|
||||
* @param[in] newVersion The SIP version to set
|
||||
*/
|
||||
void setVersion(std::string newVersion);
|
||||
|
||||
/**
|
||||
* A static method for parsing the SIP status code out of raw data
|
||||
* @param[in] data The raw data
|
||||
* @param[in] dataLen The raw data length
|
||||
* @return The parsed SIP status code as enum
|
||||
*/
|
||||
static SipResponseLayer::SipResponseStatusCode parseStatusCode(char* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* A static method for parsing the SIP version out of raw data
|
||||
* @param[in] data The raw data
|
||||
* @param[in] dataLen The raw data length
|
||||
* @return The parsed SIP version string or an empty string if version cannot be extracted
|
||||
*/
|
||||
static std::string parseVersion(char* data, size_t dataLen);
|
||||
|
||||
/**
|
||||
* @return The size in bytes of the SIP response first line
|
||||
*/
|
||||
int getSize() const { return m_FirstLineEndOffset; }
|
||||
|
||||
/**
|
||||
* As explained in SipResponseLayer, A SIP message can sometimes spread over more than 1 packet, so when looking at a single packet
|
||||
* the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication
|
||||
* whether the first line is partial
|
||||
* @return False if the first line is partial, true if it's complete
|
||||
*/
|
||||
bool isComplete() const { return m_IsComplete; }
|
||||
|
||||
/**
|
||||
* @class SipResponseFirstLineException
|
||||
* This exception can be thrown while constructing SipResponseFirstLine (the constructor is private, so the construction happens
|
||||
* only in SipResponseLayer). This kind of exception will be thrown if trying to construct with SIP status code of
|
||||
* SipResponseLayer#SipStatusCodeUnknown or with an empty SIP version
|
||||
*/
|
||||
class SipResponseFirstLineException : public std::exception
|
||||
{
|
||||
public:
|
||||
~SipResponseFirstLineException() throw() {}
|
||||
void setMessage(std::string message) { m_Message = message; }
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
private:
|
||||
std::string m_Message;
|
||||
};
|
||||
|
||||
private:
|
||||
SipResponseFirstLine(SipResponseLayer* sipResponse);
|
||||
SipResponseFirstLine(SipResponseLayer* sipResponse, std::string version, SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString = "");
|
||||
|
||||
static SipResponseLayer::SipResponseStatusCode validateStatusCode(char* data, size_t dataLen, SipResponseLayer::SipResponseStatusCode potentialCode);
|
||||
|
||||
|
||||
SipResponseLayer* m_SipResponse;
|
||||
std::string m_Version;
|
||||
SipResponseLayer::SipResponseStatusCode m_StatusCode;
|
||||
int m_FirstLineEndOffset;
|
||||
bool m_IsComplete;
|
||||
SipResponseFirstLineException m_Exception;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_SIP_LAYER
|
||||
110
pcappp/include/pcapplusplus/SllLayer.h
Normal file
110
pcappp/include/pcapplusplus/SllLayer.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#ifndef PACKETPP_SLL_LAYER
|
||||
#define PACKETPP_SLL_LAYER
|
||||
|
||||
#include "MacAddress.h"
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct sll_header
|
||||
* Represents SLL header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct sll_header
|
||||
{
|
||||
/** Specifies whether packet was: specifically sent to us by somebody else (value=0);
|
||||
* broadcast by somebody else (value=1); multicast, but not broadcast, by somebody else (value=2);
|
||||
* sent to somebody else by somebody else (value=3); sent by us (value=4)
|
||||
**/
|
||||
uint16_t packet_type;
|
||||
/** Contains a Linux ARPHRD_ value for the link-layer device type */
|
||||
uint16_t ARPHRD_type;
|
||||
/** Contains the length of the link-layer address of the sender of the packet. That length could be zero */
|
||||
uint16_t link_layer_addr_len;
|
||||
/** contains the link-layer address of the sender of the packet; the number of bytes of that field that are
|
||||
* meaningful is specified by the link-layer address length field
|
||||
**/
|
||||
uint8_t link_layer_addr[8];
|
||||
/** Contains an Ethernet protocol type of the next layer */
|
||||
uint16_t protocol_type;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @class SllLayer
|
||||
* Represents an SLL (Linux cooked capture) protocol layer
|
||||
*/
|
||||
class SllLayer : public Layer
|
||||
{
|
||||
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 ether_header)
|
||||
* @param[in] dataLen Size of the data in bytes
|
||||
* @param[in] packet A pointer to the Packet instance where layer will be stored in
|
||||
*/
|
||||
SllLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = SLL; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new SLL header and allocates the data
|
||||
* @param[in] packetType The packet type
|
||||
* @param[in] ARPHRDType The ARPHRD type
|
||||
*/
|
||||
SllLayer(uint16_t packetType, uint16_t ARPHRDType);
|
||||
|
||||
~SllLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the Sll header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the sll_header
|
||||
*/
|
||||
sll_header* getSllHeader() const { return (sll_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* A setter for the link layer address field
|
||||
* @param[in] addr The address to set. Memory will be copied to packet
|
||||
* @param[in] addrLength Address length, must be lower or equal to 8 (which is max length for SLL address)
|
||||
* @return True if address was set successfully, or false of addrLength is out of bounds (0 or larger than 8)
|
||||
*/
|
||||
bool setLinkLayerAddr(uint8_t* addr, size_t addrLength);
|
||||
|
||||
/**
|
||||
* Set a MAC address in the link layer address field
|
||||
* @param[in] macAddr MAC address to set
|
||||
* @return True if address was set successfully, false if MAC address isn't valid or if set failed
|
||||
*/
|
||||
bool setMacAddressAsLinkLayer(MacAddress macAddr);
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer,
|
||||
* MplsLayer.
|
||||
* Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of sll_header
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(sll_header); }
|
||||
|
||||
/**
|
||||
* Calculate the next protocol type for known protocols: IPv4, IPv6, ARP, VLAN
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_SLL_LAYER */
|
||||
392
pcappp/include/pcapplusplus/SystemUtils.h
Normal file
392
pcappp/include/pcapplusplus/SystemUtils.h
Normal file
@@ -0,0 +1,392 @@
|
||||
#ifndef PCAPPP_SYSTEM_UTILS
|
||||
#define PCAPPP_SYSTEM_UTILS
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
#define MAX_NUM_OF_CORES 32
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int gettimeofday(struct timeval * tp, struct timezone * tzp);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct SystemCore
|
||||
* Represents data of 1 CPU core. Current implementation supports up to 32 cores
|
||||
*/
|
||||
struct SystemCore
|
||||
{
|
||||
/**
|
||||
* Core position in a 32-bit mask. For each core this attribute holds a 4B integer where only 1 bit is set, according to the core ID.
|
||||
* For example: in core #0 the right-most bit will be set (meaning the number 0x01);
|
||||
* in core #5 the 5th right-most bit will be set (meaning the number 0x20)...
|
||||
*/
|
||||
uint32_t Mask;
|
||||
|
||||
/**
|
||||
* Core ID - a value between 0 and 31
|
||||
*/
|
||||
uint8_t Id;
|
||||
|
||||
/**
|
||||
* Overload of the comparison operator
|
||||
* @return true if 2 addresses are equal. False otherwise
|
||||
*/
|
||||
bool operator==(const SystemCore& other) const { return Id == other.Id; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct SystemCores
|
||||
* Contains static representation to all 32 cores and a static array to map core ID (integer) to a SystemCore struct
|
||||
*/
|
||||
struct SystemCores
|
||||
{
|
||||
/**
|
||||
* Static representation of core #0
|
||||
*/
|
||||
static const SystemCore Core0;
|
||||
/**
|
||||
* Static representation of core #1
|
||||
*/
|
||||
static const SystemCore Core1;
|
||||
/**
|
||||
* Static representation of core #2
|
||||
*/
|
||||
static const SystemCore Core2;
|
||||
/**
|
||||
* Static representation of core #3
|
||||
*/
|
||||
static const SystemCore Core3;
|
||||
/**
|
||||
* Static representation of core #4
|
||||
*/
|
||||
static const SystemCore Core4;
|
||||
/**
|
||||
* Static representation of core #5
|
||||
*/
|
||||
static const SystemCore Core5;
|
||||
/**
|
||||
* Static representation of core #6
|
||||
*/
|
||||
static const SystemCore Core6;
|
||||
/**
|
||||
* Static representation of core #7
|
||||
*/
|
||||
static const SystemCore Core7;
|
||||
/**
|
||||
* Static representation of core #8
|
||||
*/
|
||||
static const SystemCore Core8;
|
||||
/**
|
||||
* Static representation of core #9
|
||||
*/
|
||||
static const SystemCore Core9;
|
||||
/**
|
||||
* Static representation of core #10
|
||||
*/
|
||||
static const SystemCore Core10;
|
||||
/**
|
||||
* Static representation of core #11
|
||||
*/
|
||||
static const SystemCore Core11;
|
||||
/**
|
||||
* Static representation of core #12
|
||||
*/
|
||||
static const SystemCore Core12;
|
||||
/**
|
||||
* Static representation of core #13
|
||||
*/
|
||||
static const SystemCore Core13;
|
||||
/**
|
||||
* Static representation of core #14
|
||||
*/
|
||||
static const SystemCore Core14;
|
||||
/**
|
||||
* Static representation of core #15
|
||||
*/
|
||||
static const SystemCore Core15;
|
||||
/**
|
||||
* Static representation of core #16
|
||||
*/
|
||||
static const SystemCore Core16;
|
||||
/**
|
||||
* Static representation of core #17
|
||||
*/
|
||||
static const SystemCore Core17;
|
||||
/**
|
||||
* Static representation of core #18
|
||||
*/
|
||||
static const SystemCore Core18;
|
||||
/**
|
||||
* Static representation of core #19
|
||||
*/
|
||||
static const SystemCore Core19;
|
||||
/**
|
||||
* Static representation of core #20
|
||||
*/
|
||||
static const SystemCore Core20;
|
||||
/**
|
||||
* Static representation of core #21
|
||||
*/
|
||||
static const SystemCore Core21;
|
||||
/**
|
||||
* Static representation of core #22
|
||||
*/
|
||||
static const SystemCore Core22;
|
||||
/**
|
||||
* Static representation of core #23
|
||||
*/
|
||||
static const SystemCore Core23;
|
||||
/**
|
||||
* Static representation of core #24
|
||||
*/
|
||||
static const SystemCore Core24;
|
||||
/**
|
||||
* Static representation of core #25
|
||||
*/
|
||||
static const SystemCore Core25;
|
||||
/**
|
||||
* Static representation of core #26
|
||||
*/
|
||||
static const SystemCore Core26;
|
||||
/**
|
||||
* Static representation of core #27
|
||||
*/
|
||||
static const SystemCore Core27;
|
||||
/**
|
||||
* Static representation of core #28
|
||||
*/
|
||||
static const SystemCore Core28;
|
||||
/**
|
||||
* Static representation of core #29
|
||||
*/
|
||||
static const SystemCore Core29;
|
||||
/**
|
||||
* Static representation of core #30
|
||||
*/
|
||||
static const SystemCore Core30;
|
||||
/**
|
||||
* Static representation of core #31
|
||||
*/
|
||||
static const SystemCore Core31;
|
||||
|
||||
/**
|
||||
* A static array for mapping core ID (integer) to the corresponding static SystemCore representation
|
||||
*/
|
||||
static const SystemCore IdToSystemCore[MAX_NUM_OF_CORES];
|
||||
};
|
||||
|
||||
typedef uint32_t CoreMask;
|
||||
|
||||
/**
|
||||
* Get total number of cores on device
|
||||
* @return Total number of CPU cores on device
|
||||
*/
|
||||
int getNumOfCores();
|
||||
|
||||
/**
|
||||
* Create a core mask for all cores available on machine
|
||||
* @return A core mask for all cores available on machine
|
||||
*/
|
||||
CoreMask getCoreMaskForAllMachineCores();
|
||||
|
||||
|
||||
/**
|
||||
* Create a core mask from a vector of system cores
|
||||
* @param[in] cores A vector of SystemCore instances
|
||||
* @return A core mask representing these cores
|
||||
*/
|
||||
CoreMask createCoreMaskFromCoreVector(std::vector<SystemCore> cores);
|
||||
|
||||
|
||||
/**
|
||||
* Create a core mask from a vector of core IDs
|
||||
* @param[in] coreIds A vector of core IDs
|
||||
* @return A core mask representing these cores
|
||||
*/
|
||||
CoreMask createCoreMaskFromCoreIds(std::vector<int> coreIds);
|
||||
|
||||
|
||||
/**
|
||||
* Convert a core mask into a vector of its appropriate system cores
|
||||
* @param[in] coreMask The input core mask
|
||||
* @param[out] resultVec The vector that will contain the system cores
|
||||
*/
|
||||
void createCoreVectorFromCoreMask(CoreMask coreMask, std::vector<SystemCore>& resultVec);
|
||||
|
||||
/**
|
||||
* Execute a shell command and return its output
|
||||
* @param[in] command The command to run
|
||||
* @return The output of the command (both stdout and stderr)
|
||||
*/
|
||||
std::string executeShellCommand(const std::string command);
|
||||
|
||||
/**
|
||||
* Check if a directory exists
|
||||
* @param[in] dirPath Full path of the directory to search
|
||||
* @return True if directory exists, false otherwise
|
||||
*/
|
||||
bool directoryExists(std::string dirPath);
|
||||
|
||||
/**
|
||||
* Retrieve a system-wide real-time accurate clock. It's actually a multi-platform version of clock_gettime() which is
|
||||
* fully supported only on Linux
|
||||
* @param[out] sec The second portion of the time
|
||||
* @param[out] nsec The nanosecond portion of the time
|
||||
* @return 0 for success, or -1 for failure
|
||||
*/
|
||||
int clockGetTime(long& sec, long& nsec);
|
||||
|
||||
/**
|
||||
* A multi-platform version of the popular sleep method. This method simply runs the right sleep method, according to the platform
|
||||
* it is running on.
|
||||
* @param[in] seconds Number of seconds to sleep
|
||||
*/
|
||||
void multiPlatformSleep(uint32_t seconds);
|
||||
|
||||
/**
|
||||
* A multi-platform version of sleep in milliseconds resolution. This method simply runs the right sleep method, according to the platform
|
||||
* it is running on.
|
||||
* @param[in] milliseconds Number of milliseconds to sleep
|
||||
*/
|
||||
void multiPlatformMSleep(uint32_t milliseconds);
|
||||
|
||||
/**
|
||||
* A multi-platform version of `htons` which convert host to network byte order
|
||||
* @param[in] host Value in host byte order
|
||||
* @return Value in network byte order
|
||||
*/
|
||||
uint16_t hostToNet16(uint16_t host);
|
||||
|
||||
/**
|
||||
* A multi-platform version of `ntohs` which convert network to host byte order
|
||||
* @param[in] net Value in network byte order
|
||||
* @return Value in host byte order
|
||||
*/
|
||||
uint16_t netToHost16(uint16_t net);
|
||||
|
||||
/**
|
||||
* A multi-platform version of `htonl` which convert host to network byte order
|
||||
* @param[in] host Value in host byte order
|
||||
* @return Value in network byte order
|
||||
*/
|
||||
uint32_t hostToNet32(uint32_t host);
|
||||
|
||||
/**
|
||||
* A multi-platform version of `ntohl` which convert network to host byte order
|
||||
* @param[in] net Value in network byte order
|
||||
* @return Value in host byte order
|
||||
*/
|
||||
uint32_t netToHost32(uint32_t net);
|
||||
|
||||
/**
|
||||
* @class AppName
|
||||
* This class extracts the application name from the current running executable and stores it for usage of the application throughout its runtime.
|
||||
* This class should be initialized once in the beginning of the main() method using AppName#init() and from then on the app name could be retrieved using AppName#get()
|
||||
*/
|
||||
class AppName
|
||||
{
|
||||
private:
|
||||
static std::string m_AppName;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Static init method which should be called once at the beginning of the main method.
|
||||
* @param[in] argc The argc param from main()
|
||||
* @param[in] argv The argv param from main()
|
||||
* @return No return value
|
||||
*/
|
||||
static void init(int argc, char* argv[])
|
||||
{
|
||||
if (argc == 0)
|
||||
{
|
||||
m_AppName.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_AppName = argv[0];
|
||||
|
||||
// remove Linux/Unix path
|
||||
size_t lastPos = m_AppName.rfind('/');
|
||||
if (lastPos != std::string::npos)
|
||||
{
|
||||
m_AppName = m_AppName.substr(lastPos + 1);
|
||||
}
|
||||
|
||||
// remove Windows path
|
||||
lastPos = m_AppName.rfind('\\');
|
||||
if (lastPos != std::string::npos)
|
||||
{
|
||||
m_AppName = m_AppName.substr(lastPos + 1);
|
||||
}
|
||||
|
||||
// remove file extension
|
||||
m_AppName = m_AppName.substr(0, m_AppName.rfind('.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The app name as extracted from the current running executable
|
||||
*/
|
||||
static const std::string& get() { return m_AppName; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ApplicationEventHandler
|
||||
* A singleton class that provides callbacks for events that occur during application life-cycle such as ctrl+c pressed,
|
||||
* application closed, killed, etc.
|
||||
*/
|
||||
class ApplicationEventHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @typedef EventHandlerCallback
|
||||
* The callback to be invoked when the event occurs
|
||||
* @param[in] cookie A pointer the the cookie provided by the user in ApplicationEventHandler c'tor
|
||||
*/
|
||||
typedef void (*EventHandlerCallback)(void* cookie);
|
||||
|
||||
/**
|
||||
* As ApplicationEventHandler is a singleton, this is the static getter to retrieve its instance
|
||||
* @return The singleton instance of ApplicationEventHandler
|
||||
*/
|
||||
static ApplicationEventHandler& getInstance()
|
||||
{
|
||||
static ApplicationEventHandler instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register for an application-interrupted event, meaning ctrl+c was pressed
|
||||
* @param[in] handler The callback to be activated when the event occurs
|
||||
* @param[in] cookie A pointer to a user provided object. This object will be transferred to the EventHandlerCallback callback.
|
||||
* This cookie is very useful for transferring objects that give context to the event callback
|
||||
*/
|
||||
void onApplicationInterrupted(EventHandlerCallback handler, void* cookie);
|
||||
|
||||
private:
|
||||
EventHandlerCallback m_ApplicationInterruptedHandler;
|
||||
void* m_ApplicationInterruptedCookie;
|
||||
|
||||
// private c'tor
|
||||
ApplicationEventHandler();
|
||||
|
||||
#if defined(_WIN32)
|
||||
static int handlerRoutine(unsigned long fdwCtrlType);
|
||||
#else
|
||||
static void handlerRoutine(int signum);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PCAPPP_SYSTEM_UTILS */
|
||||
398
pcappp/include/pcapplusplus/TLVData.h
Normal file
398
pcappp/include/pcapplusplus/TLVData.h
Normal file
@@ -0,0 +1,398 @@
|
||||
#ifndef PACKETPP_TLV_DATA
|
||||
#define PACKETPP_TLV_DATA
|
||||
|
||||
#include "Layer.h"
|
||||
#include "IpAddress.h"
|
||||
#include <string.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* @class TLVRecord
|
||||
* A wrapper class for a Type-Length-Value (TLV) record. This class does not create or modify TLV records, but rather
|
||||
* serves as a wrapper and provides useful methods for retrieving data from them. This class has several abstract methods
|
||||
* that should be implemented in derived classes. These methods are for record length value calculation (the 'L' in TLV)
|
||||
* which is implemented differently in different protocols
|
||||
*/
|
||||
template<typename TRecType, typename TRecLen>
|
||||
class TLVRecord
|
||||
{
|
||||
protected:
|
||||
|
||||
/** A struct representing the TLV construct */
|
||||
struct TLVRawData
|
||||
{
|
||||
/** Record type */
|
||||
TRecType recordType;
|
||||
/** Record length in bytes */
|
||||
TRecLen recordLen;
|
||||
/** Record value (variable size) */
|
||||
uint8_t recordValue[];
|
||||
};
|
||||
|
||||
TLVRawData* m_Data;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the TLV record raw data (byte array)
|
||||
* @param[in] recordRawData A pointer to the TLV record raw data
|
||||
*/
|
||||
TLVRecord(uint8_t* recordRawData)
|
||||
{
|
||||
assign(recordRawData);
|
||||
}
|
||||
|
||||
/**
|
||||
* A copy c'tor for this class. This copy c'tor doesn't copy the TLV data, but only the pointer to it,
|
||||
* which means that after calling it both the old and the new instance will point to the same TLV raw data
|
||||
* @param[in] other The TLVRecord instance to copy from
|
||||
*/
|
||||
TLVRecord(const TLVRecord& other)
|
||||
{
|
||||
m_Data = other.m_Data;
|
||||
}
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
virtual ~TLVRecord() { }
|
||||
|
||||
/**
|
||||
* Assign a pointer to the TLV record raw data (byte array)
|
||||
* @param[in] recordRawData A pointer to the TLV record raw data
|
||||
*/
|
||||
void assign(uint8_t* recordRawData)
|
||||
{
|
||||
if(recordRawData == NULL)
|
||||
m_Data = NULL;
|
||||
else
|
||||
m_Data = (TLVRawData*)recordRawData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of the assignment operator. This operator doesn't copy the TLV data, but rather copies the pointer to it,
|
||||
* which means that after calling it both the old and the new instance will point to the same TLV raw data
|
||||
* @param[in] other The TLVRecord instance to assign
|
||||
*/
|
||||
TLVRecord& operator=(const TLVRecord& other)
|
||||
{
|
||||
m_Data = other.m_Data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of the equality operator. Two record are equal if both of them point to the same data, or if they point
|
||||
* to different data but their total size is equal and the raw data they both contain is similar.
|
||||
* @param[in] rhs The object to compare to
|
||||
* @return True if both objects are equal, false otherwise
|
||||
*/
|
||||
bool operator==(const TLVRecord& rhs) const
|
||||
{
|
||||
if (m_Data == rhs.m_Data)
|
||||
return true;
|
||||
|
||||
if (getTotalSize() != rhs.getTotalSize())
|
||||
return false;
|
||||
|
||||
if (isNull() || ((TLVRecord&)rhs).isNull())
|
||||
return false;
|
||||
|
||||
return (memcmp(m_Data, rhs.m_Data, getTotalSize()) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of the not equal operator.
|
||||
* @param[in] rhs The object to compare to
|
||||
* @return True if objects are not equal, false otherwise
|
||||
*/
|
||||
bool operator!=(const TLVRecord& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type field of the record (the 'T' in __Type__-Length-Value)
|
||||
*/
|
||||
TRecType getType() const { return m_Data->recordType; }
|
||||
|
||||
/**
|
||||
* @return A pointer to the value of the record as byte array (the 'V' in Type-Length- __Value__)
|
||||
*/
|
||||
uint8_t* getValue() const { return m_Data->recordValue; }
|
||||
|
||||
/**
|
||||
* @return True if the TLV record raw data is NULL, false otherwise
|
||||
*/
|
||||
bool isNull() const { return (m_Data == NULL); }
|
||||
|
||||
/**
|
||||
* @return True if the TLV record raw data is not NULL, false otherwise
|
||||
*/
|
||||
bool isNotNull() const { return (m_Data != NULL); }
|
||||
|
||||
/**
|
||||
* @return A pointer to the TLV record raw data byte stream
|
||||
*/
|
||||
uint8_t* getRecordBasePtr() const { return (uint8_t*)m_Data; }
|
||||
|
||||
/**
|
||||
* Free the memory of the TLV record raw data
|
||||
*/
|
||||
void purgeRecordData() { if (!isNull()) delete [] m_Data; }
|
||||
|
||||
/**
|
||||
* A templated method to retrieve the record data as a certain type T. For example, if record data is 4B long
|
||||
* (integer) then this method should be used as getValueAs<int>() and it will return the record data as an integer.<BR>
|
||||
* Notice this return value is a copy of the data, not a pointer to the actual data
|
||||
* @param[in] offset The offset in the record data to start reading the value from. Useful for cases when you want
|
||||
* to read some of the data that doesn't start at offset 0. This is an optional parameter and the default value
|
||||
* is 0, meaning start reading the value at the beginning of the record data
|
||||
* @return The record data as type T
|
||||
*/
|
||||
template<typename T>
|
||||
T getValueAs(size_t offset = 0) const
|
||||
{
|
||||
if (getDataSize() - offset < sizeof(T))
|
||||
return 0;
|
||||
|
||||
T result;
|
||||
memcpy(&result, m_Data->recordValue + offset, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* A templated method to copy data of type T into the TLV record data. For example: if record data is 4[Bytes] long use
|
||||
* this method with \<int\> to set an integer value into the record data: setValue<int>(num)
|
||||
* @param[in] newValue The value of type T to copy to the record data
|
||||
* @param[in] valueOffset An optional parameter that specifies where to start setting the record data (default set to 0). For example:
|
||||
* if record data is 20 bytes long and you only need to set the 4 last bytes as integer then use this method like this:
|
||||
* setValue<int>(num, 16)
|
||||
* @return True if value was set successfully or false if the size of T is larger than the record data size
|
||||
*/
|
||||
template<typename T>
|
||||
bool setValue(T newValue, int valueOffset = 0)
|
||||
{
|
||||
if (getDataSize() < sizeof(T))
|
||||
return false;
|
||||
|
||||
memcpy(m_Data->recordValue + valueOffset, &newValue, sizeof(T));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The total size of the TLV record (in bytes)
|
||||
*/
|
||||
virtual size_t getTotalSize() const = 0;
|
||||
|
||||
/**
|
||||
* @return The size of the record value (meaning the size of the 'V' part in TLV)
|
||||
*/
|
||||
virtual size_t getDataSize() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class TLVRecordReader
|
||||
* A class for reading TLV records data out of a byte stream. This class contains helper methods for retrieving and
|
||||
* counting TLV records. This is a template class that expects template argument class derived from TLVRecord.
|
||||
*/
|
||||
template<typename TLVRecordType>
|
||||
class TLVRecordReader
|
||||
{
|
||||
private:
|
||||
mutable size_t m_RecordCount;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A default c'tor for this class
|
||||
*/
|
||||
TLVRecordReader() { m_RecordCount = (size_t)-1; }
|
||||
|
||||
/**
|
||||
* A default copy c'tor for this class
|
||||
*/
|
||||
TLVRecordReader(const TLVRecordReader& other)
|
||||
{
|
||||
m_RecordCount = other.m_RecordCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* A d'tor for this class which currently does nothing
|
||||
*/
|
||||
virtual ~TLVRecordReader() { }
|
||||
|
||||
/**
|
||||
* Overload of the assignment operator for this class
|
||||
* @param[in] other The TLVRecordReader instance to assign
|
||||
*/
|
||||
TLVRecordReader& operator=(const TLVRecordReader& other)
|
||||
{
|
||||
m_RecordCount = other.m_RecordCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first TLV record out of a byte stream
|
||||
* @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
|
||||
* @param[in] tlvDataLen The TLV data byte stream length
|
||||
* @return An instance of type TLVRecordType that contains the first TLV record. If tlvDataBasePtr is NULL or
|
||||
* tlvDataLen is zero the returned TLVRecordType instance will be logically NULL, meaning TLVRecordType.isNull() will
|
||||
* return true
|
||||
*/
|
||||
TLVRecordType getFirstTLVRecord(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
|
||||
{
|
||||
// In most cases tlvDataLen is not zero and the size is correct therefore the overhead is not significant if the checks will be done later
|
||||
TLVRecordType resRec(tlvDataBasePtr); // for NRVO optimization
|
||||
|
||||
// check if there are records at all and the total size is not zero
|
||||
if (tlvDataLen == 0 || resRec.getTotalSize() == 0)
|
||||
resRec.assign(NULL);
|
||||
|
||||
return resRec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a TLV record that follows a given TLV record in a byte stream
|
||||
* @param[in] record A given TLV record
|
||||
* @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
|
||||
* @param[in] tlvDataLen The TLV data byte stream length
|
||||
* @return An instance of type TLVRecordType that wraps the record following the record given as input. If the
|
||||
* input record.isNull() is true or if the next record is out of bounds of the byte stream, a logical NULL instance
|
||||
* of TLVRecordType will be returned, meaning TLVRecordType.isNull() will return true
|
||||
*/
|
||||
TLVRecordType getNextTLVRecord(TLVRecordType& record, uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
|
||||
{
|
||||
TLVRecordType resRec(NULL); // for NRVO optimization
|
||||
|
||||
if (record.isNull())
|
||||
return resRec;
|
||||
|
||||
// record pointer is out-bounds of the TLV records memory
|
||||
if ((record.getRecordBasePtr() - tlvDataBasePtr) < 0)
|
||||
return resRec;
|
||||
|
||||
// record pointer is out-bounds of the TLV records memory
|
||||
if (record.getRecordBasePtr() - tlvDataBasePtr + (int)record.getTotalSize() >= (int)tlvDataLen)
|
||||
return resRec;
|
||||
|
||||
resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
|
||||
if (resRec.getTotalSize() == 0)
|
||||
resRec.assign(NULL);
|
||||
|
||||
return resRec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the first TLV record that corresponds to a given record type (the 'T' in __Type__-Length-Value)
|
||||
* @param[in] recordType The record type to search for
|
||||
* @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
|
||||
* @param[in] tlvDataLen The TLV data byte stream length
|
||||
* @return An instance of type TLVRecordType that contains the result record. If record was not found a logical
|
||||
* NULL instance of TLVRecordType will be returned, meaning TLVRecordType.isNull() will return true
|
||||
*/
|
||||
TLVRecordType getTLVRecord(uint32_t recordType, uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
|
||||
{
|
||||
TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
|
||||
while (!curRec.isNull())
|
||||
{
|
||||
if (curRec.getType() == recordType)
|
||||
{
|
||||
return curRec;
|
||||
}
|
||||
|
||||
curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
|
||||
}
|
||||
|
||||
curRec.assign(NULL);
|
||||
return curRec; // for NRVO optimization
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TLV record count in a given TLV data byte stream. For efficiency purposes the count is being cached
|
||||
* so only the first call to this method will go over all the TLV records, while all consequent calls will return
|
||||
* the cached number. This implies that if there is a change in the number of records, it's the user's responsibility
|
||||
* to call changeTLVRecordCount() with the record count change
|
||||
* @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
|
||||
* @param[in] tlvDataLen The TLV data byte stream length
|
||||
* @return The TLV record count
|
||||
*/
|
||||
size_t getTLVRecordCount(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
|
||||
{
|
||||
if (m_RecordCount != (size_t)-1)
|
||||
return m_RecordCount;
|
||||
|
||||
m_RecordCount = 0;
|
||||
TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
|
||||
while (!curRec.isNull())
|
||||
{
|
||||
m_RecordCount++;
|
||||
curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
|
||||
}
|
||||
|
||||
return m_RecordCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* As described in getTLVRecordCount(), the TLV record count is being cached for efficiency purposes. So if the
|
||||
* number of TLV records change, it's the user's responsibility to call this method with the number of TLV records
|
||||
* being added or removed. If records were added the change should be a positive number, or a negative number
|
||||
* if records were removed
|
||||
* @param[in] changedBy Number of records that were added or removed
|
||||
*/
|
||||
void changeTLVRecordCount(int changedBy) { if (m_RecordCount != (size_t)-1) m_RecordCount += changedBy; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class TLVRecordBuilder
|
||||
* A base class for building Type-Length-Value (TLV) records. This builder receives the record parameters in its c'tor,
|
||||
* builds the record raw buffer and provides a method to build a TLVRecord object out of it. Please notice this is
|
||||
* a base class that lacks the capability of actually building TLVRecord objects and also cannot be instantiated. The
|
||||
* reason for that is that different protocols build TLV records in different ways, so these missing capabilities will
|
||||
* be implemented by the derived classes which are specific to each protocol. This class only provides the common
|
||||
* infrastructure that will be used by them
|
||||
*/
|
||||
class TLVRecordBuilder
|
||||
{
|
||||
protected:
|
||||
|
||||
TLVRecordBuilder();
|
||||
|
||||
TLVRecordBuilder(uint32_t recType, const uint8_t* recValue, uint8_t recValueLen);
|
||||
|
||||
TLVRecordBuilder(uint32_t recType, uint8_t recValue);
|
||||
|
||||
TLVRecordBuilder(uint32_t recType, uint16_t recValue);
|
||||
|
||||
TLVRecordBuilder(uint32_t recType, uint32_t recValue);
|
||||
|
||||
TLVRecordBuilder(uint32_t recType, const IPv4Address& recValue);
|
||||
|
||||
TLVRecordBuilder(uint32_t recType, const std::string& recValue, bool valueIsHexString = false);
|
||||
|
||||
TLVRecordBuilder(const TLVRecordBuilder& other);
|
||||
|
||||
TLVRecordBuilder& operator=(const TLVRecordBuilder& other);
|
||||
|
||||
virtual ~TLVRecordBuilder();
|
||||
|
||||
void init(uint32_t recType, const uint8_t* recValue, size_t recValueLen);
|
||||
|
||||
uint8_t* m_RecValue;
|
||||
size_t m_RecValueLen;
|
||||
uint32_t m_RecType;
|
||||
|
||||
private:
|
||||
|
||||
void copyData(const TLVRecordBuilder& other);
|
||||
};
|
||||
}
|
||||
#endif // PACKETPP_TLV_DATA
|
||||
71
pcappp/include/pcapplusplus/TablePrinter.h
Normal file
71
pcappp/include/pcapplusplus/TablePrinter.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <vector>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
/**
|
||||
* A class for printing tables in command-line
|
||||
*/
|
||||
class TablePrinter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* C'tor - get column names and column widths
|
||||
* @param[in] columnNames A vector of strings containing column names
|
||||
* @param[in] columnWidths A vector of integers containing column widths
|
||||
*/
|
||||
TablePrinter(std::vector<std::string> columnNames, std::vector<int> columnWidths);
|
||||
|
||||
/**
|
||||
* A d'tor for this class. Closes the table if not closed
|
||||
*/
|
||||
virtual ~TablePrinter();
|
||||
|
||||
/**
|
||||
* Print a single row by providing a single string containing all values delimited by a specified character.
|
||||
* For example: if specified delimiter is '|' and there are 3 columns an example input can be:
|
||||
* "value for column1|value for column2|value for column3"
|
||||
* @param[in] values A string delimited by a specified delimiter that contains values for all columns
|
||||
* @param[in] delimiter A delimiter that separates between values of different columns in the values string
|
||||
* @return True if row was printed successfully or false otherwise (in any case of error an appropriate message
|
||||
* will be printed to log)
|
||||
*/
|
||||
bool printRow(std::string values, char delimiter);
|
||||
|
||||
/**
|
||||
* Print a single row
|
||||
* @param[in] values A vector of strings containing values for all columns
|
||||
* @return True if row was printed successfully or false otherwise (in any case of error an appropriate message
|
||||
* will be printed to log)
|
||||
*/
|
||||
bool printRow(std::vector<std::string> values);
|
||||
|
||||
/**
|
||||
* Print a separator line
|
||||
*/
|
||||
void printSeparator();
|
||||
|
||||
/**
|
||||
* Close the table - should be called after all rows were printed. Calling this method is not a must as it's called
|
||||
* in the class d'tor
|
||||
*/
|
||||
void closeTable();
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_ColumnNames;
|
||||
std::vector<int> m_ColumnWidths;
|
||||
bool m_FirstRow;
|
||||
bool m_TableClosed;
|
||||
|
||||
/**
|
||||
* Print the table headline
|
||||
*/
|
||||
void printHeadline();
|
||||
};
|
||||
|
||||
}
|
||||
506
pcappp/include/pcapplusplus/TcpLayer.h
Normal file
506
pcappp/include/pcapplusplus/TcpLayer.h
Normal file
@@ -0,0 +1,506 @@
|
||||
#ifndef PACKETPP_TCP_LAYER
|
||||
#define PACKETPP_TCP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "TLVData.h"
|
||||
#include <string.h>
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct tcphdr
|
||||
* Represents an TCP protocol header
|
||||
*/
|
||||
#pragma pack(push,1)
|
||||
struct tcphdr
|
||||
{
|
||||
/** Source TCP port */
|
||||
uint16_t portSrc;
|
||||
/** Destination TCP port */
|
||||
uint16_t portDst;
|
||||
/** Sequence number */
|
||||
uint32_t sequenceNumber;
|
||||
/** Acknowledgment number */
|
||||
uint32_t ackNumber;
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
uint16_t reserved:4,
|
||||
/** Specifies the size of the TCP header in 32-bit words */
|
||||
dataOffset:4,
|
||||
/** FIN flag */
|
||||
finFlag:1,
|
||||
/** SYN flag */
|
||||
synFlag:1,
|
||||
/** RST flag */
|
||||
rstFlag:1,
|
||||
/** PSH flag */
|
||||
pshFlag:1,
|
||||
/** ACK flag */
|
||||
ackFlag:1,
|
||||
/** URG flag */
|
||||
urgFlag:1,
|
||||
/** ECE flag */
|
||||
eceFlag:1,
|
||||
/** CWR flag */
|
||||
cwrFlag:1;
|
||||
#elif (BYTE_ORDER == BIG_ENDIAN)
|
||||
/** Specifies the size of the TCP header in 32-bit words */
|
||||
uint16_t dataOffset:4,
|
||||
reserved:4,
|
||||
/** CWR flag */
|
||||
cwrFlag:1,
|
||||
/** ECE flag */
|
||||
eceFlag:1,
|
||||
/** URG flag */
|
||||
urgFlag:1,
|
||||
/** ACK flag */
|
||||
ackFlag:1,
|
||||
/** PSH flag */
|
||||
pshFlag:1,
|
||||
/** RST flag */
|
||||
rstFlag:1,
|
||||
/** SYN flag */
|
||||
synFlag:1,
|
||||
/** FIN flag */
|
||||
finFlag:1;
|
||||
#else
|
||||
#error "Endian is not LE nor BE..."
|
||||
#endif
|
||||
/** The size of the receive window, which specifies the number of window size units (by default, bytes) */
|
||||
uint16_t windowSize;
|
||||
/** The 16-bit checksum field is used for error-checking of the header and data */
|
||||
uint16_t headerChecksum;
|
||||
/** If the URG flag (@ref tcphdr#urgFlag) is set, then this 16-bit field is an offset from the sequence number indicating the last urgent data byte */
|
||||
uint16_t urgentPointer;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* TCP options types
|
||||
*/
|
||||
enum TcpOptionType
|
||||
{
|
||||
/** Padding */
|
||||
PCPP_TCPOPT_NOP = 1,
|
||||
/** End of options */
|
||||
PCPP_TCPOPT_EOL = 0,
|
||||
/** Segment size negotiating */
|
||||
TCPOPT_MSS = 2,
|
||||
/** Window scaling */
|
||||
PCPP_TCPOPT_WINDOW = 3,
|
||||
/** SACK Permitted */
|
||||
TCPOPT_SACK_PERM = 4,
|
||||
/** SACK Block */
|
||||
PCPP_TCPOPT_SACK = 5,
|
||||
/** Echo (obsoleted by option ::PCPP_TCPOPT_TIMESTAMP) */
|
||||
TCPOPT_ECHO = 6,
|
||||
/** Echo Reply (obsoleted by option ::PCPP_TCPOPT_TIMESTAMP) */
|
||||
TCPOPT_ECHOREPLY = 7,
|
||||
/** TCP Timestamps */
|
||||
PCPP_TCPOPT_TIMESTAMP = 8,
|
||||
/** CC (obsolete) */
|
||||
TCPOPT_CC = 11,
|
||||
/** CC.NEW (obsolete) */
|
||||
TCPOPT_CCNEW = 12,
|
||||
/** CC.ECHO(obsolete) */
|
||||
TCPOPT_CCECHO = 13,
|
||||
/** MD5 Signature Option */
|
||||
TCPOPT_MD5 = 19,
|
||||
/** Multipath TCP */
|
||||
TCPOPT_MPTCP = 0x1e,
|
||||
/** SCPS Capabilities */
|
||||
TCPOPT_SCPS = 20,
|
||||
/** SCPS SNACK */
|
||||
TCPOPT_SNACK = 21,
|
||||
/** SCPS Record Boundary */
|
||||
TCPOPT_RECBOUND = 22,
|
||||
/** SCPS Corruption Experienced */
|
||||
TCPOPT_CORREXP = 23,
|
||||
/** Quick-Start Response */
|
||||
TCPOPT_QS = 27,
|
||||
/** User Timeout Option (also, other known unauthorized use) */
|
||||
TCPOPT_USER_TO = 28,
|
||||
/** RFC3692-style Experiment 1 (also improperly used for shipping products) */
|
||||
TCPOPT_EXP_FD = 0xfd,
|
||||
/** RFC3692-style Experiment 2 (also improperly used for shipping products) */
|
||||
TCPOPT_EXP_FE = 0xfe,
|
||||
/** Riverbed probe option, non IANA registered option number */
|
||||
TCPOPT_RVBD_PROBE = 76,
|
||||
/** Riverbed transparency option, non IANA registered option number */
|
||||
TCPOPT_RVBD_TRPY = 78,
|
||||
/** Unknown option */
|
||||
TCPOPT_Unknown = 255
|
||||
};
|
||||
|
||||
|
||||
// TCP option lengths
|
||||
|
||||
/** pcpp::PCPP_TCPOPT_NOP length */
|
||||
#define PCPP_TCPOLEN_NOP 1
|
||||
/** pcpp::PCPP_TCPOPT_EOL length */
|
||||
#define PCPP_TCPOLEN_EOL 1
|
||||
/** pcpp::TCPOPT_MSS length */
|
||||
#define PCPP_TCPOLEN_MSS 4
|
||||
/** pcpp::PCPP_TCPOPT_WINDOW length */
|
||||
#define PCPP_TCPOLEN_WINDOW 3
|
||||
/** pcpp::TCPOPT_SACK_PERM length */
|
||||
#define PCPP_TCPOLEN_SACK_PERM 2
|
||||
/** pcpp::PCPP_TCPOPT_SACK length */
|
||||
#define PCPP_TCPOLEN_SACK_MIN 2
|
||||
/** pcpp::TCPOPT_ECHO length */
|
||||
#define PCPP_TCPOLEN_ECHO 6
|
||||
/** pcpp::TCPOPT_ECHOREPLY length */
|
||||
#define PCPP_TCPOLEN_ECHOREPLY 6
|
||||
/** pcpp::PCPP_TCPOPT_TIMESTAMP length */
|
||||
#define PCPP_TCPOLEN_TIMESTAMP 10
|
||||
/** pcpp::TCPOPT_CC length */
|
||||
#define PCPP_TCPOLEN_CC 6
|
||||
/** pcpp::TCPOPT_CCNEW length */
|
||||
#define PCPP_TCPOLEN_CCNEW 6
|
||||
/** pcpp::TCPOPT_CCECHO length */
|
||||
#define PCPP_TCPOLEN_CCECHO 6
|
||||
/** pcpp::TCPOPT_MD5 length */
|
||||
#define PCPP_TCPOLEN_MD5 18
|
||||
/** pcpp::TCPOPT_MPTCP length */
|
||||
#define PCPP_TCPOLEN_MPTCP_MIN 8
|
||||
/** pcpp::TCPOPT_SCPS length */
|
||||
#define PCPP_TCPOLEN_SCPS 4
|
||||
/** pcpp::TCPOPT_SNACK length */
|
||||
#define PCPP_TCPOLEN_SNACK 6
|
||||
/** pcpp::TCPOPT_RECBOUND length */
|
||||
#define PCPP_TCPOLEN_RECBOUND 2
|
||||
/** pcpp::TCPOPT_CORREXP length */
|
||||
#define PCPP_TCPOLEN_CORREXP 2
|
||||
/** pcpp::TCPOPT_QS length */
|
||||
#define PCPP_TCPOLEN_QS 8
|
||||
/** pcpp::TCPOPT_USER_TO length */
|
||||
#define PCPP_TCPOLEN_USER_TO 4
|
||||
/** pcpp::TCPOPT_RVBD_PROBE length */
|
||||
#define PCPP_TCPOLEN_RVBD_PROBE_MIN 3
|
||||
/** pcpp::TCPOPT_RVBD_TRPY length */
|
||||
#define PCPP_TCPOLEN_RVBD_TRPY_MIN 16
|
||||
/** pcpp::TCPOPT_EXP_FD and pcpp::TCPOPT_EXP_FE length */
|
||||
#define PCPP_TCPOLEN_EXP_MIN 2
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpOption
|
||||
* A wrapper class for TCP options. This class does not create or modify TCP option records, but rather
|
||||
* serves as a wrapper and provides useful methods for retrieving data from them
|
||||
*/
|
||||
class TcpOption : public TLVRecord<uint8_t, uint8_t>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* A c'tor for this class that gets a pointer to the option raw data (byte array)
|
||||
* @param[in] optionRawData A pointer to the TCP option raw data
|
||||
*/
|
||||
TcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
|
||||
|
||||
/**
|
||||
* A d'tor for this class, currently does nothing
|
||||
*/
|
||||
~TcpOption() { }
|
||||
|
||||
/**
|
||||
* @return TCP option type casted as pcpp::TcpOptionType enum. If the data is null a value
|
||||
* of ::TCPOPT_Unknown is returned
|
||||
*/
|
||||
TcpOptionType getTcpOptionType() const
|
||||
{
|
||||
if (m_Data == NULL)
|
||||
return TCPOPT_Unknown;
|
||||
|
||||
return (TcpOptionType)m_Data->recordType;
|
||||
}
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
if (m_Data == NULL)
|
||||
return (size_t)0;
|
||||
|
||||
if (m_Data->recordType == (uint8_t)PCPP_TCPOPT_NOP || m_Data->recordType == (uint8_t)PCPP_TCPOPT_EOL)
|
||||
return sizeof(uint8_t);
|
||||
|
||||
return (size_t)m_Data->recordLen;
|
||||
}
|
||||
|
||||
size_t getDataSize() const
|
||||
{
|
||||
if (m_Data == NULL)
|
||||
return 0;
|
||||
|
||||
if (m_Data->recordType == (uint8_t)PCPP_TCPOPT_NOP || m_Data->recordType == (uint8_t)PCPP_TCPOPT_EOL)
|
||||
return (size_t)0;
|
||||
|
||||
return (size_t)m_Data->recordLen - (2*sizeof(uint8_t));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpOptionBuilder
|
||||
* A class for building TCP option records. This builder receives the TCP option parameters in its c'tor,
|
||||
* builds the TCP option raw buffer and provides a build() method to get a TcpOption object out of it
|
||||
*/
|
||||
class TcpOptionBuilder : public TLVRecordBuilder
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum to describe NOP and EOL TCP options. Used in one of this class's c'tors
|
||||
*/
|
||||
enum NopEolOptionTypes
|
||||
{
|
||||
/** NOP TCP option */
|
||||
NOP,
|
||||
/** EOL TCP option */
|
||||
EOL
|
||||
};
|
||||
|
||||
/**
|
||||
* A c'tor for building TCP options which their value is a byte array. The TcpOption object can be later
|
||||
* retrieved by calling build()
|
||||
* @param[in] optionType TCP option type
|
||||
* @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way.
|
||||
* @param[in] optionValueLen Option value length in bytes
|
||||
*/
|
||||
TcpOptionBuilder(TcpOptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) {}
|
||||
|
||||
/**
|
||||
* A c'tor for building TCP options which have a 1-byte value. The TcpOption object can be later retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType TCP option type
|
||||
* @param[in] optionValue A 1-byte option value
|
||||
*/
|
||||
TcpOptionBuilder(TcpOptionType optionType, uint8_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) {}
|
||||
|
||||
/**
|
||||
* A c'tor for building TCP options which have a 2-byte value. The TcpOption object can be later retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType TCP option type
|
||||
* @param[in] optionValue A 2-byte option value
|
||||
*/
|
||||
TcpOptionBuilder(TcpOptionType optionType, uint16_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) {}
|
||||
|
||||
/**
|
||||
* A c'tor for building TCP options which have a 4-byte value. The TcpOption object can be later retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType TCP option type
|
||||
* @param[in] optionValue A 4-byte option value
|
||||
*/
|
||||
TcpOptionBuilder(TcpOptionType optionType, uint32_t optionValue) :
|
||||
TLVRecordBuilder((uint8_t)optionType, optionValue) {}
|
||||
|
||||
/**
|
||||
* A c'tor for building TCP NOP and EOL options. These option types are special in that they contain only 1 byte
|
||||
* which is the TCP option type (NOP or EOL). The TcpOption object can be later retrieved
|
||||
* by calling build()
|
||||
* @param[in] optionType An enum value indicating which option type to build (NOP or EOL)
|
||||
*/
|
||||
TcpOptionBuilder(NopEolOptionTypes optionType);
|
||||
|
||||
/**
|
||||
* Build the TcpOption object out of the parameters defined in the c'tor
|
||||
* @return The TcpOption object
|
||||
*/
|
||||
TcpOption build() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpLayer
|
||||
* Represents a TCP (Transmission Control Protocol) protocol layer
|
||||
*/
|
||||
class TcpLayer : public Layer
|
||||
{
|
||||
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 tcphdr)
|
||||
* @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
|
||||
*/
|
||||
TcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new TCP header with zero TCP options
|
||||
*/
|
||||
TcpLayer();
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new TCP header with source port and destination port and zero TCP options
|
||||
* @param[in] portSrc Source port
|
||||
* @param[in] portDst Destination port
|
||||
*/
|
||||
TcpLayer(uint16_t portSrc, uint16_t portDst);
|
||||
|
||||
~TcpLayer() {}
|
||||
|
||||
/**
|
||||
* A copy constructor that copy the entire header from the other TcpLayer (including TCP options)
|
||||
*/
|
||||
TcpLayer(const TcpLayer& other);
|
||||
|
||||
/**
|
||||
* An assignment operator that first delete all data from current layer and then copy the entire header from the other TcpLayer (including TCP options)
|
||||
*/
|
||||
TcpLayer& operator=(const TcpLayer& other);
|
||||
|
||||
/**
|
||||
* Get a pointer to the TCP header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref tcphdr
|
||||
*/
|
||||
tcphdr* getTcpHeader() const { return (tcphdr*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return TCP source port
|
||||
*/
|
||||
uint16_t getSrcPort() const;
|
||||
|
||||
/**
|
||||
* @return TCP destination port
|
||||
*/
|
||||
uint16_t getDstPort() const;
|
||||
|
||||
/**
|
||||
* Get a TCP option by type
|
||||
* @param[in] option TCP option type to retrieve
|
||||
* @return An TcpOption object that contains the first option that matches this type, or logical NULL
|
||||
* (TcpOption#isNull() == true) if no such option found
|
||||
*/
|
||||
TcpOption getTcpOption(TcpOptionType option) const;
|
||||
|
||||
/**
|
||||
* @return The first TCP option in the packet. If the current layer contains no options the returned value will contain
|
||||
* a logical NULL (TcpOption#isNull() == true)
|
||||
*/
|
||||
TcpOption getFirstTcpOption() const;
|
||||
|
||||
/**
|
||||
* Get the TCP option that comes after a given option. If the given option was the last one, the
|
||||
* returned value will contain a logical NULL (TcpOption#isNull() == true)
|
||||
* @param[in] tcpOption A TCP option object that exists in the current layer
|
||||
* @return A TcpOption object that contains the TCP option data that comes next, or logical NULL if the given
|
||||
* TCP option: (1) was the last one; or (2) contains a logical NULL; or (3) doesn't belong to this packet
|
||||
*/
|
||||
TcpOption getNextTcpOption(TcpOption& tcpOption) const;
|
||||
|
||||
/**
|
||||
* @return The number of TCP options in this layer
|
||||
*/
|
||||
size_t getTcpOptionCount() const;
|
||||
|
||||
/**
|
||||
* Add a new TCP option at the end of the layer (after the last TCP option)
|
||||
* @param[in] optionBuilder A TcpOptionBuilder object that contains the TCP option data to be added
|
||||
* @return A TcpOption object that contains the newly added TCP option data or logical NULL
|
||||
* (TcpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
|
||||
* printed to log
|
||||
*/
|
||||
TcpOption addTcpOption(const TcpOptionBuilder& optionBuilder);
|
||||
|
||||
/**
|
||||
* Add a new TCP option after an existing one
|
||||
* @param[in] optionBuilder A TcpOptionBuilder object that contains the requested TCP option data to be added
|
||||
* @param[in] prevOptionType The TCP option which the newly added option should come after. This is an optional parameter which
|
||||
* gets a default value of ::TCPOPT_Unknown if omitted, which means the new option will be added as the first option in the layer
|
||||
* @return A TcpOption object containing the newly added TCP option data or logical NULL
|
||||
* (TcpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
|
||||
* printed to log
|
||||
*/
|
||||
TcpOption addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType = TCPOPT_Unknown);
|
||||
|
||||
/**
|
||||
* Remove an existing TCP option from the layer. TCP option is found by type
|
||||
* @param[in] optionType The TCP option type to remove
|
||||
* @return True if TCP option was removed or false if type wasn't found or if removal failed (in each case a proper error
|
||||
* will be written to log)
|
||||
*/
|
||||
bool removeTcpOption(TcpOptionType optionType);
|
||||
|
||||
/**
|
||||
* Remove all TCP options in this layer
|
||||
* @return True if all TCP options were successfully removed or false if removal failed for some reason
|
||||
* (a proper error will be written to log)
|
||||
*/
|
||||
bool removeAllTcpOptions();
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the checksum from header and data and possibly write the result to @ref tcphdr#headerChecksum
|
||||
* @param[in] writeResultToPacket If set to true then checksum result will be written to @ref tcphdr#headerChecksum
|
||||
* @return The checksum result
|
||||
*/
|
||||
uint16_t calculateChecksum(bool writeResultToPacket);
|
||||
|
||||
/**
|
||||
* The static method makes validation of input data
|
||||
* @param[in] data The pointer to the beginning of byte stream of TCP packet
|
||||
* @param[in] dataLen The length of byte stream
|
||||
* @return True if the data is valid and can represent a TCP packet
|
||||
*/
|
||||
static inline bool isDataValid(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of @ref tcphdr + all TCP options
|
||||
*/
|
||||
size_t getHeaderLen() const { return getTcpHeader()->dataOffset*4 ;}
|
||||
|
||||
/**
|
||||
* Calculate @ref tcphdr#headerChecksum field
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; }
|
||||
|
||||
private:
|
||||
|
||||
TLVRecordReader<TcpOption> m_OptionReader;
|
||||
int m_NumOfTrailingBytes;
|
||||
|
||||
void initLayer();
|
||||
uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(tcphdr); }
|
||||
TcpOption addTcpOptionAt(const TcpOptionBuilder& optionBuilder, int offset);
|
||||
void adjustTcpOptionTrailer(size_t totalOptSize);
|
||||
void copyLayerData(const TcpLayer& other);
|
||||
};
|
||||
|
||||
|
||||
// implementation of inline methods
|
||||
|
||||
bool TcpLayer::isDataValid(const uint8_t* data, size_t dataLen)
|
||||
{
|
||||
const tcphdr* hdr = reinterpret_cast<const tcphdr*>(data);
|
||||
return dataLen >= sizeof(tcphdr)
|
||||
&& hdr->dataOffset >= 5 /* the minimum TCP header size */
|
||||
&& dataLen >= hdr->dataOffset * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_TCP_LAYER */
|
||||
460
pcappp/include/pcapplusplus/TcpReassembly.h
Normal file
460
pcappp/include/pcapplusplus/TcpReassembly.h
Normal file
@@ -0,0 +1,460 @@
|
||||
#ifndef PACKETPP_TCP_REASSEMBLY
|
||||
#define PACKETPP_TCP_REASSEMBLY
|
||||
|
||||
#include "Packet.h"
|
||||
#include "IpAddress.h"
|
||||
#include "PointerVector.h"
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This is an implementation of TCP reassembly logic, which means reassembly of TCP messages spanning multiple TCP segments (or packets).<BR>
|
||||
* This logic can be useful in analyzing messages for a large number of protocols implemented on top of TCP including HTTP, SSL/TLS, FTP and many many more.
|
||||
*
|
||||
* __General Features:__
|
||||
* - Manage multiple TCP connections under one pcpp#TcpReassembly instance
|
||||
* - Support TCP retransmission
|
||||
* - Support out-of-order packets
|
||||
* - Support missing TCP data
|
||||
* - TCP connections can end "naturally" (by FIN/RST packets) or manually by the user
|
||||
* - Support callbacks for new TCP data, connection start and connection end
|
||||
*
|
||||
* __Logic Description:__
|
||||
* - The user creates an instance of the pcpp#TcpReassembly class
|
||||
* - Then the user starts feeding it with TCP packets
|
||||
* - The pcpp#TcpReassembly instance manages all TCP connections from the packets it's being fed. For each connection it manages its 2 sides (A->B and B->A)
|
||||
* - When a packet arrives, it is first classified to a certain TCP connection
|
||||
* - Then it is classified to a certain side of the TCP connection
|
||||
* - Then the pcpp#TcpReassembly logic tries to understand if the data in this packet is the expected data (sequence-wise) and if it's new (e.g isn't a retransmission)
|
||||
* - If the packet data matches these criteria a callback is being invoked. This callback is supplied by the user in the creation of the pcpp#TcpReassembly instance. This callback contains
|
||||
* the new data (of course), but also information about the connection (5-tuple, 4-byte hash key describing the connection, etc.) and also a pointer to a "user cookie", meaning a pointer to
|
||||
* a structure provided by the user during the creation of the pcpp#TcpReassembly instance
|
||||
* - If the data in this packet isn't new, it's being ignored
|
||||
* - If the data in this packet isn't expected (meaning this packet came out-of-order), then the data is being queued internally and will be sent to the user when its turn arrives
|
||||
* (meaning, after the data before arrives)
|
||||
* - If the missing data doesn't arrive until a new message from the other side of the connection arrives or until the connection ends - this will be considered as missing data and the
|
||||
* queued data will be sent to the user, but the string "[X bytes missing]" will be added to the message sent in the callback
|
||||
* - pcpp#TcpReassembly supports 2 more callbacks - one is invoked when a new TCP connection is first seen and the other when it's ended (either by a FIN/RST packet or manually by the user).
|
||||
* Both of these callbacks contain data about the connection (5-tuple, 4-byte hash key describing the connection, etc.) and also a pointer to a "user cookie", meaning a pointer to a
|
||||
* structure provided by the user during the creation of the pcpp#TcpReassembly instance. The end connection callback also provides the reason for closing it ("naturally" or manually)
|
||||
*
|
||||
* __Basic Usage and APIs:__
|
||||
* - pcpp#TcpReassembly c'tor - Create an instance, provide the callbacks and the user cookie to the instance
|
||||
* - pcpp#TcpReassembly#reassemblePacket() - Feed pcpp#TcpReassembly instance with packets
|
||||
* - pcpp#TcpReassembly#closeConnection() - Manually close a connection by a flow key
|
||||
* - pcpp#TcpReassembly#closeAllConnections() - Manually close all currently opened connections
|
||||
* - pcpp#TcpReassembly#OnTcpMessageReady callback - Invoked when new data arrives on a certain connection. Contains the new data as well as connection data (5-tuple, flow key)
|
||||
* - pcpp#TcpReassembly#OnTcpConnectionStart callback - Invoked when a new connection is identified
|
||||
* - pcpp#TcpReassembly#OnTcpConnectionEnd callback - Invoked when a connection ends (either by FIN/RST or manually by the user)
|
||||
*
|
||||
* __Additional information:__
|
||||
* When the connection is closed the information is not being deleted from memory immediately. There is a delay between these moments. Existence of this delay is caused by two reasons:
|
||||
* - pcpp#TcpReassembly#reassemblePacket() should detect the packets that arrive after the FIN packet has been received
|
||||
* - the user can use the information about connections managed by pcpp#TcpReassembly instance. Following methods are used for this purpose: pcpp#TcpReassembly#getConnectionInformation and pcpp#TcpReassembly#isConnectionOpen.
|
||||
* Cleaning of memory can be performed automatically (the default behavior) by pcpp#TcpReassembly#reassemblePacket() or manually by calling pcpp#TcpReassembly#purgeClosedConnections in the user code.
|
||||
* Automatic cleaning is performed once per second.
|
||||
*
|
||||
* The struct pcpp#TcpReassemblyConfiguration allows to setup the parameters of cleanup. Following parameters are supported:
|
||||
* - pcpp#TcpReassemblyConfiguration#doNotRemoveConnInfo - if this member is set to false the automatic cleanup mode is applied
|
||||
* - pcpp#TcpReassemblyConfiguration#closedConnectionDelay - the value of delay expressed in seconds. The minimum value is 1
|
||||
* - pcpp#TcpReassemblyConfiguration#maxNumToClean - to avoid performance overhead when the cleanup is being performed, this parameter is used. It defines the maximum number of items to be removed per one call of pcpp#TcpReassembly#purgeClosedConnections
|
||||
* - pcpp#TcpReassemblyConfiguration#maxOutOfOrderFragments - the maximum number of unmatched fragments to keep per flow before missed fragments are considered lost. A value of 0 means unlimited
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace pcpp
|
||||
* @brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct ConnectionData
|
||||
* Represents basic TCP/UDP + IP connection data
|
||||
*/
|
||||
struct ConnectionData
|
||||
{
|
||||
/** Source IP address */
|
||||
IPAddress srcIP;
|
||||
/** Destination IP address */
|
||||
IPAddress dstIP;
|
||||
/** Source TCP/UDP port */
|
||||
uint16_t srcPort;
|
||||
/** Destination TCP/UDP port */
|
||||
uint16_t dstPort;
|
||||
/** A 4-byte hash key representing the connection */
|
||||
uint32_t flowKey;
|
||||
/** Start TimeStamp of the connection */
|
||||
timeval startTime;
|
||||
/** End TimeStamp of the connection */
|
||||
timeval endTime;
|
||||
|
||||
/**
|
||||
* A c'tor for this struct that basically zeros all members
|
||||
*/
|
||||
ConnectionData() : srcPort(0), dstPort(0), flowKey(0), startTime(), endTime() {}
|
||||
|
||||
/**
|
||||
* Set startTime of Connection
|
||||
* @param[in] startTime integer value
|
||||
*/
|
||||
void setStartTime(const timeval &startTime) { this->startTime = startTime; }
|
||||
|
||||
/**
|
||||
* Set endTime of Connection
|
||||
* @param[in] endTime integer value
|
||||
*/
|
||||
void setEndTime(const timeval &endTime) { this->endTime = endTime; }
|
||||
};
|
||||
|
||||
|
||||
class TcpReassembly;
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpStreamData
|
||||
* When following a TCP connection each packet may contain a piece of the data transferred between the client and the server. This class represents these pieces: each instance of it
|
||||
* contains a piece of data, usually extracted from a single packet, as well as information about the connection
|
||||
*/
|
||||
class TcpStreamData
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A c'tor for this class that get data from outside and set the internal members
|
||||
* @param[in] tcpData A pointer to buffer containing the TCP data piece
|
||||
* @param[in] tcpDataLength The length of the buffer
|
||||
* @param[in] missingBytes The number of missing bytes due to packet loss.
|
||||
* @param[in] connData TCP connection information for this TCP data
|
||||
* @param[in] timestamp when this packet was received
|
||||
*/
|
||||
TcpStreamData(const uint8_t* tcpData, size_t tcpDataLength, size_t missingBytes, const ConnectionData& connData, timeval timestamp)
|
||||
: m_Data(tcpData), m_DataLen(tcpDataLength), m_MissingBytes(missingBytes), m_Connection(connData), m_Timestamp(timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the data buffer
|
||||
* @return A pointer to the buffer
|
||||
*/
|
||||
const uint8_t* getData() const { return m_Data; }
|
||||
|
||||
/**
|
||||
* A getter for buffer length
|
||||
* @return Buffer length
|
||||
*/
|
||||
size_t getDataLength() const { return m_DataLen; }
|
||||
|
||||
/**
|
||||
* A getter for missing byte count due to packet loss.
|
||||
* @return Missing byte count
|
||||
*/
|
||||
size_t getMissingByteCount() const { return m_MissingBytes; }
|
||||
|
||||
/**
|
||||
* Determine if bytes are missing. getMissingByteCount can be called to determine the number of missing bytes.
|
||||
* @return true if bytes are missing.
|
||||
*/
|
||||
bool isBytesMissing() const { return getMissingByteCount() > 0; }
|
||||
|
||||
/**
|
||||
* A getter for the connection data
|
||||
* @return The const reference to connection data
|
||||
*/
|
||||
const ConnectionData& getConnectionData() const { return m_Connection; }
|
||||
|
||||
/**
|
||||
* A getter for the timestamp of this packet
|
||||
* @return The const timeval object with timestamp of this packet
|
||||
*/
|
||||
timeval getTimeStamp() const { return m_Timestamp; }
|
||||
|
||||
private:
|
||||
const uint8_t* m_Data;
|
||||
size_t m_DataLen;
|
||||
size_t m_MissingBytes;
|
||||
const ConnectionData& m_Connection;
|
||||
timeval m_Timestamp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct TcpReassemblyConfiguration
|
||||
* A structure for configuring the TcpReassembly class
|
||||
*/
|
||||
struct TcpReassemblyConfiguration
|
||||
{
|
||||
/** The flag indicating whether to remove the connection data after a connection is closed */
|
||||
bool removeConnInfo;
|
||||
|
||||
/** How long the closed connections will not be cleaned up. The value is expressed in seconds. If the value is set to 0 then TcpReassembly should use the default value.
|
||||
* This parameter is only relevant if removeConnInfo is equal to true.
|
||||
*/
|
||||
uint32_t closedConnectionDelay;
|
||||
|
||||
/** The maximum number of items to be cleaned up per one call of purgeClosedConnections. If the value is set to 0 then TcpReassembly should use the default value.
|
||||
* This parameter is only relevant if removeConnInfo is equal to true.
|
||||
*/
|
||||
uint32_t maxNumToClean;
|
||||
|
||||
/** The maximum number of fragments with a non-matching sequence-number to store per connection flow before packets are assumed permanently missed.
|
||||
If the value is 0, TcpReassembly should keep out of order fragments indefinitely, or until a message from the paired side is seen.
|
||||
*/
|
||||
uint32_t maxOutOfOrderFragments;
|
||||
|
||||
/** To enable to clear buffer once packet contains data from a different side than the side seen before
|
||||
*/
|
||||
bool enableBaseBufferClearCondition;
|
||||
|
||||
/**
|
||||
* A c'tor for this struct
|
||||
* @param[in] removeConnInfo The flag indicating whether to remove the connection data after a connection is closed. The default is true
|
||||
* @param[in] closedConnectionDelay How long the closed connections will not be cleaned up. The value is expressed in seconds. If it's set to 0 the default value will be used. The default is 5.
|
||||
* @param[in] maxNumToClean The maximum number of items to be cleaned up per one call of purgeClosedConnections. If it's set to 0 the default value will be used. The default is 30.
|
||||
* @param[in] maxOutOfOrderFragments The maximum number of unmatched fragments to keep per flow before missed fragments are considered lost. The default is unlimited.
|
||||
* @param[in] enableBaseBufferClearCondition To enable to clear buffer once packet contains data from a different side than the side seen before
|
||||
*/
|
||||
TcpReassemblyConfiguration(bool removeConnInfo = true, uint32_t closedConnectionDelay = 5, uint32_t maxNumToClean = 30, uint32_t maxOutOfOrderFragments = 0,
|
||||
bool enableBaseBufferClearCondition = true) : removeConnInfo(removeConnInfo), closedConnectionDelay(closedConnectionDelay), maxNumToClean(maxNumToClean), maxOutOfOrderFragments(maxOutOfOrderFragments), enableBaseBufferClearCondition(enableBaseBufferClearCondition)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class TcpReassembly
|
||||
* A class containing the TCP reassembly logic. Please refer to the documentation at the top of TcpReassembly.h for understanding how to use this class
|
||||
*/
|
||||
class TcpReassembly
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* An enum for connection end reasons
|
||||
*/
|
||||
enum ConnectionEndReason
|
||||
{
|
||||
/** Connection ended because of FIN or RST packet */
|
||||
TcpReassemblyConnectionClosedByFIN_RST,
|
||||
/** Connection ended manually by the user */
|
||||
TcpReassemblyConnectionClosedManually
|
||||
};
|
||||
|
||||
/**
|
||||
* An enum for providing reassembly status for each processed packet
|
||||
*/
|
||||
enum ReassemblyStatus
|
||||
{
|
||||
/**
|
||||
* The processed packet contains valid TCP payload, and its payload is processed by `OnMessageReadyCallback` callback function.
|
||||
* The packet may be:
|
||||
* 1. An in-order TCP packet, meaning `packet_sequence == sequence_expected`.
|
||||
* Note if there's any buffered out-of-order packet waiting for this packet, their associated callbacks are called in this `reassemblePacket` call.
|
||||
* 2. An out-of-order TCP packet which satisfy `packet_sequence < sequence_expected && packet_sequence + packet_payload_length > sequence_expected`.
|
||||
* Note only the new data (the `[sequence_expected, packet_sequence + packet_payload_length]` part ) is processed by `OnMessageReadyCallback` callback function.
|
||||
*/
|
||||
TcpMessageHandled,
|
||||
/**
|
||||
* The processed packet is an out-of-order TCP packet, meaning `packet_sequence > sequence_expected`. It's buffered so no `OnMessageReadyCallback` callback function is called.
|
||||
* The callback function for this packet maybe called LATER, under different circumstances:
|
||||
* 1. When an in-order packet which is right before this packet arrives(case 1 and case 2 described in `TcpMessageHandled` section above).
|
||||
* 2. When a FIN or RST packet arrives, which will clear the buffered out-of-order packets of this side.
|
||||
* If this packet contains "new data", meaning `(packet_sequence <= sequence_expected) && (packet_sequence + packet_payload_length > sequence_expected)`, the new data is processed by `OnMessageReadyCallback` callback.
|
||||
*/
|
||||
OutOfOrderTcpMessageBuffered,
|
||||
/**
|
||||
* The processed packet is a FIN or RST packet with no payload.
|
||||
* Buffered out-of-order packets will be cleared.
|
||||
* If they contain "new data", the new data is processed by `OnMessageReadyCallback` callback.
|
||||
*/
|
||||
FIN_RSTWithNoData,
|
||||
/**
|
||||
* The processed packet is not a SYN/SYNACK/FIN/RST packet and has no payload.
|
||||
* Normally it's just a bare ACK packet.
|
||||
* It's ignored and no callback function is called.
|
||||
*/
|
||||
Ignore_PacketWithNoData,
|
||||
/**
|
||||
* The processed packet comes from a closed flow(an in-order FIN or RST is seen).
|
||||
* It's ignored and no callback function is called.
|
||||
*/
|
||||
Ignore_PacketOfClosedFlow,
|
||||
/**
|
||||
* The processed packet is a restransmission packet with no new data, meaning the `packet_sequence + packet_payload_length < sequence_expected`.
|
||||
* It's ignored and no callback function is called.
|
||||
*/
|
||||
Ignore_Retransimission,
|
||||
/**
|
||||
* The processed packet is not an IP packet.
|
||||
* It's ignored and no callback function is called.
|
||||
*/
|
||||
NonIpPacket,
|
||||
/**
|
||||
* The processed packet is not a TCP packet.
|
||||
* It's ignored and no callback function is called.
|
||||
*/
|
||||
NonTcpPacket,
|
||||
/**
|
||||
* The processed packet does not belong to any known TCP connection.
|
||||
* It's ignored and no callback function is called.
|
||||
* Normally this will be happen.
|
||||
*/
|
||||
Error_PacketDoesNotMatchFlow,
|
||||
};
|
||||
|
||||
/**
|
||||
* The type for storing the connection information
|
||||
*/
|
||||
typedef std::map<uint32_t, ConnectionData> ConnectionInfoList;
|
||||
|
||||
/**
|
||||
* @typedef OnTcpMessageReady
|
||||
* A callback invoked when new data arrives on a connection
|
||||
* @param[in] side The side this data belongs to (MachineA->MachineB or vice versa). The value is 0 or 1 where 0 is the first side seen in the connection and 1 is the second side seen
|
||||
* @param[in] tcpData The TCP data itself + connection information
|
||||
* @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no cookie provided)
|
||||
*/
|
||||
typedef void (*OnTcpMessageReady)(int8_t side, const TcpStreamData& tcpData, void* userCookie);
|
||||
|
||||
/**
|
||||
* @typedef OnTcpConnectionStart
|
||||
* A callback invoked when a new TCP connection is identified (whether it begins with a SYN packet or not)
|
||||
* @param[in] connectionData Connection information
|
||||
* @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no cookie provided)
|
||||
*/
|
||||
typedef void (*OnTcpConnectionStart)(const ConnectionData& connectionData, void* userCookie);
|
||||
|
||||
/**
|
||||
* @typedef OnTcpConnectionEnd
|
||||
* A callback invoked when a TCP connection is terminated, either by a FIN or RST packet or manually by the user
|
||||
* @param[in] connectionData Connection information
|
||||
* @param[in] reason The reason for connection termination: FIN/RST packet or manually by the user
|
||||
* @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no cookie provided)
|
||||
*/
|
||||
typedef void (*OnTcpConnectionEnd)(const ConnectionData& connectionData, ConnectionEndReason reason, void* userCookie);
|
||||
|
||||
/**
|
||||
* A c'tor for this class
|
||||
* @param[in] onMessageReadyCallback The callback to be invoked when new data arrives
|
||||
* @param[in] userCookie A pointer to an object provided by the user. This pointer will be returned when invoking the various callbacks. This parameter is optional, default cookie is NULL
|
||||
* @param[in] onConnectionStartCallback The callback to be invoked when a new connection is identified. This parameter is optional
|
||||
* @param[in] onConnectionEndCallback The callback to be invoked when a new connection is terminated (either by a FIN/RST packet or manually by the user). This parameter is optional
|
||||
* @param[in] config Optional parameter for defining special configuration parameters. If not set the default parameters will be set
|
||||
*/
|
||||
TcpReassembly(OnTcpMessageReady onMessageReadyCallback, void* userCookie = NULL, OnTcpConnectionStart onConnectionStartCallback = NULL, OnTcpConnectionEnd onConnectionEndCallback = NULL, const TcpReassemblyConfiguration &config = TcpReassemblyConfiguration());
|
||||
|
||||
/**
|
||||
* The most important method of this class which gets a packet from the user and processes it. If this packet opens a new connection, ends a connection or contains new data on an
|
||||
* existing connection, the relevant callback will be called (TcpReassembly#OnTcpMessageReady, TcpReassembly#OnTcpConnectionStart, TcpReassembly#OnTcpConnectionEnd)
|
||||
* @param[in] tcpData A reference to the packet to process
|
||||
* @return A enum of `TcpReassembly::ReassemblyStatus`, indicating status of TCP reassembly
|
||||
*/
|
||||
ReassemblyStatus reassemblePacket(Packet& tcpData);
|
||||
|
||||
/**
|
||||
* The most important method of this class which gets a raw packet from the user and processes it. If this packet opens a new connection, ends a connection or contains new data on an
|
||||
* existing connection, the relevant callback will be invoked (TcpReassembly#OnTcpMessageReady, TcpReassembly#OnTcpConnectionStart, TcpReassembly#OnTcpConnectionEnd)
|
||||
* @param[in] tcpRawData A reference to the raw packet to process
|
||||
* @return A enum of `TcpReassembly::ReassemblyStatus`, indicating status of TCP reassembly
|
||||
*/
|
||||
ReassemblyStatus reassemblePacket(RawPacket* tcpRawData);
|
||||
|
||||
/**
|
||||
* Close a connection manually. If the connection doesn't exist or already closed an error log is printed. This method will cause the TcpReassembly#OnTcpConnectionEnd to be invoked with
|
||||
* a reason of TcpReassembly#TcpReassemblyConnectionClosedManually
|
||||
* @param[in] flowKey A 4-byte hash key representing the connection. Can be taken from a ConnectionData instance
|
||||
*/
|
||||
void closeConnection(uint32_t flowKey);
|
||||
|
||||
/**
|
||||
* Close all open connections manually. This method will cause the TcpReassembly#OnTcpConnectionEnd to be invoked for each connection with a reason of
|
||||
* TcpReassembly#TcpReassemblyConnectionClosedManually
|
||||
*/
|
||||
void closeAllConnections();
|
||||
|
||||
/**
|
||||
* Get a map of all connections managed by this TcpReassembly instance (both connections that are open and those that are already closed)
|
||||
* @return A map of all connections managed. Notice this map is constant and cannot be changed by the user
|
||||
*/
|
||||
const ConnectionInfoList& getConnectionInformation() const { return m_ConnectionInfo; }
|
||||
|
||||
/**
|
||||
* Check if a certain connection managed by this TcpReassembly instance is currently opened or closed
|
||||
* @param[in] connection The connection to check
|
||||
* @return A positive number (> 0) if connection is opened, zero (0) if connection is closed, and a negative number (< 0) if this connection isn't managed by this TcpReassembly instance
|
||||
*/
|
||||
int isConnectionOpen(const ConnectionData& connection) const;
|
||||
|
||||
/**
|
||||
* Clean up the closed connections from the memory
|
||||
* @param[in] maxNumToClean The maximum number of items to be cleaned up per one call. This parameter, when its value is not zero, overrides the value that was set by the constructor.
|
||||
* @return The number of cleared items
|
||||
*/
|
||||
uint32_t purgeClosedConnections(uint32_t maxNumToClean = 0);
|
||||
|
||||
private:
|
||||
struct TcpFragment
|
||||
{
|
||||
uint32_t sequence;
|
||||
size_t dataLength;
|
||||
uint8_t* data;
|
||||
timeval timestamp;
|
||||
|
||||
TcpFragment() : sequence(0), dataLength(0), data(NULL) {}
|
||||
~TcpFragment() { delete [] data; }
|
||||
};
|
||||
|
||||
struct TcpOneSideData
|
||||
{
|
||||
IPAddress srcIP;
|
||||
uint16_t srcPort;
|
||||
uint32_t sequence;
|
||||
PointerVector<TcpFragment> tcpFragmentList;
|
||||
bool gotFinOrRst;
|
||||
|
||||
TcpOneSideData() : srcPort(0), sequence(0), gotFinOrRst(false) {}
|
||||
};
|
||||
|
||||
struct TcpReassemblyData
|
||||
{
|
||||
bool closed;
|
||||
int8_t numOfSides;
|
||||
int8_t prevSide;
|
||||
TcpOneSideData twoSides[2];
|
||||
ConnectionData connData;
|
||||
|
||||
TcpReassemblyData() : closed(false), numOfSides(0), prevSide(-1) {}
|
||||
};
|
||||
|
||||
typedef std::map<uint32_t, TcpReassemblyData> ConnectionList;
|
||||
typedef std::map<time_t, std::list<uint32_t> > CleanupList;
|
||||
|
||||
OnTcpMessageReady m_OnMessageReadyCallback;
|
||||
OnTcpConnectionStart m_OnConnStart;
|
||||
OnTcpConnectionEnd m_OnConnEnd;
|
||||
void* m_UserCookie;
|
||||
ConnectionList m_ConnectionList;
|
||||
ConnectionInfoList m_ConnectionInfo;
|
||||
CleanupList m_CleanupList;
|
||||
bool m_RemoveConnInfo;
|
||||
uint32_t m_ClosedConnectionDelay;
|
||||
uint32_t m_MaxNumToClean;
|
||||
size_t m_MaxOutOfOrderFragments;
|
||||
time_t m_PurgeTimepoint;
|
||||
bool m_EnableBaseBufferClearCondition;
|
||||
|
||||
void checkOutOfOrderFragments(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, bool cleanWholeFragList);
|
||||
|
||||
void handleFinOrRst(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, uint32_t flowKey);
|
||||
|
||||
void closeConnectionInternal(uint32_t flowKey, ConnectionEndReason reason);
|
||||
|
||||
void insertIntoCleanupList(uint32_t flowKey);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* PACKETPP_TCP_REASSEMBLY */
|
||||
263
pcappp/include/pcapplusplus/TextBasedProtocol.h
Normal file
263
pcappp/include/pcapplusplus/TextBasedProtocol.h
Normal file
@@ -0,0 +1,263 @@
|
||||
#ifndef PACKETPP_TEXT_BASED_PROTOCOL_LAYER
|
||||
#define PACKETPP_TEXT_BASED_PROTOCOL_LAYER
|
||||
|
||||
#include <map>
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/** End of header */
|
||||
#define PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER ""
|
||||
|
||||
class TextBasedProtocolMessage;
|
||||
|
||||
|
||||
// -------- Class HeaderField -----------------
|
||||
|
||||
|
||||
/**
|
||||
* @class HeaderField
|
||||
* A wrapper class for each text-based-protocol header field, e.g "Host", "Cookie", "Content-Length", "Via", "Call-ID", etc.
|
||||
* Each field contains a name (e.g "Host") and a value (e.g "www.wikipedia.org"). The user can get and set both of them through dedicated methods.
|
||||
* The separator between header fields is either CRLF ("\r\n\") or LF ("\n") in more rare cases, which means every HeaderField instance is
|
||||
* responsible for wrapping and parsing a header field from the previous CRLF (not inclusive) until the next CRLF/LF (inclusive)
|
||||
* A special case is with the end of a header, meaning 2 consecutive CRLFs ("\r\n\r\n") or consecutive LFs ("\n\n"). PcapPlusPlus treats the first
|
||||
* CRLF/LF as part of the last field in the header, and the second CRLF is an HeaderField instance of its own which name and values are an empty string ("")
|
||||
* or pcpp::PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER
|
||||
*/
|
||||
class HeaderField
|
||||
{
|
||||
friend class TextBasedProtocolMessage;
|
||||
public:
|
||||
|
||||
~HeaderField();
|
||||
|
||||
/**
|
||||
* A copy constructor that creates a new instance out of an existing HeaderField instance. The copied instance will not have shared
|
||||
* resources with the original instance, meaning all members and properties are copied
|
||||
* @param[in] other The original instance to copy from
|
||||
*/
|
||||
HeaderField(const HeaderField& other);
|
||||
|
||||
/**
|
||||
* Assignment operator for this class. This method copies the data from the other instance and will not share any resources with it.
|
||||
* Also, if the instance already contains data it will be deleted or zeroed
|
||||
* @param[in] other The instance to assign from
|
||||
* @return A reference to the assignee
|
||||
*/
|
||||
HeaderField& operator=(const HeaderField& other);
|
||||
|
||||
/**
|
||||
* @return The field length in bytes, meaning count of all characters from the previous CRLF (not inclusive) until the next CRLF (inclusive)
|
||||
* For example: the field "Host: www.wikipedia.org\r\n" will have the length of 25
|
||||
*/
|
||||
size_t getFieldSize() const { return m_FieldSize; }
|
||||
|
||||
/**
|
||||
* @return The field name as string. Notice the return data is copied data, so changing it won't change the packet data
|
||||
*/
|
||||
std::string getFieldName() const;
|
||||
|
||||
/**
|
||||
* @return The field value as string. Notice the return data is copied data, so changing it won't change the packet data
|
||||
*/
|
||||
std::string getFieldValue() const;
|
||||
|
||||
/**
|
||||
* A setter for field value
|
||||
* @param[in] newValue The new value to set to the field. Old value will be deleted
|
||||
* @return True if setting the value was completed successfully, false otherwise
|
||||
*/
|
||||
bool setFieldValue(std::string newValue);
|
||||
|
||||
/**
|
||||
* Get an indication whether the field is a field that ends the header (meaning contain only CRLF - see class explanation)
|
||||
* @return True if this is a end-of-header field, false otherwise
|
||||
*/
|
||||
bool isEndOfHeader() const { return m_IsEndOfHeaderField; }
|
||||
|
||||
private:
|
||||
HeaderField(std::string name, std::string value, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue);
|
||||
HeaderField(TextBasedProtocolMessage* TextBasedProtocolMessage, int offsetInMessage, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue);
|
||||
|
||||
char* getData() const;
|
||||
void setNextField(HeaderField* nextField);
|
||||
HeaderField *getNextField() const;
|
||||
void initNewField(std::string name, std::string value);
|
||||
void attachToTextBasedProtocolMessage(TextBasedProtocolMessage* message, int fieldOffsetInMessage);
|
||||
|
||||
uint8_t* m_NewFieldData;
|
||||
TextBasedProtocolMessage* m_TextBasedProtocolMessage;
|
||||
int m_NameOffsetInMessage;
|
||||
size_t m_FieldNameSize;
|
||||
int m_ValueOffsetInMessage;
|
||||
size_t m_FieldValueSize;
|
||||
size_t m_FieldSize;
|
||||
HeaderField* m_NextField;
|
||||
bool m_IsEndOfHeaderField;
|
||||
char m_NameValueSeparator;
|
||||
bool m_SpacesAllowedBetweenNameAndValue;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// -------- Class TextBasedProtocolMessage -----------------
|
||||
|
||||
/**
|
||||
* @class TextBasedProtocolMessage
|
||||
* An abstract base class that wraps text-based-protocol header layers (both requests and responses). It is the base class for all those layers.
|
||||
* This class is not meant to be instantiated, hence the protected c'tor
|
||||
*/
|
||||
class TextBasedProtocolMessage : public Layer
|
||||
{
|
||||
friend class HeaderField;
|
||||
public:
|
||||
~TextBasedProtocolMessage();
|
||||
|
||||
/**
|
||||
* Get a pointer to a header field by name. The search is case insensitive, meaning if a field with name "Host" exists and the
|
||||
* fieldName parameter is "host" (all letter are lower case), this method will return a pointer to "Host" field
|
||||
* @param[in] fieldName The field name
|
||||
* @param[in] index Optional parameter. If the field name appears more than once, this parameter will indicate which field to get.
|
||||
* The default value is 0 (get the first appearance of the field name as appears on the packet)
|
||||
* @return A pointer to an HeaderField instance, or NULL if field doesn't exist
|
||||
*/
|
||||
HeaderField* getFieldByName(std::string fieldName, int index = 0) const;
|
||||
|
||||
/**
|
||||
* @return A pointer to the first header field exists in this message, or NULL if no such field exists
|
||||
*/
|
||||
HeaderField* getFirstField() const { return m_FieldList; }
|
||||
|
||||
/**
|
||||
* Get the field which appears after a certain field
|
||||
* @param[in] prevField A pointer to the field
|
||||
* @return The field after prevField or NULL if prevField is the last field. If prevField is NULL, this method will return NULL
|
||||
*/
|
||||
HeaderField* getNextField(HeaderField* prevField) const { if (prevField != NULL) return prevField->getNextField(); else return NULL; }
|
||||
|
||||
/**
|
||||
* @return The number of header fields currently in the layer (not including CRLF at the end of the header)
|
||||
*/
|
||||
int getFieldCount() const;
|
||||
|
||||
/**
|
||||
* Add a new header field to this message. This field will be added last (before the end-of-header field)
|
||||
* @param[in] fieldName The field name
|
||||
* @param[in] fieldValue The field value
|
||||
* @return A pointer to the newly created header field, or NULL if the field could not be created
|
||||
*/
|
||||
virtual HeaderField* addField(const std::string& fieldName, const std::string& fieldValue);
|
||||
|
||||
/**
|
||||
* Add a new header field to this message. This field will be added last (before the end-of-header field)
|
||||
* @param[in] newField The header field to add
|
||||
* @return A pointer to the newly created header field, or NULL if the field could not be created
|
||||
*/
|
||||
virtual HeaderField* addField(const HeaderField& newField);
|
||||
|
||||
/**
|
||||
* Add the special end-of-header field (see the explanation in HeaderField)
|
||||
* @return A pointer to the newly created header field, or NULL if the field could not be created
|
||||
*/
|
||||
HeaderField* addEndOfHeader();
|
||||
|
||||
/**
|
||||
* Insert a new field after an existing field
|
||||
* @param[in] prevField A pointer to the existing field. If it's NULL the new field will be added as first field
|
||||
* @param[in] fieldName The field name
|
||||
* @param[in] fieldValue The field value
|
||||
* @return A pointer to the newly created header field, or NULL if the field could not be created
|
||||
*/
|
||||
virtual HeaderField* insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue);
|
||||
|
||||
/**
|
||||
* Insert a new field after an existing field
|
||||
* @param[in] prevFieldName A name of an existing field. If the field doesn't exist NULL will be returned.
|
||||
* If field name is empty ('') the new field will be added as first field
|
||||
* @param[in] fieldName The field name
|
||||
* @param[in] fieldValue The field value
|
||||
* @return A pointer to the newly created header field, or NULL if the field could not be created
|
||||
*/
|
||||
virtual HeaderField* insertField(std::string prevFieldName, const std::string& fieldName, const std::string& fieldValue);
|
||||
|
||||
/**
|
||||
* Insert a new field after an existing field
|
||||
* @param[in] prevField A pointer to the existing field
|
||||
* @param[in] newField The header field to add
|
||||
* @return A pointer to the newly created header field, or NULL if the field could not be created
|
||||
*/
|
||||
virtual HeaderField* insertField(HeaderField* prevField, const HeaderField& newField);
|
||||
|
||||
/**
|
||||
* Remove a field from the message
|
||||
* @param[in] fieldToRemove A pointer to the field that should be removed
|
||||
* @return True if the field was removed successfully, or false otherwise (for example: if fieldToRemove is NULL, if it doesn't exist
|
||||
* in the message, or if the removal failed)
|
||||
*/
|
||||
bool removeField(HeaderField* fieldToRemove);
|
||||
|
||||
/**
|
||||
* Remove a field from the message
|
||||
* @param[in] fieldName The name of the field that should be removed
|
||||
* @param[in] index Optional parameter. If the field name appears more than once, this parameter will indicate which field to remove.
|
||||
* The default value is 0 (remove the first appearance of the field name as appears on the packet)
|
||||
* @return True if the field was removed successfully, or false otherwise (for example: if fieldName doesn't exist in the message, or if the removal failed)
|
||||
*/
|
||||
bool removeField(std::string fieldName, int index = 0);
|
||||
|
||||
/**
|
||||
* Indicate whether the header is complete (ending with end-of-header "\r\n\r\n" or "\n\n") or spread over more packets
|
||||
* @return True if the header is complete or false if not
|
||||
*/
|
||||
bool isHeaderComplete() const;
|
||||
|
||||
// implement Layer's abstract methods
|
||||
|
||||
/**
|
||||
* Currently set only PayloadLayer for the rest of the data
|
||||
*/
|
||||
virtual void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return The message length
|
||||
*/
|
||||
size_t getHeaderLen() const;
|
||||
|
||||
/**
|
||||
* Does nothing for this class
|
||||
*/
|
||||
virtual void computeCalculateFields();
|
||||
|
||||
protected:
|
||||
TextBasedProtocolMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
|
||||
TextBasedProtocolMessage() : m_FieldList(NULL), m_LastField(NULL), m_FieldsOffset(0) {}
|
||||
|
||||
// copy c'tor
|
||||
TextBasedProtocolMessage(const TextBasedProtocolMessage& other);
|
||||
TextBasedProtocolMessage& operator=(const TextBasedProtocolMessage& other);
|
||||
|
||||
void copyDataFrom(const TextBasedProtocolMessage& other);
|
||||
|
||||
void parseFields();
|
||||
void shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift);
|
||||
|
||||
// abstract methods
|
||||
virtual char getHeaderFieldNameValueSeparator() const = 0;
|
||||
virtual bool spacesAllowedBetweenHeaderFieldNameAndValue() const = 0;
|
||||
|
||||
HeaderField* m_FieldList;
|
||||
HeaderField* m_LastField;
|
||||
int m_FieldsOffset;
|
||||
std::multimap<std::string, HeaderField*> m_FieldNameToFieldMap;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // PACKETPP_TEXT_BASED_PROTOCOL_LAYER
|
||||
16
pcappp/include/pcapplusplus/TimespecTimeval.h
Normal file
16
pcappp/include/pcapplusplus/TimespecTimeval.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/// these conversion macros are not defined on some of the platforms, including
|
||||
/// Windows
|
||||
|
||||
#ifndef TIMEVAL_TO_TIMESPEC
|
||||
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
|
||||
(ts)->tv_sec = (tv)->tv_sec; \
|
||||
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TIMESPEC_TO_TIMEVAL
|
||||
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
|
||||
(tv)->tv_sec = (ts)->tv_sec; \
|
||||
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
|
||||
}
|
||||
#endif
|
||||
105
pcappp/include/pcapplusplus/UdpLayer.h
Normal file
105
pcappp/include/pcapplusplus/UdpLayer.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#ifndef PACKETPP_UDP_LAYER
|
||||
#define PACKETPP_UDP_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct udphdr
|
||||
* Represents an UDP protocol header
|
||||
*/
|
||||
#pragma pack(push,1)
|
||||
struct udphdr
|
||||
{
|
||||
/** Source port */
|
||||
uint16_t portSrc;
|
||||
/** Destination port */
|
||||
uint16_t portDst;
|
||||
/** Length of header and payload in bytes */
|
||||
uint16_t length;
|
||||
/** Error-checking of the header and data */
|
||||
uint16_t headerChecksum;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @class UdpLayer
|
||||
* Represents an UDP (User Datagram Protocol) protocol layer
|
||||
*/
|
||||
class UdpLayer : public Layer
|
||||
{
|
||||
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 udphdr)
|
||||
* @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
|
||||
*/
|
||||
UdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = UDP; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new UDP header with source and destination ports
|
||||
* @param[in] portSrc Source UDP port address
|
||||
* @param[in] portDst Destination UDP port
|
||||
*/
|
||||
UdpLayer(uint16_t portSrc, uint16_t portDst);
|
||||
|
||||
/**
|
||||
* Get a pointer to the UDP header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the @ref udphdr
|
||||
*/
|
||||
udphdr* getUdpHeader() const { return (udphdr*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return UDP source port
|
||||
*/
|
||||
uint16_t getSrcPort() const;
|
||||
|
||||
/**
|
||||
* @return UDP destination port
|
||||
*/
|
||||
uint16_t getDstPort() const;
|
||||
|
||||
/**
|
||||
* Calculate the checksum from header and data and possibly write the result to @ref udphdr#headerChecksum
|
||||
* @param[in] writeResultToPacket If set to true then checksum result will be written to @ref udphdr#headerChecksum
|
||||
* @return The checksum result
|
||||
*/
|
||||
uint16_t calculateChecksum(bool writeResultToPacket);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: DnsLayer, DhcpLayer, VxlanLayer, SipRequestLayer, SipResponseLayer,
|
||||
* RadiusLayer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of @ref udphdr
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(udphdr); }
|
||||
|
||||
/**
|
||||
* Calculate @ref udphdr#headerChecksum field
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_UDP_LAYER */
|
||||
137
pcappp/include/pcapplusplus/VlanLayer.h
Normal file
137
pcappp/include/pcapplusplus/VlanLayer.h
Normal file
@@ -0,0 +1,137 @@
|
||||
#ifndef PACKETPP_VLAN_LAYER
|
||||
#define PACKETPP_VLAN_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
#include "EthLayer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct vlan_header
|
||||
* Represents a VLAN header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct vlan_header
|
||||
{
|
||||
/**
|
||||
@verbatim
|
||||
0 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Prio |C| VLAN ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@endverbatim
|
||||
*/
|
||||
uint16_t vlan;
|
||||
/** Ethernet type for next layer */
|
||||
uint16_t etherType;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @class VlanLayer
|
||||
* Represents a VLAN tunnel layer
|
||||
*/
|
||||
class VlanLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
VlanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = VLAN; }
|
||||
|
||||
/**
|
||||
* A constructor that allocates a new VLAN header
|
||||
* @param[in] vlanID VLAN ID
|
||||
* @param[in] cfi CFI value
|
||||
* @param[in] priority Priority value
|
||||
* @param[in] etherType Protocol EtherType of the next layer. It's an optional parameter, a value of 0 will be set if not provided
|
||||
*/
|
||||
VlanLayer(const uint16_t vlanID, bool cfi, uint8_t priority, uint16_t etherType = 0);
|
||||
|
||||
~VlanLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the VLAN header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the vlan_header
|
||||
*/
|
||||
vlan_header* getVlanHeader() const { return (vlan_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* Get the VLAN ID value. This method differs from vlan_header#vlanID because vlan_header#vlanID is 12 bits long in a 16 bit field.
|
||||
* This methods extracts only the 12 bit relevant for the VLAN ID
|
||||
* @return VLAN ID value
|
||||
* @todo Verify it works in big endian machines as well
|
||||
*/
|
||||
uint16_t getVlanID() const;
|
||||
|
||||
/**
|
||||
* @return The CFI bit value
|
||||
* @todo Verify it works in big endian machines as well
|
||||
*/
|
||||
uint8_t getCFI() const;
|
||||
|
||||
/**
|
||||
* @return The priority value
|
||||
* @todo Verify it works in big endian machines as well
|
||||
*/
|
||||
uint8_t getPriority() const;
|
||||
|
||||
/**
|
||||
* Set VLAN ID. This method differs from setting vlan_header#vlanID because vlan_header#vlanID is 12 bits long in a 16 bit field.
|
||||
* This methods sets only the 12 bit relevant for the VLAN ID
|
||||
* @param[in] id The VLAN ID to set
|
||||
* @todo Verify it works in big endian machines as well
|
||||
*/
|
||||
void setVlanID(uint16_t id);
|
||||
|
||||
/**
|
||||
* Set CFI bit
|
||||
* @param[in] cfi The CFI bit to set
|
||||
* @todo Verify it works in big endian machines as well
|
||||
*/
|
||||
void setCFI(bool cfi);
|
||||
|
||||
/**
|
||||
* Set priority value
|
||||
* @param[in] priority The priority value to set
|
||||
* @todo Verify it works in big endian machines as well
|
||||
*/
|
||||
void setPriority(uint8_t priority);
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, MplsLayer. Otherwise sets PayloadLayer
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of vlan_header
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(vlan_header); }
|
||||
|
||||
/**
|
||||
* Calculate the EtherType for known protocols: IPv4, IPv6, ARP, VLAN
|
||||
*/
|
||||
void computeCalculateFields();
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif /* PACKETPP_VLAN_LAYER */
|
||||
145
pcappp/include/pcapplusplus/VxlanLayer.h
Normal file
145
pcappp/include/pcapplusplus/VxlanLayer.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef PACKETPP_VXLAN_LAYER
|
||||
#define PACKETPP_VXLAN_LAYER
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
/// @file
|
||||
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @struct vxlan_header
|
||||
* Represents a VXLAN protocol header
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct vxlan_header
|
||||
{
|
||||
#if(BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/** Reserved bits */
|
||||
uint16_t reserved6_8:3;
|
||||
/** VNI present flag */
|
||||
uint16_t vniPresentFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved2_4:3;
|
||||
/** GBP flag */
|
||||
uint16_t gbpFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved14_16:3;
|
||||
/** Policy applied flag */
|
||||
uint16_t policyAppliedFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved11_12:2;
|
||||
/** Don't learn flag */
|
||||
uint16_t dontLearnFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved9:1;
|
||||
#else
|
||||
/** Reserved bits */
|
||||
uint16_t reserved9:1;
|
||||
/** Don't learn flag */
|
||||
uint16_t dontLearnFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved11_12:2;
|
||||
/** Policy applied flag */
|
||||
uint16_t policyAppliedFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved14_16:3;
|
||||
/** GBP flag */
|
||||
uint16_t gbpFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved2_4:3;
|
||||
/** VNI present flag */
|
||||
uint16_t vniPresentFlag:1;
|
||||
/** Reserved bits */
|
||||
uint16_t reserved6_8:3;
|
||||
#endif
|
||||
|
||||
/** Group Policy ID */
|
||||
uint16_t groupPolicyID;
|
||||
|
||||
/** VXLAN Network ID (VNI) */
|
||||
uint32_t vni:24;
|
||||
/** Reserved bits */
|
||||
uint32_t pad:8;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/**
|
||||
* @class VxlanLayer
|
||||
* Represents a VXLAN (Virtual eXtensible Local Area Network) protocol layer
|
||||
*/
|
||||
class VxlanLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** A constructor that creates the layer from an existing packet raw data
|
||||
* @param[in] data A pointer to the raw data
|
||||
* @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
|
||||
*/
|
||||
VxlanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = VXLAN; }
|
||||
|
||||
/**
|
||||
* A constructor that creates a new VXLAN header and allocates the data. Note: the VNI present flag is set automatically
|
||||
* @param[in] vni VNI (VXLAN Network ID) to set. Optional parameter (default is 0)
|
||||
* @param[in] groupPolicyID Group Policy ID to set. Optional parameter (default is 0)
|
||||
* @param[in] setGbpFlag Set GBP flag. Optional parameter (default is false)
|
||||
* @param[in] setPolicyAppliedFlag Set Policy Applied flag. Optional parameter (default is false)
|
||||
* @param[in] setDontLearnFlag Set Don't Learn flag. Optional parameter (default is false)
|
||||
*/
|
||||
VxlanLayer(uint32_t vni = 0, uint16_t groupPolicyID = 0, bool setGbpFlag = false, bool setPolicyAppliedFlag = false, bool setDontLearnFlag = false);
|
||||
|
||||
~VxlanLayer() {}
|
||||
|
||||
/**
|
||||
* Get a pointer to the VXLAN header. Notice this points directly to the data, so every change will change the actual packet data
|
||||
* @return A pointer to the vxlan_header
|
||||
*/
|
||||
vxlan_header* getVxlanHeader() const { return (vxlan_header*)m_Data; }
|
||||
|
||||
/**
|
||||
* @return The VXLAN Network ID (VNI) value
|
||||
*/
|
||||
uint32_t getVNI() const;
|
||||
|
||||
/**
|
||||
* Set VXLAN Network ID (VNI) value
|
||||
* @param[in] vni VNI value to set
|
||||
*/
|
||||
void setVNI(uint32_t vni);
|
||||
|
||||
/**
|
||||
* A static method that checks whether the port is considered as VxLAN
|
||||
* @param[in] port The port number to be checked
|
||||
*/
|
||||
static bool isVxlanPort(uint16_t port) { return port == 4789; }
|
||||
|
||||
|
||||
// implement abstract methods
|
||||
|
||||
/**
|
||||
* Next layer for VXLAN is always Ethernet
|
||||
*/
|
||||
void parseNextLayer();
|
||||
|
||||
/**
|
||||
* @return Size of vxlan_header
|
||||
*/
|
||||
size_t getHeaderLen() const { return sizeof(vxlan_header); }
|
||||
|
||||
/**
|
||||
* Does nothing for this layer
|
||||
*/
|
||||
void computeCalculateFields() {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PACKETPP_VXLAN_LAYER
|
||||
113
pcappp/include/pcapplusplus/Win32-Extensions.h
Normal file
113
pcappp/include/pcapplusplus/Win32-Extensions.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
|
||||
* nor the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WIN32_EXTENSIONS_H__
|
||||
#define __WIN32_EXTENSIONS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Definitions */
|
||||
|
||||
/*!
|
||||
\brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().
|
||||
*/
|
||||
struct pcap_send_queue
|
||||
{
|
||||
u_int maxlen; ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field.
|
||||
u_int len; ///< Current size of the queue, in bytes.
|
||||
char *buffer; ///< Buffer containing the packets to be sent.
|
||||
};
|
||||
|
||||
typedef struct pcap_send_queue pcap_send_queue;
|
||||
|
||||
/*!
|
||||
\brief This typedef is a support for the pcap_get_airpcap_handle() function
|
||||
*/
|
||||
#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
|
||||
#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
|
||||
typedef struct _AirpcapHandle *PAirpcapHandle;
|
||||
#endif
|
||||
|
||||
#define BPF_MEM_EX_IMM 0xc0
|
||||
#define BPF_MEM_EX_IND 0xe0
|
||||
|
||||
/*used for ST*/
|
||||
#define BPF_MEM_EX 0xc0
|
||||
#define BPF_TME 0x08
|
||||
|
||||
#define BPF_LOOKUP 0x90
|
||||
#define BPF_EXECUTE 0xa0
|
||||
#define BPF_INIT 0xb0
|
||||
#define BPF_VALIDATE 0xc0
|
||||
#define BPF_SET_ACTIVE 0xd0
|
||||
#define BPF_RESET 0xe0
|
||||
#define BPF_SET_MEMORY 0x80
|
||||
#define BPF_GET_REGISTER_VALUE 0x70
|
||||
#define BPF_SET_REGISTER_VALUE 0x60
|
||||
#define BPF_SET_WORKING 0x50
|
||||
#define BPF_SET_ACTIVE_READ 0x40
|
||||
#define BPF_SET_AUTODELETION 0x30
|
||||
#define BPF_SEPARATION 0xff
|
||||
|
||||
/* Prototypes */
|
||||
pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
|
||||
|
||||
void pcap_sendqueue_destroy(pcap_send_queue* queue);
|
||||
|
||||
int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
|
||||
|
||||
u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
|
||||
|
||||
HANDLE pcap_getevent(pcap_t *p);
|
||||
|
||||
struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);
|
||||
|
||||
int pcap_setuserbuffer(pcap_t *p, int size);
|
||||
|
||||
int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);
|
||||
|
||||
int pcap_live_dump_ended(pcap_t *p, int sync);
|
||||
|
||||
int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data);
|
||||
|
||||
int pcap_start_oem(char* err_str, int flags);
|
||||
|
||||
PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__WIN32_EXTENSIONS_H__
|
||||
64
pcappp/include/pcapplusplus/WinPcapLiveDevice.h
Normal file
64
pcappp/include/pcapplusplus/WinPcapLiveDevice.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef PCAPP_WINPCAP_LIVE_DEVICE
|
||||
#define PCAPP_WINPCAP_LIVE_DEVICE
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
/// @file
|
||||
|
||||
#include "PcapLiveDevice.h"
|
||||
|
||||
/**
|
||||
* \namespace pcpp
|
||||
* \brief The main namespace for the PcapPlusPlus lib
|
||||
*/
|
||||
namespace pcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @class WinPcapLiveDevice
|
||||
* A class that wraps a Windows network interface (each of the interfaces listed in ipconfig).
|
||||
* This class is almost similar in its capabilities to PcapLiveDevice (its parent class) with some small changes that mainly result from
|
||||
* differences between libpcap and WinPcap/Npcap. Please see the reference for PcapLiveDevice for more details
|
||||
*/
|
||||
class WinPcapLiveDevice : public PcapLiveDevice
|
||||
{
|
||||
friend class PcapLiveDeviceList;
|
||||
protected:
|
||||
int m_MinAmountOfDataToCopyFromKernelToApplication;
|
||||
|
||||
// c'tor is not public, there should be only one for every interface (created by PcapLiveDeviceList)
|
||||
WinPcapLiveDevice(pcap_if_t* iface, bool calculateMTU, bool calculateMacAddress, bool calculateDefaultGateway);
|
||||
// copy c'tor is not public
|
||||
WinPcapLiveDevice( const WinPcapLiveDevice& other );
|
||||
WinPcapLiveDevice& operator=(const WinPcapLiveDevice& other);
|
||||
|
||||
public:
|
||||
virtual LiveDeviceType getDeviceType() const { return WinPcapDevice; }
|
||||
|
||||
bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie);
|
||||
bool startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie);
|
||||
bool startCapture(RawPacketVector& capturedPacketsVector) { return PcapLiveDevice::startCapture(capturedPacketsVector); }
|
||||
|
||||
virtual int sendPackets(RawPacket* rawPacketsArr, int arrLength);
|
||||
|
||||
/**
|
||||
* WinPcap/Npcap have a feature (that doesn't exist in libpcap) to change the minimum amount of data in the kernel buffer that causes a read
|
||||
* from the application to return (unless the timeout expires). Please see documentation for pcap_setmintocopy for more info. This method
|
||||
* enables the user to change this size. Note the device must be open for this method to work
|
||||
* @param[in] size The size to set in bytes
|
||||
* @return True if set succeeded, false if the device is closed or if pcap_setmintocopy failed
|
||||
*/
|
||||
bool setMinAmountOfDataToCopyFromKernelToApplication(int size);
|
||||
|
||||
/**
|
||||
* @return The current amount of data in the kernel buffer that causes a read from the application to return (see also
|
||||
* setMinAmountOfDataToCopyFromKernelToApplication())
|
||||
*/
|
||||
int getMinAmountOfDataToCopyFromKernelToApplication() const { return m_MinAmountOfDataToCopyFromKernelToApplication; }
|
||||
};
|
||||
|
||||
} // namespace pcpp
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif /* PCAPP_WINPCAP_LIVE_DEVICE */
|
||||
215
pcappp/include/pcapplusplus/_ptw32.h
Normal file
215
pcappp/include/pcapplusplus/_ptw32.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Module: _ptw32.h
|
||||
*
|
||||
* Purpose:
|
||||
* Pthreads4w internal macros, to be shared by other headers
|
||||
* comprising the pthreads4w package.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads4w - POSIX Threads for Windows
|
||||
* Copyright 1998 John E. Bossom
|
||||
* Copyright 1999-2018, Pthreads4w contributors
|
||||
*
|
||||
* Homepage: https://sourceforge.net/projects/pthreads4w/
|
||||
*
|
||||
* The current list of contributors is contained
|
||||
* in the file CONTRIBUTORS included with the source
|
||||
* code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
*
|
||||
* https://sourceforge.net/p/pthreads4w/wiki/Contributors/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __PTW32_H
|
||||
#define __PTW32_H
|
||||
|
||||
/* See the README file for an explanation of the pthreads-win32
|
||||
* version numbering scheme and how the DLL is named etc.
|
||||
*
|
||||
* FIXME: consider moving this to <_ptw32.h>; maybe also add a
|
||||
* leading underscore to the macro names.
|
||||
*/
|
||||
#define __PTW32_VERSION_MAJOR 3
|
||||
#define __PTW32_VERSION_MINOR 0
|
||||
#define __PTW32_VERSION_MICRO 0
|
||||
#define __PTW32_VERION_BUILD 0
|
||||
#define __PTW32_VERSION 3,0,0,0
|
||||
#define __PTW32_VERSION_STRING "3, 0, 0, 0\0"
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC system_header
|
||||
# if ! defined __declspec
|
||||
# error "Please upgrade your GNU compiler to one that supports __declspec."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
# define __PTW32_BEGIN_C_DECLS extern "C" {
|
||||
# define __PTW32_END_C_DECLS }
|
||||
#else
|
||||
# define __PTW32_BEGIN_C_DECLS
|
||||
# define __PTW32_END_C_DECLS
|
||||
#endif
|
||||
|
||||
#if defined __PTW32_STATIC_LIB
|
||||
# define __PTW32_DLLPORT
|
||||
|
||||
#elif defined __PTW32_BUILD
|
||||
# define __PTW32_DLLPORT __declspec (dllexport)
|
||||
#else
|
||||
# define __PTW32_DLLPORT /*__declspec (dllimport)*/
|
||||
#endif
|
||||
|
||||
#ifndef __PTW32_CDECL
|
||||
/* FIXME: another internal macro; should have two initial underscores;
|
||||
* Nominally, we prefer to use __cdecl calling convention for all our
|
||||
* functions, but we map it through this macro alias to facilitate the
|
||||
* possible choice of alternatives; for example:
|
||||
*/
|
||||
# ifdef _OPEN_WATCOM_SOURCE
|
||||
/* The Open Watcom C/C++ compiler uses a non-standard default calling
|
||||
* convention, (similar to __fastcall), which passes function arguments
|
||||
* in registers, unless the __cdecl convention is explicitly specified
|
||||
* in exposed function prototypes.
|
||||
*
|
||||
* Our preference is to specify the __cdecl convention for all calls,
|
||||
* even though this could slow Watcom code down slightly. If you know
|
||||
* that the Watcom compiler will be used to build both the DLL and your
|
||||
* application, then you may #define _OPEN_WATCOM_SOURCE, so disabling
|
||||
* the forced specification of __cdecl for all function declarations;
|
||||
* remember that this must be defined consistently, for both the DLL
|
||||
* build, and the application build.
|
||||
*/
|
||||
# define __PTW32_CDECL
|
||||
# else
|
||||
# define __PTW32_CDECL __cdecl
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is more or less a duplicate of what is in the autoconf config.h,
|
||||
* which is only used when building the pthreads4w libraries.
|
||||
*/
|
||||
|
||||
#if !defined (__PTW32_CONFIG_H) && !defined(__PTW32_PSEUDO_CONFIG_H_SOURCED)
|
||||
# define __PTW32_PSEUDO_CONFIG_H_SOURCED
|
||||
# if defined(WINCE)
|
||||
# undef HAVE_CPU_AFFINITY
|
||||
# define NEED_DUPLICATEHANDLE
|
||||
# define NEED_CREATETHREAD
|
||||
# define NEED_ERRNO
|
||||
# define NEED_CALLOC
|
||||
# define NEED_UNICODE_CONSTS
|
||||
# define NEED_PROCESS_AFFINITY_MASK
|
||||
/* This may not be needed */
|
||||
# define RETAIN_WSALASTERROR
|
||||
# elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1900
|
||||
# define HAVE_STRUCT_TIMESPEC
|
||||
# elif _MSC_VER < 1300
|
||||
# define __PTW32_CONFIG_MSVC6
|
||||
# elif _MSC_VER < 1400
|
||||
# define __PTW32_CONFIG_MSVC7
|
||||
# endif
|
||||
# elif defined(_UWIN)
|
||||
# define HAVE_MODE_T
|
||||
# define HAVE_STRUCT_TIMESPEC
|
||||
# define HAVE_SIGNAL_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If HAVE_ERRNO_H is defined then assume that autoconf has been used
|
||||
* to overwrite config.h, otherwise the original config.h is in use
|
||||
* at build-time or the above block of defines is in use otherwise
|
||||
* and NEED_ERRNO is either defined or not defined.
|
||||
*/
|
||||
#if defined(HAVE_ERRNO_H) || !defined(NEED_ERRNO)
|
||||
# include <errno.h>
|
||||
#else
|
||||
# include "need_errno.h"
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
# define int64_t LONGLONG
|
||||
# define uint64_t ULONGLONG
|
||||
#elif !defined(__MINGW32__)
|
||||
typedef _int64 int64_t;
|
||||
typedef unsigned _int64 uint64_t;
|
||||
# if defined (__PTW32_CONFIG_MSVC6)
|
||||
typedef long intptr_t;
|
||||
# endif
|
||||
#elif defined(HAVE_STDINT_H) && HAVE_STDINT_H == 1
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In case ETIMEDOUT hasn't been defined above somehow.
|
||||
*/
|
||||
#if !defined(ETIMEDOUT)
|
||||
/*
|
||||
* note: ETIMEDOUT is no longer defined in winsock.h
|
||||
* WSAETIMEDOUT is so use its value.
|
||||
*/
|
||||
# include <winsock.h>
|
||||
# if defined(WSAETIMEDOUT)
|
||||
# define ETIMEDOUT WSAETIMEDOUT
|
||||
# else
|
||||
# define ETIMEDOUT 10060 /* This is the value of WSAETIMEDOUT in winsock.h. */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Several systems may not define some error numbers;
|
||||
* defining those which are likely to be missing here will let
|
||||
* us complete the library builds.
|
||||
*/
|
||||
#if !defined(ENOTSUP)
|
||||
# define ENOTSUP 48 /* This is the value in Solaris. */
|
||||
#endif
|
||||
|
||||
#if !defined(ENOSYS)
|
||||
# define ENOSYS 140 /* Semi-arbitrary value */
|
||||
#endif
|
||||
|
||||
#if !defined(EDEADLK)
|
||||
# if defined(EDEADLOCK)
|
||||
# define EDEADLK EDEADLOCK
|
||||
# else
|
||||
# define EDEADLK 36 /* This is the value in MSVC. */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* POSIX 2008 - related to robust mutexes */
|
||||
#if __PTW32_VERSION_MAJOR > 2
|
||||
# if !defined(EOWNERDEAD)
|
||||
# define EOWNERDEAD 1000
|
||||
# endif
|
||||
# if !defined(ENOTRECOVERABLE)
|
||||
# define ENOTRECOVERABLE 1001
|
||||
# endif
|
||||
#else
|
||||
# if !defined(EOWNERDEAD)
|
||||
# define EOWNERDEAD 42
|
||||
# endif
|
||||
# if !defined(ENOTRECOVERABLE)
|
||||
# define ENOTRECOVERABLE 43
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* !__PTW32_H */
|
||||
137
pcappp/include/pcapplusplus/bittypes.h
Normal file
137
pcappp/include/pcapplusplus/bittypes.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 1999 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _BITTYPES_H
|
||||
#define _BITTYPES_H
|
||||
|
||||
#ifndef HAVE_U_INT8_T
|
||||
|
||||
#if SIZEOF_CHAR == 1
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef signed char int8_t;
|
||||
#elif SIZEOF_INT == 1
|
||||
typedef unsigned int u_int8_t;
|
||||
typedef signed int int8_t;
|
||||
#else /* XXX */
|
||||
#error "there's no appropriate type for u_int8_t"
|
||||
#endif
|
||||
#define HAVE_U_INT8_T 1
|
||||
#define HAVE_INT8_T 1
|
||||
|
||||
#endif /* HAVE_U_INT8_T */
|
||||
|
||||
#ifndef HAVE_U_INT16_T
|
||||
|
||||
#if SIZEOF_SHORT == 2
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef signed short int16_t;
|
||||
#elif SIZEOF_INT == 2
|
||||
typedef unsigned int u_int16_t;
|
||||
typedef signed int int16_t;
|
||||
#elif SIZEOF_CHAR == 2
|
||||
typedef unsigned char u_int16_t;
|
||||
typedef signed char int16_t;
|
||||
#else /* XXX */
|
||||
#error "there's no appropriate type for u_int16_t"
|
||||
#endif
|
||||
#define HAVE_U_INT16_T 1
|
||||
#define HAVE_INT16_T 1
|
||||
|
||||
#endif /* HAVE_U_INT16_T */
|
||||
|
||||
#ifndef HAVE_U_INT32_T
|
||||
|
||||
#if SIZEOF_INT == 4
|
||||
typedef unsigned int u_int32_t;
|
||||
typedef signed int int32_t;
|
||||
#elif SIZEOF_LONG == 4
|
||||
typedef unsigned long u_int32_t;
|
||||
typedef signed long int32_t;
|
||||
#elif SIZEOF_SHORT == 4
|
||||
typedef unsigned short u_int32_t;
|
||||
typedef signed short int32_t;
|
||||
#else /* XXX */
|
||||
#error "there's no appropriate type for u_int32_t"
|
||||
#endif
|
||||
#define HAVE_U_INT32_T 1
|
||||
#define HAVE_INT32_T 1
|
||||
|
||||
#endif /* HAVE_U_INT32_T */
|
||||
|
||||
#ifndef HAVE_U_INT64_T
|
||||
#if SIZEOF_LONG_LONG == 8
|
||||
typedef unsigned long long u_int64_t;
|
||||
typedef long long int64_t;
|
||||
#elif defined(_MSC_EXTENSIONS)
|
||||
typedef unsigned _int64 u_int64_t;
|
||||
typedef _int64 int64_t;
|
||||
#elif SIZEOF_INT == 8
|
||||
typedef unsigned int u_int64_t;
|
||||
#elif SIZEOF_LONG == 8
|
||||
typedef unsigned long u_int64_t;
|
||||
#elif SIZEOF_SHORT == 8
|
||||
typedef unsigned short u_int64_t;
|
||||
#else /* XXX */
|
||||
#error "there's no appropriate type for u_int64_t"
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_U_INT64_T */
|
||||
|
||||
#ifndef PRId64
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
#define PRId64 "I64d"
|
||||
#else /* _MSC_EXTENSIONS */
|
||||
#define PRId64 "lld"
|
||||
#endif /* _MSC_EXTENSIONS */
|
||||
#endif /* PRId64 */
|
||||
|
||||
#ifndef PRIo64
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
#define PRIo64 "I64o"
|
||||
#else /* _MSC_EXTENSIONS */
|
||||
#define PRIo64 "llo"
|
||||
#endif /* _MSC_EXTENSIONS */
|
||||
#endif /* PRIo64 */
|
||||
|
||||
#ifndef PRIx64
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
#define PRIx64 "I64x"
|
||||
#else /* _MSC_EXTENSIONS */
|
||||
#define PRIx64 "llx"
|
||||
#endif /* _MSC_EXTENSIONS */
|
||||
#endif /* PRIx64 */
|
||||
|
||||
#ifndef PRIu64
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
#define PRIu64 "I64u"
|
||||
#else /* _MSC_EXTENSIONS */
|
||||
#define PRIu64 "llu"
|
||||
#endif /* _MSC_EXTENSIONS */
|
||||
#endif /* PRIu64 */
|
||||
|
||||
#endif /* _BITTYPES_H */
|
||||
163
pcappp/include/pcapplusplus/ip6_misc.h
Normal file
163
pcappp/include/pcapplusplus/ip6_misc.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 1993, 1994, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the University of California,
|
||||
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.5 2006-01-22 18:02:18 gianluca Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#define IN_MULTICAST(a) IN_CLASSD(a)
|
||||
#endif
|
||||
|
||||
#define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
|
||||
|
||||
#define IN_LOOPBACKNET 127
|
||||
|
||||
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
|
||||
/* IPv6 address */
|
||||
struct in6_addr
|
||||
{
|
||||
union
|
||||
{
|
||||
u_int8_t u6_addr8[16];
|
||||
u_int16_t u6_addr16[8];
|
||||
u_int32_t u6_addr32[4];
|
||||
} in6_u;
|
||||
#define s6_addr in6_u.u6_addr8
|
||||
#define s6_addr16 in6_u.u6_addr16
|
||||
#define s6_addr32 in6_u.u6_addr32
|
||||
#define s6_addr64 in6_u.u6_addr64
|
||||
};
|
||||
|
||||
#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
|
||||
#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
|
||||
#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF))
|
||||
typedef unsigned short sa_family_t;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
|
||||
|
||||
#define __SOCKADDR_COMMON(sa_prefix) \
|
||||
sa_family_t sa_prefix##family
|
||||
|
||||
/* Ditto, for IPv6. */
|
||||
struct sockaddr_in6
|
||||
{
|
||||
__SOCKADDR_COMMON (sin6_);
|
||||
u_int16_t sin6_port; /* Transport layer port # */
|
||||
u_int32_t sin6_flowinfo; /* IPv6 flow information */
|
||||
struct in6_addr sin6_addr; /* IPv6 address */
|
||||
};
|
||||
|
||||
#define IN6_IS_ADDR_V4MAPPED(a) \
|
||||
((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
|
||||
(((u_int32_t *) (a))[2] == htonl (0xffff)))
|
||||
|
||||
#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
|
||||
|
||||
#define IN6_IS_ADDR_LINKLOCAL(a) \
|
||||
((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
|
||||
|
||||
#define IN6_IS_ADDR_LOOPBACK(a) \
|
||||
(((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
|
||||
((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
|
||||
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
|
||||
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
|
||||
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
|
||||
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
|
||||
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
|
||||
|
||||
#define nd_rd_type nd_rd_hdr.icmp6_type
|
||||
#define nd_rd_code nd_rd_hdr.icmp6_code
|
||||
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
|
||||
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
|
||||
|
||||
/*
|
||||
* IPV6 extension headers
|
||||
*/
|
||||
#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */
|
||||
#define IPPROTO_IPV6 41 /* IPv6 header. */
|
||||
#define IPPROTO_ROUTING 43 /* IPv6 routing header */
|
||||
#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
|
||||
#define IPPROTO_ESP 50 /* encapsulating security payload */
|
||||
#define IPPROTO_AH 51 /* authentication header */
|
||||
#define IPPROTO_ICMPV6 58 /* ICMPv6 */
|
||||
#define IPPROTO_NONE 59 /* IPv6 no next header */
|
||||
#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */
|
||||
#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */
|
||||
|
||||
#define IPV6_RTHDR_TYPE_0 0
|
||||
|
||||
/* Option types and related macros */
|
||||
#define IP6OPT_PAD1 0x00 /* 00 0 00000 */
|
||||
#define IP6OPT_PADN 0x01 /* 00 0 00001 */
|
||||
#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
|
||||
#define IP6OPT_JUMBO_LEN 6
|
||||
#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */
|
||||
|
||||
#define IP6OPT_RTALERT_LEN 4
|
||||
#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */
|
||||
#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */
|
||||
#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
|
||||
#define IP6OPT_MINLEN 2
|
||||
|
||||
#define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */
|
||||
#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */
|
||||
#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */
|
||||
#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */
|
||||
#define IP6OPT_EID 0x8a /* 10 0 01010 */
|
||||
|
||||
#define IP6OPT_TYPE(o) ((o) & 0xC0)
|
||||
#define IP6OPT_TYPE_SKIP 0x00
|
||||
#define IP6OPT_TYPE_DISCARD 0x40
|
||||
#define IP6OPT_TYPE_FORCEICMP 0x80
|
||||
#define IP6OPT_TYPE_ICMP 0xC0
|
||||
|
||||
#define IP6OPT_MUTABLE 0x20
|
||||
|
||||
|
||||
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
|
||||
#ifndef EAI_ADDRFAMILY
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
||||
int ai_family; /* PF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||
size_t ai_addrlen; /* length of ai_addr */
|
||||
char *ai_canonname; /* canonical name for hostname */
|
||||
struct sockaddr *ai_addr; /* binary address */
|
||||
struct addrinfo *ai_next; /* next structure in linked list */
|
||||
};
|
||||
#endif
|
||||
#endif /* __MINGW32__ */
|
||||
47
pcappp/include/pcapplusplus/pcap-bpf.h
Normal file
47
pcappp/include/pcapplusplus/pcap-bpf.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.50 2007/04/01 21:43:55 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* For backwards compatibility.
|
||||
*
|
||||
* Note to OS vendors: do NOT get rid of this file! Some applications
|
||||
* might expect to be able to include <pcap-bpf.h>.
|
||||
*/
|
||||
#include <pcap/bpf.h>
|
||||
42
pcappp/include/pcapplusplus/pcap-namedb.h
Normal file
42
pcappp/include/pcapplusplus/pcap-namedb.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 1996
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the Computer Systems
|
||||
* Engineering Group at Lawrence Berkeley Laboratory.
|
||||
* 4. Neither the name of the University nor of the Laboratory may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006/10/04 18:13:32 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* For backwards compatibility.
|
||||
*
|
||||
* Note to OS vendors: do NOT get rid of this file! Some applications
|
||||
* might expect to be able to include <pcap-namedb.h>.
|
||||
*/
|
||||
#include <pcap/namedb.h>
|
||||
95
pcappp/include/pcapplusplus/pcap-stdinc.h
Normal file
95
pcappp/include/pcapplusplus/pcap-stdinc.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (California)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Politecnico di Torino nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#define SIZEOF_CHAR 1
|
||||
#define SIZEOF_SHORT 2
|
||||
#define SIZEOF_INT 4
|
||||
#ifndef _MSC_EXTENSIONS
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Avoids a compiler warning in case this was already defined
|
||||
* (someone defined _WINSOCKAPI_ when including 'windows.h', in order
|
||||
* to prevent it from including 'winsock.h')
|
||||
*/
|
||||
#ifdef _WINSOCKAPI_
|
||||
#undef _WINSOCKAPI_
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "bittypes.h"
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#include "IP6_misc.h"
|
||||
#endif
|
||||
|
||||
#define caddr_t char*
|
||||
|
||||
#if _MSC_VER < 1500
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <stdint.h>
|
||||
#else /*__MINGW32__*/
|
||||
/* MSVC compiler */
|
||||
#ifndef _UINTPTR_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif
|
||||
#define _UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef _INTPTR_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
typedef __int64 intptr_t;
|
||||
#else
|
||||
typedef _W64 int intptr_t;
|
||||
#endif
|
||||
#define _INTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#endif /*__MINGW32__*/
|
||||
45
pcappp/include/pcapplusplus/pcap.h
Normal file
45
pcappp/include/pcapplusplus/pcap.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the Computer Systems
|
||||
* Engineering Group at Lawrence Berkeley Laboratory.
|
||||
* 4. Neither the name of the University nor of the Laboratory may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* For backwards compatibility.
|
||||
*
|
||||
* Note to OS vendors: do NOT get rid of this file! Many applications
|
||||
* expect to be able to include <pcap.h>, and at least some of them
|
||||
* go through contortions in their configure scripts to try to detect
|
||||
* OSes that have "helpfully" moved pcap.h to <pcap/pcap.h> without
|
||||
* leaving behind a <pcap.h> file.
|
||||
*/
|
||||
#include <pcap/pcap.h>
|
||||
48
pcappp/include/pcapplusplus/pcap/bluetooth.h
Normal file
48
pcappp/include/pcapplusplus/pcap/bluetooth.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Paolo Abeni (Italy)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* bluetooth data struct
|
||||
* By Paolo Abeni <paolo.abeni@email.it>
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007/09/22 02:10:17 guy Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
|
||||
#define _PCAP_BLUETOOTH_STRUCTS_H__
|
||||
|
||||
/*
|
||||
* Header prepended libpcap to each bluetooth h:4 frame.
|
||||
* fields are in network byte order
|
||||
*/
|
||||
typedef struct _pcap_bluetooth_h4_header {
|
||||
u_int32_t direction; /* if first bit is set direction is incoming */
|
||||
} pcap_bluetooth_h4_header;
|
||||
|
||||
|
||||
#endif
|
||||
934
pcappp/include/pcapplusplus/pcap/bpf.h
Normal file
934
pcappp/include/pcapplusplus/pcap/bpf.h
Normal file
@@ -0,0 +1,934 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.8 2008-09-22 20:16:01 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is libpcap's cut-down version of bpf.h; it includes only
|
||||
* the stuff needed for the code generator and the userland BPF
|
||||
* interpreter, and the libpcap APIs for setting filters, etc..
|
||||
*
|
||||
* "pcap-bpf.c" will include the native OS version, as it deals with
|
||||
* the OS's BPF implementation.
|
||||
*
|
||||
* XXX - should this all just be moved to "pcap.h"?
|
||||
*/
|
||||
|
||||
#ifndef BPF_MAJOR_VERSION
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* BSD style release date */
|
||||
#define BPF_RELEASE 199606
|
||||
|
||||
#ifdef MSDOS /* must be 32-bit */
|
||||
typedef long bpf_int32;
|
||||
typedef unsigned long bpf_u_int32;
|
||||
#else
|
||||
typedef int bpf_int32;
|
||||
typedef u_int bpf_u_int32;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Alignment macros. BPF_WORDALIGN rounds up to the next
|
||||
* even multiple of BPF_ALIGNMENT.
|
||||
*/
|
||||
#ifndef __NetBSD__
|
||||
#define BPF_ALIGNMENT sizeof(bpf_int32)
|
||||
#else
|
||||
#define BPF_ALIGNMENT sizeof(long)
|
||||
#endif
|
||||
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
|
||||
|
||||
#define BPF_MAXBUFSIZE 0x8000
|
||||
#define BPF_MINBUFSIZE 32
|
||||
|
||||
/*
|
||||
* Structure for "pcap_compile()", "pcap_setfilter()", etc..
|
||||
*/
|
||||
struct bpf_program {
|
||||
u_int bf_len;
|
||||
struct bpf_insn *bf_insns;
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct return by BIOCVERSION. This represents the version number of
|
||||
* the filter language described by the instruction encodings below.
|
||||
* bpf understands a program iff kernel_major == filter_major &&
|
||||
* kernel_minor >= filter_minor, that is, if the value returned by the
|
||||
* running kernel has the same major number and a minor number equal
|
||||
* equal to or less than the filter being downloaded. Otherwise, the
|
||||
* results are undefined, meaning an error may be returned or packets
|
||||
* may be accepted haphazardly.
|
||||
* It has nothing to do with the source code version.
|
||||
*/
|
||||
struct bpf_version {
|
||||
u_short bv_major;
|
||||
u_short bv_minor;
|
||||
};
|
||||
/* Current version number of filter architecture. */
|
||||
#define BPF_MAJOR_VERSION 1
|
||||
#define BPF_MINOR_VERSION 1
|
||||
|
||||
/*
|
||||
* Data-link level type codes.
|
||||
*
|
||||
* Do *NOT* add new values to this list without asking
|
||||
* "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
|
||||
* the risk of using a value that's already being used for some other
|
||||
* purpose, and of having tools that read libpcap-format captures not
|
||||
* being able to handle captures with your new DLT_ value, with no hope
|
||||
* that they will ever be changed to do so (as that would destroy their
|
||||
* ability to read captures using that value for that other purpose).
|
||||
*/
|
||||
|
||||
/*
|
||||
* These are the types that are the same on all platforms, and that
|
||||
* have been defined by <net/bpf.h> for ages.
|
||||
*/
|
||||
#define DLT_NULL 0 /* BSD loopback encapsulation */
|
||||
#define DLT_EN10MB 1 /* Ethernet (10Mb) */
|
||||
#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
|
||||
#define DLT_AX25 3 /* Amateur Radio AX.25 */
|
||||
#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
|
||||
#define DLT_CHAOS 5 /* Chaos */
|
||||
#define DLT_IEEE802 6 /* 802.5 Token Ring */
|
||||
#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
|
||||
#define DLT_SLIP 8 /* Serial Line IP */
|
||||
#define DLT_PPP 9 /* Point-to-point Protocol */
|
||||
#define DLT_FDDI 10 /* FDDI */
|
||||
|
||||
/*
|
||||
* These are types that are different on some platforms, and that
|
||||
* have been defined by <net/bpf.h> for ages. We use #ifdefs to
|
||||
* detect the BSDs that define them differently from the traditional
|
||||
* libpcap <net/bpf.h>
|
||||
*
|
||||
* XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
|
||||
* but I don't know what the right #define is for BSD/OS.
|
||||
*/
|
||||
#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define DLT_RAW 14 /* raw IP */
|
||||
#else
|
||||
#define DLT_RAW 12 /* raw IP */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given that the only OS that currently generates BSD/OS SLIP or PPP
|
||||
* is, well, BSD/OS, arguably everybody should have chosen its values
|
||||
* for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
|
||||
* didn't. So it goes.
|
||||
*/
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#ifndef DLT_SLIP_BSDOS
|
||||
#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
|
||||
#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
|
||||
#endif
|
||||
#else
|
||||
#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
|
||||
#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 17 is used for DLT_OLD_PFLOG in OpenBSD;
|
||||
* OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
|
||||
* 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
|
||||
*/
|
||||
|
||||
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
|
||||
|
||||
/*
|
||||
* Apparently Redback uses this for its SmartEdge 400/800. I hope
|
||||
* nobody else decided to use it, too.
|
||||
*/
|
||||
#define DLT_REDBACK_SMARTEDGE 32
|
||||
|
||||
/*
|
||||
* These values are defined by NetBSD; other platforms should refrain from
|
||||
* using them for other purposes, so that NetBSD savefiles with link
|
||||
* types of 50 or 51 can be read as this type on all platforms.
|
||||
*/
|
||||
#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
|
||||
#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
|
||||
|
||||
/*
|
||||
* The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
|
||||
* a link-layer type of 99 for the tcpdump it supplies. The link-layer
|
||||
* header has 6 bytes of unknown data, something that appears to be an
|
||||
* Ethernet type, and 36 bytes that appear to be 0 in at least one capture
|
||||
* I've seen.
|
||||
*/
|
||||
#define DLT_SYMANTEC_FIREWALL 99
|
||||
|
||||
/*
|
||||
* Values between 100 and 103 are used in capture file headers as
|
||||
* link-layer types corresponding to DLT_ types that differ
|
||||
* between platforms; don't use those values for new DLT_ new types.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This value was defined by libpcap 0.5; platforms that have defined
|
||||
* it with a different value should define it here with that value -
|
||||
* a link type of 104 in a save file will be mapped to DLT_C_HDLC,
|
||||
* whatever value that happens to be, so programs will correctly
|
||||
* handle files with that link type regardless of the value of
|
||||
* DLT_C_HDLC.
|
||||
*
|
||||
* The name DLT_C_HDLC was used by BSD/OS; we use that name for source
|
||||
* compatibility with programs written for BSD/OS.
|
||||
*
|
||||
* libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
|
||||
* for source compatibility with programs written for libpcap 0.5.
|
||||
*/
|
||||
#define DLT_C_HDLC 104 /* Cisco HDLC */
|
||||
#define DLT_CHDLC DLT_C_HDLC
|
||||
|
||||
#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
|
||||
|
||||
/*
|
||||
* 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
|
||||
* except when it isn't. (I.e., sometimes it's just raw IP, and
|
||||
* sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
|
||||
* so that we don't have to worry about the link-layer header.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
|
||||
* with other values.
|
||||
* DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
|
||||
* (DLCI, etc.).
|
||||
*/
|
||||
#define DLT_FRELAY 107
|
||||
|
||||
/*
|
||||
* OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
|
||||
* that the AF_ type in the link-layer header is in network byte order.
|
||||
*
|
||||
* DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
|
||||
* we don't use 12 for it in OSes other than OpenBSD.
|
||||
*/
|
||||
#ifdef __OpenBSD__
|
||||
#define DLT_LOOP 12
|
||||
#else
|
||||
#define DLT_LOOP 108
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
|
||||
* DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
|
||||
* than OpenBSD.
|
||||
*/
|
||||
#ifdef __OpenBSD__
|
||||
#define DLT_ENC 13
|
||||
#else
|
||||
#define DLT_ENC 109
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Values between 110 and 112 are reserved for use in capture file headers
|
||||
* as link-layer types corresponding to DLT_ types that might differ
|
||||
* between platforms; don't use those values for new DLT_ types
|
||||
* other than the corresponding DLT_ types.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is for Linux cooked sockets.
|
||||
*/
|
||||
#define DLT_LINUX_SLL 113
|
||||
|
||||
/*
|
||||
* Apple LocalTalk hardware.
|
||||
*/
|
||||
#define DLT_LTALK 114
|
||||
|
||||
/*
|
||||
* Acorn Econet.
|
||||
*/
|
||||
#define DLT_ECONET 115
|
||||
|
||||
/*
|
||||
* Reserved for use with OpenBSD ipfilter.
|
||||
*/
|
||||
#define DLT_IPFILTER 116
|
||||
|
||||
/*
|
||||
* OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
|
||||
* in SuSE 6.3, so we can't use 17 for it in capture-file headers.
|
||||
*
|
||||
* XXX: is there a conflict with DLT_PFSYNC 18 as well?
|
||||
*/
|
||||
#ifdef __OpenBSD__
|
||||
#define DLT_OLD_PFLOG 17
|
||||
#define DLT_PFSYNC 18
|
||||
#endif
|
||||
#define DLT_PFLOG 117
|
||||
|
||||
/*
|
||||
* Registered for Cisco-internal use.
|
||||
*/
|
||||
#define DLT_CISCO_IOS 118
|
||||
|
||||
/*
|
||||
* For 802.11 cards using the Prism II chips, with a link-layer
|
||||
* header including Prism monitor mode information plus an 802.11
|
||||
* header.
|
||||
*/
|
||||
#define DLT_PRISM_HEADER 119
|
||||
|
||||
/*
|
||||
* Reserved for Aironet 802.11 cards, with an Aironet link-layer header
|
||||
* (see Doug Ambrisko's FreeBSD patches).
|
||||
*/
|
||||
#define DLT_AIRONET_HEADER 120
|
||||
|
||||
/*
|
||||
* Reserved for Siemens HiPath HDLC.
|
||||
*/
|
||||
#define DLT_HHDLC 121
|
||||
|
||||
/*
|
||||
* This is for RFC 2625 IP-over-Fibre Channel.
|
||||
*
|
||||
* This is not for use with raw Fibre Channel, where the link-layer
|
||||
* header starts with a Fibre Channel frame header; it's for IP-over-FC,
|
||||
* where the link-layer header starts with an RFC 2625 Network_Header
|
||||
* field.
|
||||
*/
|
||||
#define DLT_IP_OVER_FC 122
|
||||
|
||||
/*
|
||||
* This is for Full Frontal ATM on Solaris with SunATM, with a
|
||||
* pseudo-header followed by an AALn PDU.
|
||||
*
|
||||
* There may be other forms of Full Frontal ATM on other OSes,
|
||||
* with different pseudo-headers.
|
||||
*
|
||||
* If ATM software returns a pseudo-header with VPI/VCI information
|
||||
* (and, ideally, packet type information, e.g. signalling, ILMI,
|
||||
* LANE, LLC-multiplexed traffic, etc.), it should not use
|
||||
* DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
|
||||
* and the like don't have to infer the presence or absence of a
|
||||
* pseudo-header and the form of the pseudo-header.
|
||||
*/
|
||||
#define DLT_SUNATM 123 /* Solaris+SunATM */
|
||||
|
||||
/*
|
||||
* Reserved as per request from Kent Dahlgren <kent@praesum.com>
|
||||
* for private use.
|
||||
*/
|
||||
#define DLT_RIO 124 /* RapidIO */
|
||||
#define DLT_PCI_EXP 125 /* PCI Express */
|
||||
#define DLT_AURORA 126 /* Xilinx Aurora link layer */
|
||||
|
||||
/*
|
||||
* Header for 802.11 plus a number of bits of link-layer information
|
||||
* including radio information, used by some recent BSD drivers as
|
||||
* well as the madwifi Atheros driver for Linux.
|
||||
*/
|
||||
#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
|
||||
|
||||
/*
|
||||
* Reserved for the TZSP encapsulation, as per request from
|
||||
* Chris Waters <chris.waters@networkchemistry.com>
|
||||
* TZSP is a generic encapsulation for any other link type,
|
||||
* which includes a means to include meta-information
|
||||
* with the packet, e.g. signal strength and channel
|
||||
* for 802.11 packets.
|
||||
*/
|
||||
#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
|
||||
|
||||
/*
|
||||
* BSD's ARCNET headers have the source host, destination host,
|
||||
* and type at the beginning of the packet; that's what's handed
|
||||
* up to userland via BPF.
|
||||
*
|
||||
* Linux's ARCNET headers, however, have a 2-byte offset field
|
||||
* between the host IDs and the type; that's what's handed up
|
||||
* to userland via PF_PACKET sockets.
|
||||
*
|
||||
* We therefore have to have separate DLT_ values for them.
|
||||
*/
|
||||
#define DLT_ARCNET_LINUX 129 /* ARCNET */
|
||||
|
||||
/*
|
||||
* Juniper-private data link types, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>. The DLT_s are used
|
||||
* for passing on chassis-internal metainformation such as
|
||||
* QOS profiles, etc..
|
||||
*/
|
||||
#define DLT_JUNIPER_MLPPP 130
|
||||
#define DLT_JUNIPER_MLFR 131
|
||||
#define DLT_JUNIPER_ES 132
|
||||
#define DLT_JUNIPER_GGSN 133
|
||||
#define DLT_JUNIPER_MFR 134
|
||||
#define DLT_JUNIPER_ATM2 135
|
||||
#define DLT_JUNIPER_SERVICES 136
|
||||
#define DLT_JUNIPER_ATM1 137
|
||||
|
||||
/*
|
||||
* Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
|
||||
* <dieter@apple.com>. The header that's presented is an Ethernet-like
|
||||
* header:
|
||||
*
|
||||
* #define FIREWIRE_EUI64_LEN 8
|
||||
* struct firewire_header {
|
||||
* u_char firewire_dhost[FIREWIRE_EUI64_LEN];
|
||||
* u_char firewire_shost[FIREWIRE_EUI64_LEN];
|
||||
* u_short firewire_type;
|
||||
* };
|
||||
*
|
||||
* with "firewire_type" being an Ethernet type value, rather than,
|
||||
* for example, raw GASP frames being handed up.
|
||||
*/
|
||||
#define DLT_APPLE_IP_OVER_IEEE1394 138
|
||||
|
||||
/*
|
||||
* Various SS7 encapsulations, as per a request from Jeff Morriss
|
||||
* <jeff.morriss[AT]ulticom.com> and subsequent discussions.
|
||||
*/
|
||||
#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
|
||||
#define DLT_MTP2 140 /* MTP2, without pseudo-header */
|
||||
#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
|
||||
#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
|
||||
|
||||
/*
|
||||
* DOCSIS MAC frames.
|
||||
*/
|
||||
#define DLT_DOCSIS 143
|
||||
|
||||
/*
|
||||
* Linux-IrDA packets. Protocol defined at http://www.irda.org.
|
||||
* Those packets include IrLAP headers and above (IrLMP...), but
|
||||
* don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
|
||||
* framing can be handled by the hardware and depend on the bitrate.
|
||||
* This is exactly the format you would get capturing on a Linux-IrDA
|
||||
* interface (irdaX), but not on a raw serial port.
|
||||
* Note the capture is done in "Linux-cooked" mode, so each packet include
|
||||
* a fake packet header (struct sll_header). This is because IrDA packet
|
||||
* decoding is dependant on the direction of the packet (incomming or
|
||||
* outgoing).
|
||||
* When/if other platform implement IrDA capture, we may revisit the
|
||||
* issue and define a real DLT_IRDA...
|
||||
* Jean II
|
||||
*/
|
||||
#define DLT_LINUX_IRDA 144
|
||||
|
||||
/*
|
||||
* Reserved for IBM SP switch and IBM Next Federation switch.
|
||||
*/
|
||||
#define DLT_IBM_SP 145
|
||||
#define DLT_IBM_SN 146
|
||||
|
||||
/*
|
||||
* Reserved for private use. If you have some link-layer header type
|
||||
* that you want to use within your organization, with the capture files
|
||||
* using that link-layer header type not ever be sent outside your
|
||||
* organization, you can use these values.
|
||||
*
|
||||
* No libpcap release will use these for any purpose, nor will any
|
||||
* tcpdump release use them, either.
|
||||
*
|
||||
* Do *NOT* use these in capture files that you expect anybody not using
|
||||
* your private versions of capture-file-reading tools to read; in
|
||||
* particular, do *NOT* use them in products, otherwise you may find that
|
||||
* people won't be able to use tcpdump, or snort, or Ethereal, or... to
|
||||
* read capture files from your firewall/intrusion detection/traffic
|
||||
* monitoring/etc. appliance, or whatever product uses that DLT_ value,
|
||||
* and you may also find that the developers of those applications will
|
||||
* not accept patches to let them read those files.
|
||||
*
|
||||
* Also, do not use them if somebody might send you a capture using them
|
||||
* for *their* private type and tools using them for *your* private type
|
||||
* would have to read them.
|
||||
*
|
||||
* Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
|
||||
* as per the comment above, and use the type you're given.
|
||||
*/
|
||||
#define DLT_USER0 147
|
||||
#define DLT_USER1 148
|
||||
#define DLT_USER2 149
|
||||
#define DLT_USER3 150
|
||||
#define DLT_USER4 151
|
||||
#define DLT_USER5 152
|
||||
#define DLT_USER6 153
|
||||
#define DLT_USER7 154
|
||||
#define DLT_USER8 155
|
||||
#define DLT_USER9 156
|
||||
#define DLT_USER10 157
|
||||
#define DLT_USER11 158
|
||||
#define DLT_USER12 159
|
||||
#define DLT_USER13 160
|
||||
#define DLT_USER14 161
|
||||
#define DLT_USER15 162
|
||||
|
||||
/*
|
||||
* For future use with 802.11 captures - defined by AbsoluteValue
|
||||
* Systems to store a number of bits of link-layer information
|
||||
* including radio information:
|
||||
*
|
||||
* http://www.shaftnet.org/~pizza/software/capturefrm.txt
|
||||
*
|
||||
* but it might be used by some non-AVS drivers now or in the
|
||||
* future.
|
||||
*/
|
||||
#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>. The DLT_s are used
|
||||
* for passing on chassis-internal metainformation such as
|
||||
* QOS profiles, etc..
|
||||
*/
|
||||
#define DLT_JUNIPER_MONITOR 164
|
||||
|
||||
/*
|
||||
* Reserved for BACnet MS/TP.
|
||||
*/
|
||||
#define DLT_BACNET_MS_TP 165
|
||||
|
||||
/*
|
||||
* Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
|
||||
*
|
||||
* This is used in some OSes to allow a kernel socket filter to distinguish
|
||||
* between incoming and outgoing packets, on a socket intended to
|
||||
* supply pppd with outgoing packets so it can do dial-on-demand and
|
||||
* hangup-on-lack-of-demand; incoming packets are filtered out so they
|
||||
* don't cause pppd to hold the connection up (you don't want random
|
||||
* input packets such as port scans, packets from old lost connections,
|
||||
* etc. to force the connection to stay up).
|
||||
*
|
||||
* The first byte of the PPP header (0xff03) is modified to accomodate
|
||||
* the direction - 0x00 = IN, 0x01 = OUT.
|
||||
*/
|
||||
#define DLT_PPP_PPPD 166
|
||||
|
||||
/*
|
||||
* Names for backwards compatibility with older versions of some PPP
|
||||
* software; new software should use DLT_PPP_PPPD.
|
||||
*/
|
||||
#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
|
||||
#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>. The DLT_s are used
|
||||
* for passing on chassis-internal metainformation such as
|
||||
* QOS profiles, cookies, etc..
|
||||
*/
|
||||
#define DLT_JUNIPER_PPPOE 167
|
||||
#define DLT_JUNIPER_PPPOE_ATM 168
|
||||
|
||||
#define DLT_GPRS_LLC 169 /* GPRS LLC */
|
||||
#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
|
||||
#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
|
||||
|
||||
/*
|
||||
* Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
|
||||
* monitoring equipment.
|
||||
*/
|
||||
#define DLT_GCOM_T1E1 172
|
||||
#define DLT_GCOM_SERIAL 173
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>. The DLT_ is used
|
||||
* for internal communication to Physical Interface Cards (PIC)
|
||||
*/
|
||||
#define DLT_JUNIPER_PIC_PEER 174
|
||||
|
||||
/*
|
||||
* Link types requested by Gregor Maier <gregor@endace.com> of Endace
|
||||
* Measurement Systems. They add an ERF header (see
|
||||
* http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
|
||||
* the link-layer header.
|
||||
*/
|
||||
#define DLT_ERF_ETH 175 /* Ethernet */
|
||||
#define DLT_ERF_POS 176 /* Packet-over-SONET */
|
||||
|
||||
/*
|
||||
* Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
|
||||
* for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
|
||||
* includes additional information before the LAPD header, so it's
|
||||
* not necessarily a generic LAPD header.
|
||||
*/
|
||||
#define DLT_LINUX_LAPD 177
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>.
|
||||
* The DLT_ are used for prepending meta-information
|
||||
* like interface index, interface name
|
||||
* before standard Ethernet, PPP, Frelay & C-HDLC Frames
|
||||
*/
|
||||
#define DLT_JUNIPER_ETHER 178
|
||||
#define DLT_JUNIPER_PPP 179
|
||||
#define DLT_JUNIPER_FRELAY 180
|
||||
#define DLT_JUNIPER_CHDLC 181
|
||||
|
||||
/*
|
||||
* Multi Link Frame Relay (FRF.16)
|
||||
*/
|
||||
#define DLT_MFR 182
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>.
|
||||
* The DLT_ is used for internal communication with a
|
||||
* voice Adapter Card (PIC)
|
||||
*/
|
||||
#define DLT_JUNIPER_VP 183
|
||||
|
||||
/*
|
||||
* Arinc 429 frames.
|
||||
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
|
||||
* Every frame contains a 32bit A429 label.
|
||||
* More documentation on Arinc 429 can be found at
|
||||
* http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
|
||||
*/
|
||||
#define DLT_A429 184
|
||||
|
||||
/*
|
||||
* Arinc 653 Interpartition Communication messages.
|
||||
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
|
||||
* Please refer to the A653-1 standard for more information.
|
||||
*/
|
||||
#define DLT_A653_ICM 185
|
||||
|
||||
/*
|
||||
* USB packets, beginning with a USB setup header; requested by
|
||||
* Paolo Abeni <paolo.abeni@email.it>.
|
||||
*/
|
||||
#define DLT_USB 186
|
||||
|
||||
/*
|
||||
* Bluetooth HCI UART transport layer (part H:4); requested by
|
||||
* Paolo Abeni.
|
||||
*/
|
||||
#define DLT_BLUETOOTH_HCI_H4 187
|
||||
|
||||
/*
|
||||
* IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
|
||||
* <cruz_petagay@bah.com>.
|
||||
*/
|
||||
#define DLT_IEEE802_16_MAC_CPS 188
|
||||
|
||||
/*
|
||||
* USB packets, beginning with a Linux USB header; requested by
|
||||
* Paolo Abeni <paolo.abeni@email.it>.
|
||||
*/
|
||||
#define DLT_USB_LINUX 189
|
||||
|
||||
/*
|
||||
* Controller Area Network (CAN) v. 2.0B packets.
|
||||
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
|
||||
* Used to dump CAN packets coming from a CAN Vector board.
|
||||
* More documentation on the CAN v2.0B frames can be found at
|
||||
* http://www.can-cia.org/downloads/?269
|
||||
*/
|
||||
#define DLT_CAN20B 190
|
||||
|
||||
/*
|
||||
* IEEE 802.15.4, with address fields padded, as is done by Linux
|
||||
* drivers; requested by Juergen Schimmer.
|
||||
*/
|
||||
#define DLT_IEEE802_15_4_LINUX 191
|
||||
|
||||
/*
|
||||
* Per Packet Information encapsulated packets.
|
||||
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
|
||||
*/
|
||||
#define DLT_PPI 192
|
||||
|
||||
/*
|
||||
* Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
|
||||
* requested by Charles Clancy.
|
||||
*/
|
||||
#define DLT_IEEE802_16_MAC_CPS_RADIO 193
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>.
|
||||
* The DLT_ is used for internal communication with a
|
||||
* integrated service module (ISM).
|
||||
*/
|
||||
#define DLT_JUNIPER_ISM 194
|
||||
|
||||
/*
|
||||
* IEEE 802.15.4, exactly as it appears in the spec (no padding, no
|
||||
* nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
|
||||
*/
|
||||
#define DLT_IEEE802_15_4 195
|
||||
|
||||
/*
|
||||
* Various link-layer types, with a pseudo-header, for SITA
|
||||
* (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
|
||||
*/
|
||||
#define DLT_SITA 196
|
||||
|
||||
/*
|
||||
* Various link-layer types, with a pseudo-header, for Endace DAG cards;
|
||||
* encapsulates Endace ERF records. Requested by Stephen Donnelly
|
||||
* <stephen@endace.com>.
|
||||
*/
|
||||
#define DLT_ERF 197
|
||||
|
||||
/*
|
||||
* Special header prepended to Ethernet packets when capturing from a
|
||||
* u10 Networks board. Requested by Phil Mulholland
|
||||
* <phil@u10networks.com>.
|
||||
*/
|
||||
#define DLT_RAIF1 198
|
||||
|
||||
/*
|
||||
* IPMB packet for IPMI, beginning with the I2C slave address, followed
|
||||
* by the netFn and LUN, etc.. Requested by Chanthy Toeung
|
||||
* <chanthy.toeung@ca.kontron.com>.
|
||||
*/
|
||||
#define DLT_IPMB 199
|
||||
|
||||
/*
|
||||
* Juniper-private data link type, as per request from
|
||||
* Hannes Gredler <hannes@juniper.net>.
|
||||
* The DLT_ is used for capturing data on a secure tunnel interface.
|
||||
*/
|
||||
#define DLT_JUNIPER_ST 200
|
||||
|
||||
/*
|
||||
* Bluetooth HCI UART transport layer (part H:4), with pseudo-header
|
||||
* that includes direction information; requested by Paolo Abeni.
|
||||
*/
|
||||
#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
|
||||
|
||||
/*
|
||||
* AX.25 packet with a 1-byte KISS header; see
|
||||
*
|
||||
* http://www.ax25.net/kiss.htm
|
||||
*
|
||||
* as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
|
||||
*/
|
||||
#define DLT_AX25_KISS 202
|
||||
|
||||
/*
|
||||
* LAPD packets from an ISDN channel, starting with the address field,
|
||||
* with no pseudo-header.
|
||||
* Requested by Varuna De Silva <varunax@gmail.com>.
|
||||
*/
|
||||
#define DLT_LAPD 203
|
||||
|
||||
/*
|
||||
* Variants of various link-layer headers, with a one-byte direction
|
||||
* pseudo-header prepended - zero means "received by this host",
|
||||
* non-zero (any non-zero value) means "sent by this host" - as per
|
||||
* Will Barker <w.barker@zen.co.uk>.
|
||||
*/
|
||||
#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
|
||||
#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
|
||||
#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
|
||||
#define DLT_LAPB_WITH_DIR 207 /* LAPB */
|
||||
|
||||
/*
|
||||
* 208 is reserved for an as-yet-unspecified proprietary link-layer
|
||||
* type, as requested by Will Barker.
|
||||
*/
|
||||
|
||||
/*
|
||||
* IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
|
||||
* <avn@pigeonpoint.com>.
|
||||
*/
|
||||
#define DLT_IPMB_LINUX 209
|
||||
|
||||
/*
|
||||
* FlexRay automotive bus - http://www.flexray.com/ - as requested
|
||||
* by Hannes Kaelber <hannes.kaelber@x2e.de>.
|
||||
*/
|
||||
#define DLT_FLEXRAY 210
|
||||
|
||||
/*
|
||||
* Media Oriented Systems Transport (MOST) bus for multimedia
|
||||
* transport - http://www.mostcooperation.com/ - as requested
|
||||
* by Hannes Kaelber <hannes.kaelber@x2e.de>.
|
||||
*/
|
||||
#define DLT_MOST 211
|
||||
|
||||
/*
|
||||
* Local Interconnect Network (LIN) bus for vehicle networks -
|
||||
* http://www.lin-subbus.org/ - as requested by Hannes Kaelber
|
||||
* <hannes.kaelber@x2e.de>.
|
||||
*/
|
||||
#define DLT_LIN 212
|
||||
|
||||
/*
|
||||
* X2E-private data link type used for serial line capture,
|
||||
* as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
|
||||
*/
|
||||
#define DLT_X2E_SERIAL 213
|
||||
|
||||
/*
|
||||
* X2E-private data link type used for the Xoraya data logger
|
||||
* family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
|
||||
*/
|
||||
#define DLT_X2E_XORAYA 214
|
||||
|
||||
/*
|
||||
* IEEE 802.15.4, exactly as it appears in the spec (no padding, no
|
||||
* nothing), but with the PHY-level data for non-ASK PHYs (4 octets
|
||||
* of 0 as preamble, one octet of SFD, one octet of frame length+
|
||||
* reserved bit, and then the MAC-layer data, starting with the
|
||||
* frame control field).
|
||||
*
|
||||
* Requested by Max Filippov <jcmvbkbc@gmail.com>.
|
||||
*/
|
||||
#define DLT_IEEE802_15_4_NONASK_PHY 215
|
||||
|
||||
|
||||
/*
|
||||
* DLT and savefile link type values are split into a class and
|
||||
* a member of that class. A class value of 0 indicates a regular
|
||||
* DLT_/LINKTYPE_ value.
|
||||
*/
|
||||
#define DLT_CLASS(x) ((x) & 0x03ff0000)
|
||||
|
||||
/*
|
||||
* NetBSD-specific generic "raw" link type. The class value indicates
|
||||
* that this is the generic raw type, and the lower 16 bits are the
|
||||
* address family we're dealing with. Those values are NetBSD-specific;
|
||||
* do not assume that they correspond to AF_ values for your operating
|
||||
* system.
|
||||
*/
|
||||
#define DLT_CLASS_NETBSD_RAWAF 0x02240000
|
||||
#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
|
||||
#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
|
||||
#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
|
||||
|
||||
|
||||
/*
|
||||
* The instruction encodings.
|
||||
*/
|
||||
/* instruction classes */
|
||||
#define BPF_CLASS(code) ((code) & 0x07)
|
||||
#define BPF_LD 0x00
|
||||
#define BPF_LDX 0x01
|
||||
#define BPF_ST 0x02
|
||||
#define BPF_STX 0x03
|
||||
#define BPF_ALU 0x04
|
||||
#define BPF_JMP 0x05
|
||||
#define BPF_RET 0x06
|
||||
#define BPF_MISC 0x07
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
#define BPF_W 0x00
|
||||
#define BPF_H 0x08
|
||||
#define BPF_B 0x10
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
#define BPF_IMM 0x00
|
||||
#define BPF_ABS 0x20
|
||||
#define BPF_IND 0x40
|
||||
#define BPF_MEM 0x60
|
||||
#define BPF_LEN 0x80
|
||||
#define BPF_MSH 0xa0
|
||||
|
||||
/* alu/jmp fields */
|
||||
#define BPF_OP(code) ((code) & 0xf0)
|
||||
#define BPF_ADD 0x00
|
||||
#define BPF_SUB 0x10
|
||||
#define BPF_MUL 0x20
|
||||
#define BPF_DIV 0x30
|
||||
#define BPF_OR 0x40
|
||||
#define BPF_AND 0x50
|
||||
#define BPF_LSH 0x60
|
||||
#define BPF_RSH 0x70
|
||||
#define BPF_NEG 0x80
|
||||
#define BPF_JA 0x00
|
||||
#define BPF_JEQ 0x10
|
||||
#define BPF_JGT 0x20
|
||||
#define BPF_JGE 0x30
|
||||
#define BPF_JSET 0x40
|
||||
#define BPF_SRC(code) ((code) & 0x08)
|
||||
#define BPF_K 0x00
|
||||
#define BPF_X 0x08
|
||||
|
||||
/* ret - BPF_K and BPF_X also apply */
|
||||
#define BPF_RVAL(code) ((code) & 0x18)
|
||||
#define BPF_A 0x10
|
||||
|
||||
/* misc */
|
||||
#define BPF_MISCOP(code) ((code) & 0xf8)
|
||||
#define BPF_TAX 0x00
|
||||
#define BPF_TXA 0x80
|
||||
|
||||
/*
|
||||
* The instruction data structure.
|
||||
*/
|
||||
struct bpf_insn {
|
||||
u_short code;
|
||||
u_char jt;
|
||||
u_char jf;
|
||||
bpf_u_int32 k;
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros for insn array initializers.
|
||||
*/
|
||||
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
|
||||
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
|
||||
|
||||
#if __STDC__ || defined(__cplusplus)
|
||||
extern int bpf_validate(const struct bpf_insn *, int);
|
||||
extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
|
||||
#else
|
||||
extern int bpf_validate();
|
||||
extern u_int bpf_filter();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
|
||||
*/
|
||||
#define BPF_MEMWORDS 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
89
pcappp/include/pcapplusplus/pcap/namedb.h
Normal file
89
pcappp/include/pcapplusplus/pcap/namedb.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 1996
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the Computer Systems
|
||||
* Engineering Group at Lawrence Berkeley Laboratory.
|
||||
* 4. Neither the name of the University nor of the Laboratory may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006/10/04 18:09:22 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef lib_pcap_namedb_h
|
||||
#define lib_pcap_namedb_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* As returned by the pcap_next_etherent()
|
||||
* XXX this stuff doesn't belong in this interface, but this
|
||||
* library already must do name to address translation, so
|
||||
* on systems that don't have support for /etc/ethers, we
|
||||
* export these hooks since they'll
|
||||
*/
|
||||
struct pcap_etherent {
|
||||
u_char addr[6];
|
||||
char name[122];
|
||||
};
|
||||
#ifndef PCAP_ETHERS_FILE
|
||||
#define PCAP_ETHERS_FILE "/etc/ethers"
|
||||
#endif
|
||||
struct pcap_etherent *pcap_next_etherent(FILE *);
|
||||
u_char *pcap_ether_hostton(const char*);
|
||||
u_char *pcap_ether_aton(const char *);
|
||||
|
||||
bpf_u_int32 **pcap_nametoaddr(const char *);
|
||||
#ifdef INET6
|
||||
struct addrinfo *pcap_nametoaddrinfo(const char *);
|
||||
#endif
|
||||
bpf_u_int32 pcap_nametonetaddr(const char *);
|
||||
|
||||
int pcap_nametoport(const char *, int *, int *);
|
||||
int pcap_nametoportrange(const char *, int *, int *, int *);
|
||||
int pcap_nametoproto(const char *);
|
||||
int pcap_nametoeproto(const char *);
|
||||
int pcap_nametollc(const char *);
|
||||
/*
|
||||
* If a protocol is unknown, PROTO_UNDEF is returned.
|
||||
* Also, pcap_nametoport() returns the protocol along with the port number.
|
||||
* If there are ambiguous entried in /etc/services (i.e. domain
|
||||
* can be either tcp or udp) PROTO_UNDEF is returned.
|
||||
*/
|
||||
#define PROTO_UNDEF -1
|
||||
|
||||
/* XXX move these to pcap-int.h? */
|
||||
int __pcap_atodn(const char *, bpf_u_int32 *);
|
||||
int __pcap_atoin(const char *, bpf_u_int32 *);
|
||||
u_short __pcap_nametodnaddr(const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
407
pcappp/include/pcapplusplus/pcap/pcap.h
Normal file
407
pcappp/include/pcapplusplus/pcap/pcap.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
|
||||
/*
|
||||
* Copyright (c) 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the Computer Systems
|
||||
* Engineering Group at Lawrence Berkeley Laboratory.
|
||||
* 4. Neither the name of the University nor of the Laboratory may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef lib_pcap_pcap_h
|
||||
#define lib_pcap_pcap_h
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <pcap-stdinc.h>
|
||||
#elif defined(MSDOS)
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h> /* u_int, u_char etc. */
|
||||
#else /* UN*X */
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#endif /* WIN32/MSDOS/UN*X */
|
||||
|
||||
#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
|
||||
#include <pcap/bpf.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_REMOTE
|
||||
// We have to define the SOCKET here, although it has been defined in sockutils.h
|
||||
// This is to avoid the distribution of the 'sockutils.h' file around
|
||||
// (for example in the WinPcap developer's pack)
|
||||
#ifndef SOCKET
|
||||
#ifdef WIN32
|
||||
#define SOCKET unsigned int
|
||||
#else
|
||||
#define SOCKET int
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PCAP_VERSION_MAJOR 2
|
||||
#define PCAP_VERSION_MINOR 4
|
||||
|
||||
#define PCAP_ERRBUF_SIZE 256
|
||||
|
||||
/*
|
||||
* Compatibility for systems that have a bpf.h that
|
||||
* predates the bpf typedefs for 64-bit support.
|
||||
*/
|
||||
#if BPF_RELEASE - 0 < 199406
|
||||
typedef int bpf_int32;
|
||||
typedef u_int bpf_u_int32;
|
||||
#endif
|
||||
|
||||
typedef struct pcap pcap_t;
|
||||
typedef struct pcap_dumper pcap_dumper_t;
|
||||
typedef struct pcap_if pcap_if_t;
|
||||
typedef struct pcap_addr pcap_addr_t;
|
||||
|
||||
/*
|
||||
* The first record in the file contains saved values for some
|
||||
* of the flags used in the printout phases of tcpdump.
|
||||
* Many fields here are 32 bit ints so compilers won't insert unwanted
|
||||
* padding; these files need to be interchangeable across architectures.
|
||||
*
|
||||
* Do not change the layout of this structure, in any way (this includes
|
||||
* changes that only affect the length of fields in this structure).
|
||||
*
|
||||
* Also, do not change the interpretation of any of the members of this
|
||||
* structure, in any way (this includes using values other than
|
||||
* LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
|
||||
* field).
|
||||
*
|
||||
* Instead:
|
||||
*
|
||||
* introduce a new structure for the new format, if the layout
|
||||
* of the structure changed;
|
||||
*
|
||||
* send mail to "tcpdump-workers@lists.tcpdump.org", requesting
|
||||
* a new magic number for your new capture file format, and, when
|
||||
* you get the new magic number, put it in "savefile.c";
|
||||
*
|
||||
* use that magic number for save files with the changed file
|
||||
* header;
|
||||
*
|
||||
* make the code in "savefile.c" capable of reading files with
|
||||
* the old file header as well as files with the new file header
|
||||
* (using the magic number to determine the header format).
|
||||
*
|
||||
* Then supply the changes as a patch at
|
||||
*
|
||||
* http://sourceforge.net/projects/libpcap/
|
||||
*
|
||||
* so that future versions of libpcap and programs that use it (such as
|
||||
* tcpdump) will be able to read your new capture file format.
|
||||
*/
|
||||
struct pcap_file_header {
|
||||
bpf_u_int32 magic;
|
||||
u_short version_major;
|
||||
u_short version_minor;
|
||||
bpf_int32 thiszone; /* gmt to local correction */
|
||||
bpf_u_int32 sigfigs; /* accuracy of timestamps */
|
||||
bpf_u_int32 snaplen; /* max length saved portion of each pkt */
|
||||
bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros for the value returned by pcap_datalink_ext().
|
||||
*
|
||||
* If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
|
||||
* gives the FCS length of packets in the capture.
|
||||
*/
|
||||
#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000)
|
||||
#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28)
|
||||
#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000)
|
||||
|
||||
typedef enum {
|
||||
PCAP_D_INOUT = 0,
|
||||
PCAP_D_IN,
|
||||
PCAP_D_OUT
|
||||
} pcap_direction_t;
|
||||
|
||||
/*
|
||||
* Generic per-packet information, as supplied by libpcap.
|
||||
*
|
||||
* The time stamp can and should be a "struct timeval", regardless of
|
||||
* whether your system supports 32-bit tv_sec in "struct timeval",
|
||||
* 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
|
||||
* and 64-bit applications. The on-disk format of savefiles uses 32-bit
|
||||
* tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
|
||||
* and 64-bit versions of libpcap, even if they're on the same platform,
|
||||
* should supply the appropriate version of "struct timeval", even if
|
||||
* that's not what the underlying packet capture mechanism supplies.
|
||||
*/
|
||||
struct pcap_pkthdr {
|
||||
struct timeval ts; /* time stamp */
|
||||
bpf_u_int32 caplen; /* length of portion present */
|
||||
bpf_u_int32 len; /* length this packet (off wire) */
|
||||
};
|
||||
|
||||
/*
|
||||
* As returned by the pcap_stats()
|
||||
*/
|
||||
struct pcap_stat {
|
||||
u_int ps_recv; /* number of packets received */
|
||||
u_int ps_drop; /* number of packets dropped */
|
||||
u_int ps_ifdrop; /* drops by interface XXX not yet supported */
|
||||
#ifdef HAVE_REMOTE
|
||||
u_int ps_capt; /* number of packets that are received by the application; please get rid off the Win32 ifdef */
|
||||
u_int ps_sent; /* number of packets sent by the server on the network */
|
||||
u_int ps_netdrop; /* number of packets lost on the network */
|
||||
#endif /* HAVE_REMOTE */
|
||||
};
|
||||
|
||||
#ifdef MSDOS
|
||||
/*
|
||||
* As returned by the pcap_stats_ex()
|
||||
*/
|
||||
struct pcap_stat_ex {
|
||||
u_long rx_packets; /* total packets received */
|
||||
u_long tx_packets; /* total packets transmitted */
|
||||
u_long rx_bytes; /* total bytes received */
|
||||
u_long tx_bytes; /* total bytes transmitted */
|
||||
u_long rx_errors; /* bad packets received */
|
||||
u_long tx_errors; /* packet transmit problems */
|
||||
u_long rx_dropped; /* no space in Rx buffers */
|
||||
u_long tx_dropped; /* no space available for Tx */
|
||||
u_long multicast; /* multicast packets received */
|
||||
u_long collisions;
|
||||
|
||||
/* detailed rx_errors: */
|
||||
u_long rx_length_errors;
|
||||
u_long rx_over_errors; /* receiver ring buff overflow */
|
||||
u_long rx_crc_errors; /* recv'd pkt with crc error */
|
||||
u_long rx_frame_errors; /* recv'd frame alignment error */
|
||||
u_long rx_fifo_errors; /* recv'r fifo overrun */
|
||||
u_long rx_missed_errors; /* recv'r missed packet */
|
||||
|
||||
/* detailed tx_errors */
|
||||
u_long tx_aborted_errors;
|
||||
u_long tx_carrier_errors;
|
||||
u_long tx_fifo_errors;
|
||||
u_long tx_heartbeat_errors;
|
||||
u_long tx_window_errors;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Item in a list of interfaces.
|
||||
*/
|
||||
struct pcap_if {
|
||||
struct pcap_if *next;
|
||||
char *name; /* name to hand to "pcap_open_live()" */
|
||||
char *description; /* textual description of interface, or NULL */
|
||||
struct pcap_addr *addresses;
|
||||
bpf_u_int32 flags; /* PCAP_IF_ interface flags */
|
||||
};
|
||||
|
||||
#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
|
||||
|
||||
/*
|
||||
* Representation of an interface address.
|
||||
*/
|
||||
struct pcap_addr {
|
||||
struct pcap_addr *next;
|
||||
struct sockaddr *addr; /* address */
|
||||
struct sockaddr *netmask; /* netmask for that address */
|
||||
struct sockaddr *broadaddr; /* broadcast address for that address */
|
||||
struct sockaddr *dstaddr; /* P2P destination address for that address */
|
||||
};
|
||||
|
||||
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
|
||||
const u_char *);
|
||||
|
||||
/*
|
||||
* Error codes for the pcap API.
|
||||
* These will all be negative, so you can check for the success or
|
||||
* failure of a call that returns these codes by checking for a
|
||||
* negative value.
|
||||
*/
|
||||
#define PCAP_ERROR -1 /* generic error code */
|
||||
#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */
|
||||
#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */
|
||||
#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */
|
||||
#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */
|
||||
#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
|
||||
#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
|
||||
#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
|
||||
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
|
||||
|
||||
/*
|
||||
* Warning codes for the pcap API.
|
||||
* These will all be positive and non-zero, so they won't look like
|
||||
* errors.
|
||||
*/
|
||||
#define PCAP_WARNING 1 /* generic warning code */
|
||||
#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
|
||||
|
||||
char *pcap_lookupdev(char *);
|
||||
int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
|
||||
|
||||
pcap_t *pcap_create(const char *, char *);
|
||||
int pcap_set_snaplen(pcap_t *, int);
|
||||
int pcap_set_promisc(pcap_t *, int);
|
||||
int pcap_can_set_rfmon(pcap_t *);
|
||||
int pcap_set_rfmon(pcap_t *, int);
|
||||
int pcap_set_timeout(pcap_t *, int);
|
||||
int pcap_set_buffer_size(pcap_t *, int);
|
||||
int pcap_activate(pcap_t *);
|
||||
|
||||
pcap_t *pcap_open_live(const char *, int, int, int, char *);
|
||||
pcap_t *pcap_open_dead(int, int);
|
||||
pcap_t *pcap_open_offline(const char *, char *);
|
||||
#if defined(WIN32)
|
||||
pcap_t *pcap_hopen_offline(intptr_t, char *);
|
||||
#if !defined(LIBPCAP_EXPORTS)
|
||||
#define pcap_fopen_offline(f,b) \
|
||||
pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
|
||||
#else /*LIBPCAP_EXPORTS*/
|
||||
static pcap_t *pcap_fopen_offline(FILE *, char *);
|
||||
#endif
|
||||
#else /*WIN32*/
|
||||
pcap_t *pcap_fopen_offline(FILE *, char *);
|
||||
#endif /*WIN32*/
|
||||
|
||||
void pcap_close(pcap_t *);
|
||||
int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
|
||||
int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
|
||||
const u_char*
|
||||
pcap_next(pcap_t *, struct pcap_pkthdr *);
|
||||
int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
|
||||
void pcap_breakloop(pcap_t *);
|
||||
int pcap_stats(pcap_t *, struct pcap_stat *);
|
||||
int pcap_setfilter(pcap_t *, struct bpf_program *);
|
||||
int pcap_setdirection(pcap_t *, pcap_direction_t);
|
||||
int pcap_getnonblock(pcap_t *, char *);
|
||||
int pcap_setnonblock(pcap_t *, int, char *);
|
||||
int pcap_inject(pcap_t *, const void *, size_t);
|
||||
int pcap_sendpacket(pcap_t *, const u_char *, int);
|
||||
const char *pcap_statustostr(int);
|
||||
const char *pcap_strerror(int);
|
||||
char *pcap_geterr(pcap_t *);
|
||||
void pcap_perror(pcap_t *, char *);
|
||||
int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
|
||||
bpf_u_int32);
|
||||
int pcap_compile_nopcap(int, int, struct bpf_program *,
|
||||
const char *, int, bpf_u_int32);
|
||||
void pcap_freecode(struct bpf_program *);
|
||||
int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
|
||||
const u_char *);
|
||||
int pcap_datalink(pcap_t *);
|
||||
int pcap_datalink_ext(pcap_t *);
|
||||
int pcap_list_datalinks(pcap_t *, int **);
|
||||
int pcap_set_datalink(pcap_t *, int);
|
||||
void pcap_free_datalinks(int *);
|
||||
int pcap_datalink_name_to_val(const char *);
|
||||
const char *pcap_datalink_val_to_name(int);
|
||||
const char *pcap_datalink_val_to_description(int);
|
||||
int pcap_snapshot(pcap_t *);
|
||||
int pcap_is_swapped(pcap_t *);
|
||||
int pcap_major_version(pcap_t *);
|
||||
int pcap_minor_version(pcap_t *);
|
||||
|
||||
/* XXX */
|
||||
FILE *pcap_file(pcap_t *);
|
||||
int pcap_fileno(pcap_t *);
|
||||
|
||||
pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
|
||||
pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
|
||||
FILE *pcap_dump_file(pcap_dumper_t *);
|
||||
long pcap_dump_ftell(pcap_dumper_t *);
|
||||
int pcap_dump_flush(pcap_dumper_t *);
|
||||
void pcap_dump_close(pcap_dumper_t *);
|
||||
void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
|
||||
|
||||
int pcap_findalldevs(pcap_if_t **, char *);
|
||||
void pcap_freealldevs(pcap_if_t *);
|
||||
|
||||
const char *pcap_lib_version(void);
|
||||
|
||||
/* XXX this guy lives in the bpf tree */
|
||||
u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
|
||||
int bpf_validate(const struct bpf_insn *f, int len);
|
||||
char *bpf_image(const struct bpf_insn *, int);
|
||||
void bpf_dump(const struct bpf_program *, int);
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
/*
|
||||
* Win32 definitions
|
||||
*/
|
||||
|
||||
int pcap_setbuff(pcap_t *p, int dim);
|
||||
int pcap_setmode(pcap_t *p, int mode);
|
||||
int pcap_setmintocopy(pcap_t *p, int size);
|
||||
|
||||
#ifdef WPCAP
|
||||
/* Include file with the wpcap-specific extensions */
|
||||
#include <Win32-Extensions.h>
|
||||
#endif /* WPCAP */
|
||||
|
||||
#define MODE_CAPT 0
|
||||
#define MODE_STAT 1
|
||||
#define MODE_MON 2
|
||||
|
||||
#elif defined(MSDOS)
|
||||
|
||||
/*
|
||||
* MS-DOS definitions
|
||||
*/
|
||||
|
||||
int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
|
||||
void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
|
||||
u_long pcap_mac_packets (void);
|
||||
|
||||
#else /* UN*X */
|
||||
|
||||
/*
|
||||
* UN*X definitions
|
||||
*/
|
||||
|
||||
int pcap_get_selectable_fd(pcap_t *);
|
||||
|
||||
#endif /* WIN32/MSDOS/UN*X */
|
||||
|
||||
#ifdef HAVE_REMOTE
|
||||
/* Includes most of the public stuff that is needed for the remote capture */
|
||||
#include <remote-ext.h>
|
||||
#endif /* HAVE_REMOTE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
129
pcappp/include/pcapplusplus/pcap/sll.h
Normal file
129
pcappp/include/pcapplusplus/pcap/sll.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.2.2.1 2008-05-30 01:36:06 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* For captures on Linux cooked sockets, we construct a fake header
|
||||
* that includes:
|
||||
*
|
||||
* a 2-byte "packet type" which is one of:
|
||||
*
|
||||
* LINUX_SLL_HOST packet was sent to us
|
||||
* LINUX_SLL_BROADCAST packet was broadcast
|
||||
* LINUX_SLL_MULTICAST packet was multicast
|
||||
* LINUX_SLL_OTHERHOST packet was sent to somebody else
|
||||
* LINUX_SLL_OUTGOING packet was sent *by* us;
|
||||
*
|
||||
* a 2-byte Ethernet protocol field;
|
||||
*
|
||||
* a 2-byte link-layer type;
|
||||
*
|
||||
* a 2-byte link-layer address length;
|
||||
*
|
||||
* an 8-byte source link-layer address, whose actual length is
|
||||
* specified by the previous value.
|
||||
*
|
||||
* All fields except for the link-layer address are in network byte order.
|
||||
*
|
||||
* DO NOT change the layout of this structure, or change any of the
|
||||
* LINUX_SLL_ values below. If you must change the link-layer header
|
||||
* for a "cooked" Linux capture, introduce a new DLT_ type (ask
|
||||
* "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
|
||||
* a value that collides with a value already being used), and use the
|
||||
* new header in captures of that type, so that programs that can
|
||||
* handle DLT_LINUX_SLL captures will continue to handle them correctly
|
||||
* without any change, and so that capture files with different headers
|
||||
* can be told apart and programs that read them can dissect the
|
||||
* packets in them.
|
||||
*/
|
||||
|
||||
#ifndef lib_pcap_sll_h
|
||||
#define lib_pcap_sll_h
|
||||
|
||||
/*
|
||||
* A DLT_LINUX_SLL fake link-layer header.
|
||||
*/
|
||||
#define SLL_HDR_LEN 16 /* total header length */
|
||||
#define SLL_ADDRLEN 8 /* length of address field */
|
||||
|
||||
struct sll_header {
|
||||
u_int16_t sll_pkttype; /* packet type */
|
||||
u_int16_t sll_hatype; /* link-layer address type */
|
||||
u_int16_t sll_halen; /* link-layer address length */
|
||||
u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
|
||||
u_int16_t sll_protocol; /* protocol */
|
||||
};
|
||||
|
||||
/*
|
||||
* The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
|
||||
* PACKET_ values on Linux, but are defined here so that they're
|
||||
* available even on systems other than Linux, and so that they
|
||||
* don't change even if the PACKET_ values change.
|
||||
*/
|
||||
#define LINUX_SLL_HOST 0
|
||||
#define LINUX_SLL_BROADCAST 1
|
||||
#define LINUX_SLL_MULTICAST 2
|
||||
#define LINUX_SLL_OTHERHOST 3
|
||||
#define LINUX_SLL_OUTGOING 4
|
||||
|
||||
/*
|
||||
* The LINUX_SLL_ values for "sll_protocol"; these correspond to the
|
||||
* ETH_P_ values on Linux, but are defined here so that they're
|
||||
* available even on systems other than Linux. We assume, for now,
|
||||
* that the ETH_P_ values won't change in Linux; if they do, then:
|
||||
*
|
||||
* if we don't translate them in "pcap-linux.c", capture files
|
||||
* won't necessarily be readable if captured on a system that
|
||||
* defines ETH_P_ values that don't match these values;
|
||||
*
|
||||
* if we do translate them in "pcap-linux.c", that makes life
|
||||
* unpleasant for the BPF code generator, as the values you test
|
||||
* for in the kernel aren't the values that you test for when
|
||||
* reading a capture file, so the fixup code run on BPF programs
|
||||
* handed to the kernel ends up having to do more work.
|
||||
*
|
||||
* Add other values here as necessary, for handling packet types that
|
||||
* might show up on non-Ethernet, non-802.x networks. (Not all the ones
|
||||
* in the Linux "if_ether.h" will, I suspect, actually show up in
|
||||
* captures.)
|
||||
*/
|
||||
#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
|
||||
#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
|
||||
|
||||
#endif
|
||||
90
pcappp/include/pcapplusplus/pcap/usb.h
Normal file
90
pcappp/include/pcapplusplus/pcap/usb.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Paolo Abeni (Italy)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Basic USB data struct
|
||||
* By Paolo Abeni <paolo.abeni@email.it>
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.6 2007/09/22 02:06:08 guy Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PCAP_USB_STRUCTS_H__
|
||||
#define _PCAP_USB_STRUCTS_H__
|
||||
|
||||
/*
|
||||
* possible transfer mode
|
||||
*/
|
||||
#define URB_TRANSFER_IN 0x80
|
||||
#define URB_ISOCHRONOUS 0x0
|
||||
#define URB_INTERRUPT 0x1
|
||||
#define URB_CONTROL 0x2
|
||||
#define URB_BULK 0x3
|
||||
|
||||
/*
|
||||
* possible event type
|
||||
*/
|
||||
#define URB_SUBMIT 'S'
|
||||
#define URB_COMPLETE 'C'
|
||||
#define URB_ERROR 'E'
|
||||
|
||||
/*
|
||||
* USB setup header as defined in USB specification.
|
||||
* Appears at the front of each packet in DLT_USB captures.
|
||||
*/
|
||||
typedef struct _usb_setup {
|
||||
u_int8_t bmRequestType;
|
||||
u_int8_t bRequest;
|
||||
u_int16_t wValue;
|
||||
u_int16_t wIndex;
|
||||
u_int16_t wLength;
|
||||
} pcap_usb_setup;
|
||||
|
||||
|
||||
/*
|
||||
* Header prepended by linux kernel to each event.
|
||||
* Appears at the front of each packet in DLT_USB_LINUX captures.
|
||||
*/
|
||||
typedef struct _usb_header {
|
||||
u_int64_t id;
|
||||
u_int8_t event_type;
|
||||
u_int8_t transfer_type;
|
||||
u_int8_t endpoint_number;
|
||||
u_int8_t device_address;
|
||||
u_int16_t bus_id;
|
||||
char setup_flag;/*if !=0 the urb setup header is not present*/
|
||||
char data_flag; /*if !=0 no urb data is present*/
|
||||
int64_t ts_sec;
|
||||
int32_t ts_usec;
|
||||
int32_t status;
|
||||
u_int32_t urb_len;
|
||||
u_int32_t data_len; /* amount of urb data really present in this event*/
|
||||
pcap_usb_setup setup;
|
||||
} pcap_usb_header;
|
||||
|
||||
|
||||
#endif
|
||||
46
pcappp/include/pcapplusplus/pcap/vlan.h
Normal file
46
pcappp/include/pcapplusplus/pcap/vlan.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1.2.2 2008-08-06 07:45:59 guy Exp $
|
||||
*/
|
||||
|
||||
#ifndef lib_pcap_vlan_h
|
||||
#define lib_pcap_vlan_h
|
||||
|
||||
struct vlan_tag {
|
||||
u_int16_t vlan_tpid; /* ETH_P_8021Q */
|
||||
u_int16_t vlan_tci; /* VLAN TCI */
|
||||
};
|
||||
|
||||
#define VLAN_TAG_LEN 4
|
||||
|
||||
#endif
|
||||
1228
pcappp/include/pcapplusplus/pthread.h
Normal file
1228
pcappp/include/pcapplusplus/pthread.h
Normal file
File diff suppressed because it is too large
Load Diff
444
pcappp/include/pcapplusplus/remote-ext.h
Normal file
444
pcappp/include/pcapplusplus/remote-ext.h
Normal file
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright (c) 2002 - 2003
|
||||
* NetGroup, Politecnico di Torino (Italy)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Politecnico di Torino nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __REMOTE_EXT_H__
|
||||
#define __REMOTE_EXT_H__
|
||||
|
||||
|
||||
#ifndef HAVE_REMOTE
|
||||
#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h
|
||||
#endif
|
||||
|
||||
// Definition for Microsoft Visual Studio
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\file remote-ext.h
|
||||
|
||||
The goal of this file it to include most of the new definitions that should be
|
||||
placed into the pcap.h file.
|
||||
|
||||
It includes all new definitions (structures and functions like pcap_open().
|
||||
Some of the functions are not really a remote feature, but, right now,
|
||||
they are placed here.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// All this stuff is public
|
||||
/*! \addtogroup remote_struct
|
||||
\{
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Defines the maximum buffer size in which address, port, interface names are kept.
|
||||
|
||||
In case the adapter name or such is larger than this value, it is truncated.
|
||||
This is not used by the user; however it must be aware that an hostname / interface
|
||||
name longer than this value will be truncated.
|
||||
*/
|
||||
#define PCAP_BUF_SIZE 1024
|
||||
|
||||
|
||||
/*! \addtogroup remote_source_ID
|
||||
\{
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal representation of the type of source in use (file,
|
||||
remote/local interface).
|
||||
|
||||
This indicates a file, i.e. the user want to open a capture from a local file.
|
||||
*/
|
||||
#define PCAP_SRC_FILE 2
|
||||
/*!
|
||||
\brief Internal representation of the type of source in use (file,
|
||||
remote/local interface).
|
||||
|
||||
This indicates a local interface, i.e. the user want to open a capture from
|
||||
a local interface. This does not involve the RPCAP protocol.
|
||||
*/
|
||||
#define PCAP_SRC_IFLOCAL 3
|
||||
/*!
|
||||
\brief Internal representation of the type of source in use (file,
|
||||
remote/local interface).
|
||||
|
||||
This indicates a remote interface, i.e. the user want to open a capture from
|
||||
an interface on a remote host. This does involve the RPCAP protocol.
|
||||
*/
|
||||
#define PCAP_SRC_IFREMOTE 4
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*! \addtogroup remote_source_string
|
||||
|
||||
The formats allowed by the pcap_open() are the following:
|
||||
- file://path_and_filename [opens a local file]
|
||||
- rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
|
||||
- rpcap://host/devicename [opens the selected device available on a remote host]
|
||||
- rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]
|
||||
- adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]
|
||||
- (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]
|
||||
|
||||
The formats allowed by the pcap_findalldevs_ex() are the following:
|
||||
- file://folder/ [lists all the files in the given folder]
|
||||
- rpcap:// [lists all local adapters]
|
||||
- rpcap://host:port/ [lists the devices available on a remote host]
|
||||
|
||||
Referring to the 'host' and 'port' paramters, they can be either numeric or literal. Since
|
||||
IPv6 is fully supported, these are the allowed formats:
|
||||
|
||||
- host (literal): e.g. host.foo.bar
|
||||
- host (numeric IPv4): e.g. 10.11.12.13
|
||||
- host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
|
||||
- host (numeric IPv6): e.g. [1:2:3::4]
|
||||
- port: can be either numeric (e.g. '80') or literal (e.g. 'http')
|
||||
|
||||
Here you find some allowed examples:
|
||||
- rpcap://host.foo.bar/devicename [everything literal, no port number]
|
||||
- rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
|
||||
- rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
|
||||
- rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
|
||||
- rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
|
||||
- rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
|
||||
- rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
|
||||
- rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
|
||||
|
||||
\{
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\brief String that will be used to determine the type of source in use (file,
|
||||
remote/local interface).
|
||||
|
||||
This string will be prepended to the interface name in order to create a string
|
||||
that contains all the information required to open the source.
|
||||
|
||||
This string indicates that the user wants to open a capture from a local file.
|
||||
*/
|
||||
#define PCAP_SRC_FILE_STRING "file://"
|
||||
/*!
|
||||
\brief String that will be used to determine the type of source in use (file,
|
||||
remote/local interface).
|
||||
|
||||
This string will be prepended to the interface name in order to create a string
|
||||
that contains all the information required to open the source.
|
||||
|
||||
This string indicates that the user wants to open a capture from a network interface.
|
||||
This string does not necessarily involve the use of the RPCAP protocol. If the
|
||||
interface required resides on the local host, the RPCAP protocol is not involved
|
||||
and the local functions are used.
|
||||
*/
|
||||
#define PCAP_SRC_IF_STRING "rpcap://"
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\addtogroup remote_open_flags
|
||||
\{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Defines if the adapter has to go in promiscuous mode.
|
||||
|
||||
It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise.
|
||||
Note that even if this parameter is false, the interface could well be in promiscuous
|
||||
mode for some other reason (for example because another capture process with
|
||||
promiscuous mode enabled is currently using that interface).
|
||||
On on Linux systems with 2.2 or later kernels (that have the "any" device), this
|
||||
flag does not work on the "any" device; if an argument of "any" is supplied,
|
||||
the 'promisc' flag is ignored.
|
||||
*/
|
||||
#define PCAP_OPENFLAG_PROMISCUOUS 1
|
||||
|
||||
/*!
|
||||
\brief Defines if the data trasfer (in case of a remote
|
||||
capture) has to be done with UDP protocol.
|
||||
|
||||
If it is '1' if you want a UDP data connection, '0' if you want
|
||||
a TCP data connection; control connection is always TCP-based.
|
||||
A UDP connection is much lighter, but it does not guarantee that all
|
||||
the captured packets arrive to the client workstation. Moreover,
|
||||
it could be harmful in case of network congestion.
|
||||
This flag is meaningless if the source is not a remote interface.
|
||||
In that case, it is simply ignored.
|
||||
*/
|
||||
#define PCAP_OPENFLAG_DATATX_UDP 2
|
||||
|
||||
|
||||
/*!
|
||||
\brief Defines if the remote probe will capture its own generated traffic.
|
||||
|
||||
In case the remote probe uses the same interface to capture traffic and to send
|
||||
data back to the caller, the captured traffic includes the RPCAP traffic as well.
|
||||
If this flag is turned on, the RPCAP traffic is excluded from the capture, so that
|
||||
the trace returned back to the collector is does not include this traffic.
|
||||
*/
|
||||
#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4
|
||||
|
||||
/*!
|
||||
\brief Defines if the local adapter will capture its own generated traffic.
|
||||
|
||||
This flag tells the underlying capture driver to drop the packets that were sent by itself.
|
||||
This is usefult when building applications like bridges, that should ignore the traffic
|
||||
they just sent.
|
||||
*/
|
||||
#define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8
|
||||
|
||||
/*!
|
||||
\brief This flag configures the adapter for maximum responsiveness.
|
||||
|
||||
In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before
|
||||
copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
|
||||
i.e. better performance, which is good for applications like sniffers. If the user sets the
|
||||
PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application
|
||||
is ready to receive them. This is suggested for real time applications (like, for example, a bridge)
|
||||
that need the best responsiveness.*/
|
||||
#define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\addtogroup remote_samp_methods
|
||||
\{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief No sampling has to be done on the current capture.
|
||||
|
||||
In this case, no sampling algorithms are applied to the current capture.
|
||||
*/
|
||||
#define PCAP_SAMP_NOSAMP 0
|
||||
|
||||
/*!
|
||||
\brief It defines that only 1 out of N packets must be returned to the user.
|
||||
|
||||
In this case, the 'value' field of the 'pcap_samp' structure indicates the
|
||||
number of packets (minus 1) that must be discarded before one packet got accepted.
|
||||
In other words, if 'value = 10', the first packet is returned to the caller, while
|
||||
the following 9 are discarded.
|
||||
*/
|
||||
#define PCAP_SAMP_1_EVERY_N 1
|
||||
|
||||
/*!
|
||||
\brief It defines that we have to return 1 packet every N milliseconds.
|
||||
|
||||
In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting
|
||||
time' in milliseconds before one packet got accepted.
|
||||
In other words, if 'value = 10', the first packet is returned to the caller; the next
|
||||
returned one will be the first packet that arrives when 10ms have elapsed.
|
||||
*/
|
||||
#define PCAP_SAMP_FIRST_AFTER_N_MS 2
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\addtogroup remote_auth_methods
|
||||
\{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief It defines the NULL authentication.
|
||||
|
||||
This value has to be used within the 'type' member of the pcap_rmtauth structure.
|
||||
The 'NULL' authentication has to be equal to 'zero', so that old applications
|
||||
can just put every field of struct pcap_rmtauth to zero, and it does work.
|
||||
*/
|
||||
#define RPCAP_RMTAUTH_NULL 0
|
||||
/*!
|
||||
\brief It defines the username/password authentication.
|
||||
|
||||
With this type of authentication, the RPCAP protocol will use the username/
|
||||
password provided to authenticate the user on the remote machine. If the
|
||||
authentication is successful (and the user has the right to open network devices)
|
||||
the RPCAP connection will continue; otherwise it will be dropped.
|
||||
|
||||
This value has to be used within the 'type' member of the pcap_rmtauth structure.
|
||||
*/
|
||||
#define RPCAP_RMTAUTH_PWD 1
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
||||
\brief This structure keeps the information needed to autheticate
|
||||
the user on a remote machine.
|
||||
|
||||
The remote machine can either grant or refuse the access according
|
||||
to the information provided.
|
||||
In case the NULL authentication is required, both 'username' and
|
||||
'password' can be NULL pointers.
|
||||
|
||||
This structure is meaningless if the source is not a remote interface;
|
||||
in that case, the functions which requires such a structure can accept
|
||||
a NULL pointer as well.
|
||||
*/
|
||||
struct pcap_rmtauth
|
||||
{
|
||||
/*!
|
||||
\brief Type of the authentication required.
|
||||
|
||||
In order to provide maximum flexibility, we can support different types
|
||||
of authentication based on the value of this 'type' variable. The currently
|
||||
supported authentication methods are defined into the
|
||||
\link remote_auth_methods Remote Authentication Methods Section\endlink.
|
||||
|
||||
*/
|
||||
int type;
|
||||
/*!
|
||||
\brief Zero-terminated string containing the username that has to be
|
||||
used on the remote machine for authentication.
|
||||
|
||||
This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
|
||||
and it can be NULL.
|
||||
*/
|
||||
char *username;
|
||||
/*!
|
||||
\brief Zero-terminated string containing the password that has to be
|
||||
used on the remote machine for authentication.
|
||||
|
||||
This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
|
||||
and it can be NULL.
|
||||
*/
|
||||
char *password;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief This structure defines the information related to sampling.
|
||||
|
||||
In case the sampling is requested, the capturing device should read
|
||||
only a subset of the packets coming from the source. The returned packets depend
|
||||
on the sampling parameters.
|
||||
|
||||
\warning The sampling process is applied <strong>after</strong> the filtering process.
|
||||
In other words, packets are filtered first, then the sampling process selects a
|
||||
subset of the 'filtered' packets and it returns them to the caller.
|
||||
*/
|
||||
struct pcap_samp
|
||||
{
|
||||
/*!
|
||||
Method used for sampling. Currently, the supported methods are listed in the
|
||||
\link remote_samp_methods Sampling Methods Section\endlink.
|
||||
*/
|
||||
int method;
|
||||
|
||||
/*!
|
||||
This value depends on the sampling method defined. For its meaning, please check
|
||||
at the \link remote_samp_methods Sampling Methods Section\endlink.
|
||||
*/
|
||||
int value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//! Maximum lenght of an host name (needed for the RPCAP active mode)
|
||||
#define RPCAP_HOSTLIST_SIZE 1024
|
||||
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/ // end of public documentation
|
||||
|
||||
|
||||
// Exported functions
|
||||
|
||||
|
||||
|
||||
/** \name New WinPcap functions
|
||||
|
||||
This section lists the new functions that are able to help considerably in writing
|
||||
WinPcap programs because of their easiness of use.
|
||||
*/
|
||||
//\{
|
||||
pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
|
||||
int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf);
|
||||
int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf);
|
||||
int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
|
||||
struct pcap_samp *pcap_setsampling(pcap_t *p);
|
||||
|
||||
//\}
|
||||
// End of new winpcap functions
|
||||
|
||||
|
||||
|
||||
/** \name Remote Capture functions
|
||||
*/
|
||||
//\{
|
||||
SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf);
|
||||
int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf);
|
||||
int pcap_remoteact_close(const char *host, char *errbuf);
|
||||
void pcap_remoteact_cleanup();
|
||||
//\}
|
||||
// End of remote capture functions
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
235
pcappp/include/pcapplusplus/sched.h
Normal file
235
pcappp/include/pcapplusplus/sched.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Module: sched.h
|
||||
*
|
||||
* Purpose:
|
||||
* Provides an implementation of POSIX realtime extensions
|
||||
* as defined in
|
||||
*
|
||||
* POSIX 1003.1b-1993 (POSIX.1b)
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads4w - POSIX Threads for Windows
|
||||
* Copyright 1998 John E. Bossom
|
||||
* Copyright 1999-2018, Pthreads4w contributors
|
||||
*
|
||||
* Homepage: https://sourceforge.net/projects/pthreads4w/
|
||||
*
|
||||
* The current list of contributors is contained
|
||||
* in the file CONTRIBUTORS included with the source
|
||||
* code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
*
|
||||
* https://sourceforge.net/p/pthreads4w/wiki/Contributors/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if !defined(_SCHED_H)
|
||||
#define _SCHED_H
|
||||
#define __SCHED_H_SOURCED__
|
||||
|
||||
#include <_ptw32.h>
|
||||
|
||||
/* We need a typedef for pid_t, (and POSIX requires <sched.h> to
|
||||
* define it, as it is defined in <sys/types.h>, but it does NOT
|
||||
* sanction exposure of everything from <sys/types.h>); there is
|
||||
* no pid_t in Windows anyway, (except that MinGW does define it
|
||||
* in their <sys/types.h>), so just provide a suitable typedef,
|
||||
* but note that we must do so cautiously, to avoid a typedef
|
||||
* conflict if MinGW's <sys/types.h> is also #included:
|
||||
*/
|
||||
#if ! defined __MINGW32__ || ! defined __have_typedef_pid_t
|
||||
|
||||
# if defined __MINGW64__
|
||||
typedef __int64 pid_t;
|
||||
# else
|
||||
typedef int pid_t;
|
||||
#endif
|
||||
|
||||
#if __GNUC__ < 4
|
||||
/* GCC v4.0 and later, (as used by MinGW), allows us to repeat a
|
||||
* typedef, provided every duplicate is consistent; only set this
|
||||
* multiple definition guard when we cannot be certain that it is
|
||||
* permissable to repeat typedefs.
|
||||
*/
|
||||
#define __have_typedef_pid_t 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* POSIX.1-1993 says that <sched.h> WILL expose all of <time.h>
|
||||
*/
|
||||
#undef __SCHED_H_SOURCED__
|
||||
#if _POSIX_C_SOURCE >= 200112L
|
||||
/* POSIX.1-2001 and later revises this to say only that it MAY do so;
|
||||
* only struct timespec, and associated time_t are actually required,
|
||||
* so prefer to be selective; (MinGW.org's <time.h> offers an option
|
||||
* for selective #inclusion, when __SCHED_H_SOURCED__ is defined):
|
||||
*/
|
||||
#define __SCHED_H_SOURCED__
|
||||
#define __need_struct_timespec
|
||||
#define __need_time_t
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#if defined __MINGW64__ || _MSC_VER >= 1900
|
||||
/* These are known to define struct timespec, when <time.h> has been
|
||||
* #included, but may not, (probably don't), follow the convention of
|
||||
* defining __struct_timespec_defined, as adopted by MinGW.org; for
|
||||
* these cases, we unconditionally assume that struct timespec has
|
||||
* been defined, otherwise, if MinGW.org's criterion has not been
|
||||
* satisfied...
|
||||
*/
|
||||
#elif ! defined __struct_timespec_defined
|
||||
# ifndef _TIMESPEC_DEFINED
|
||||
# define _TIMESPEC_DEFINED
|
||||
struct timespec
|
||||
{ /* ...we fall back on this explicit definition.
|
||||
*/
|
||||
time_t tv_sec;
|
||||
int tv_nsec;
|
||||
};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Microsoft VC++6.0 lacks these *_PTR types
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300 && !defined (__PTW32_HAVE_DWORD_PTR)
|
||||
typedef unsigned long ULONG_PTR;
|
||||
typedef ULONG_PTR DWORD_PTR;
|
||||
#endif
|
||||
|
||||
/* Thread scheduling policies */
|
||||
|
||||
enum
|
||||
{ SCHED_OTHER = 0,
|
||||
SCHED_FIFO,
|
||||
SCHED_RR,
|
||||
SCHED_MIN = SCHED_OTHER,
|
||||
SCHED_MAX = SCHED_RR
|
||||
};
|
||||
|
||||
struct sched_param
|
||||
{ int sched_priority;
|
||||
};
|
||||
|
||||
/*
|
||||
* CPU affinity
|
||||
*
|
||||
* cpu_set_t:
|
||||
* Considered opaque but cannot be an opaque pointer due to the need for
|
||||
* compatibility with GNU systems and sched_setaffinity() et.al., which
|
||||
* include the cpusetsize parameter "normally set to sizeof(cpu_set_t)".
|
||||
*
|
||||
* FIXME: These are GNU, and NOT specified by POSIX; maybe consider
|
||||
* occluding them within a _GNU_SOURCE (or similar) feature test.
|
||||
*/
|
||||
|
||||
#define CPU_SETSIZE (sizeof(size_t)*8)
|
||||
|
||||
#define CPU_COUNT(setptr) (_sched_affinitycpucount(setptr))
|
||||
|
||||
#define CPU_ZERO(setptr) (_sched_affinitycpuzero(setptr))
|
||||
|
||||
#define CPU_SET(cpu, setptr) (_sched_affinitycpuset((cpu),(setptr)))
|
||||
|
||||
#define CPU_CLR(cpu, setptr) (_sched_affinitycpuclr((cpu),(setptr)))
|
||||
|
||||
#define CPU_ISSET(cpu, setptr) (_sched_affinitycpuisset((cpu),(setptr)))
|
||||
|
||||
#define CPU_AND(destsetptr, srcset1ptr, srcset2ptr) (_sched_affinitycpuand((destsetptr),(srcset1ptr),(srcset2ptr)))
|
||||
|
||||
#define CPU_OR(destsetptr, srcset1ptr, srcset2ptr) (_sched_affinitycpuor((destsetptr),(srcset1ptr),(srcset2ptr)))
|
||||
|
||||
#define CPU_XOR(destsetptr, srcset1ptr, srcset2ptr) \
|
||||
(_sched_affinitycpuxor((destsetptr),(srcset1ptr),(srcset2ptr)))
|
||||
|
||||
#define CPU_EQUAL(set1ptr, set2ptr) (_sched_affinitycpuequal((set1ptr),(set2ptr)))
|
||||
|
||||
typedef union
|
||||
{ char cpuset[CPU_SETSIZE/8];
|
||||
size_t _align;
|
||||
} cpu_set_t;
|
||||
|
||||
__PTW32_BEGIN_C_DECLS
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sched_yield (void);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sched_get_priority_min (int policy);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sched_get_priority_max (int policy);
|
||||
|
||||
/* FIXME: this declaration of sched_setscheduler() is NOT as prescribed
|
||||
* by POSIX; it lacks const struct sched_param * as third argument.
|
||||
*/
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sched_setscheduler (pid_t pid, int policy);
|
||||
|
||||
/* FIXME: In addition to the above five functions, POSIX also requires:
|
||||
*
|
||||
* int sched_getparam (pid_t, struct sched_param *);
|
||||
* int sched_setparam (pid_t, const struct sched_param *);
|
||||
*
|
||||
* both of which are conspicuous by their absence here!
|
||||
*/
|
||||
|
||||
/* Compatibility with Linux - not standard in POSIX
|
||||
* FIXME: consider occluding within a _GNU_SOURCE (or similar) feature test.
|
||||
*/
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sched_setaffinity (pid_t pid, size_t cpusetsize, cpu_set_t *mask);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sched_getaffinity (pid_t pid, size_t cpusetsize, cpu_set_t *mask);
|
||||
|
||||
/*
|
||||
* Support routines and macros for cpu_set_t
|
||||
*/
|
||||
__PTW32_DLLPORT int __PTW32_CDECL _sched_affinitycpucount (const cpu_set_t *set);
|
||||
|
||||
__PTW32_DLLPORT void __PTW32_CDECL _sched_affinitycpuzero (cpu_set_t *pset);
|
||||
|
||||
__PTW32_DLLPORT void __PTW32_CDECL _sched_affinitycpuset (int cpu, cpu_set_t *pset);
|
||||
|
||||
__PTW32_DLLPORT void __PTW32_CDECL _sched_affinitycpuclr (int cpu, cpu_set_t *pset);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL _sched_affinitycpuisset (int cpu, const cpu_set_t *pset);
|
||||
|
||||
__PTW32_DLLPORT void __PTW32_CDECL _sched_affinitycpuand(cpu_set_t *pdestset, const cpu_set_t *psrcset1, const cpu_set_t *psrcset2);
|
||||
|
||||
__PTW32_DLLPORT void __PTW32_CDECL _sched_affinitycpuor(cpu_set_t *pdestset, const cpu_set_t *psrcset1, const cpu_set_t *psrcset2);
|
||||
|
||||
__PTW32_DLLPORT void __PTW32_CDECL _sched_affinitycpuxor(cpu_set_t *pdestset, const cpu_set_t *psrcset1, const cpu_set_t *psrcset2);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL _sched_affinitycpuequal (const cpu_set_t *pset1, const cpu_set_t *pset2);
|
||||
|
||||
/* Note that this macro returns ENOTSUP rather than ENOSYS, as
|
||||
* might be expected. However, returning ENOSYS should mean that
|
||||
* sched_get_priority_{min,max} are not implemented as well as
|
||||
* sched_rr_get_interval. This is not the case, since we just
|
||||
* don't support round-robin scheduling. Therefore I have chosen
|
||||
* to return the same value as sched_setscheduler when SCHED_RR
|
||||
* is passed to it.
|
||||
*
|
||||
* FIXME: POSIX requires this to be defined as a function; this
|
||||
* macro implementation is permitted IN ADDITION to the function,
|
||||
* but the macro alone is not POSIX compliant! Worse still, it
|
||||
* imposes a requirement on the caller, to ensure that both the
|
||||
* declaration of errno, and the definition of ENOTSUP, are in
|
||||
* scope at point of call, (which it may wish to do anyway, but
|
||||
* POSIX imposes no such constraint)!
|
||||
*/
|
||||
#define sched_rr_get_interval(_pid, _interval) \
|
||||
( errno = ENOTSUP, (int) -1 )
|
||||
|
||||
__PTW32_END_C_DECLS
|
||||
|
||||
#undef __SCHED_H_SOURCED__
|
||||
#endif /* !_SCHED_H */
|
||||
116
pcappp/include/pcapplusplus/semaphore.h
Normal file
116
pcappp/include/pcapplusplus/semaphore.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Module: semaphore.h
|
||||
*
|
||||
* Purpose:
|
||||
* Semaphores aren't actually part of the PThreads standard.
|
||||
* They are defined by the POSIX Standard:
|
||||
*
|
||||
* POSIX 1003.1b-1993 (POSIX.1b)
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pthreads4w - POSIX Threads for Windows
|
||||
* Copyright 1998 John E. Bossom
|
||||
* Copyright 1999-2018, Pthreads4w contributors
|
||||
*
|
||||
* Homepage: https://sourceforge.net/projects/pthreads4w/
|
||||
*
|
||||
* The current list of contributors is contained
|
||||
* in the file CONTRIBUTORS included with the source
|
||||
* code distribution. The list can also be seen at the
|
||||
* following World Wide Web location:
|
||||
*
|
||||
* https://sourceforge.net/p/pthreads4w/wiki/Contributors/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if !defined( SEMAPHORE_H )
|
||||
#define SEMAPHORE_H
|
||||
|
||||
/* FIXME: POSIX.1 says that _POSIX_SEMAPHORES should be defined
|
||||
* in <unistd.h>, not here; for later POSIX.1 versions, its value
|
||||
* should match the corresponding _POSIX_VERSION number, but in
|
||||
* the case of POSIX.1b-1993, the value is unspecified.
|
||||
*
|
||||
* Notwithstanding the above, since POSIX semaphores, (and indeed
|
||||
* having any <unistd.h> to #include), are not a standard feature
|
||||
* on MS-Windows, it is convenient to retain this definition here;
|
||||
* we may consider adding a hook, to make it selectively available
|
||||
* for inclusion by <unistd.h>, in those cases (e.g. MinGW) where
|
||||
* <unistd.h> is provided.
|
||||
*/
|
||||
#define _POSIX_SEMAPHORES
|
||||
|
||||
/* Internal macros, common to the public interfaces for various
|
||||
* pthreads-win32 components, are defined in <_ptw32.h>; we must
|
||||
* include them here.
|
||||
*/
|
||||
#include <_ptw32.h>
|
||||
|
||||
/* The sem_timedwait() function was added in POSIX.1-2001; it
|
||||
* requires struct timespec to be defined, at least as a partial
|
||||
* (a.k.a. incomplete) data type. Forward declare it as such,
|
||||
* then include <time.h> selectively, to acquire a complete
|
||||
* definition, (if available).
|
||||
*/
|
||||
struct timespec;
|
||||
#define __need_struct_timespec
|
||||
#include <time.h>
|
||||
|
||||
/* The data type used to represent our semaphore implementation,
|
||||
* as required by POSIX.1; FIXME: consider renaming the underlying
|
||||
* structure tag, to avoid possible pollution of user namespace.
|
||||
*/
|
||||
typedef struct sem_t_ * sem_t;
|
||||
|
||||
/* POSIX.1b (and later) mandates SEM_FAILED as the value to be
|
||||
* returned on failure of sem_open(); (our implementation is a
|
||||
* stub, which will always return this).
|
||||
*/
|
||||
#define SEM_FAILED (sem_t *)(-1)
|
||||
|
||||
__PTW32_BEGIN_C_DECLS
|
||||
|
||||
/* Function prototypes: some are implemented as stubs, which
|
||||
* always fail; (FIXME: identify them).
|
||||
*/
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_init (sem_t * sem,
|
||||
int pshared,
|
||||
unsigned int value);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_destroy (sem_t * sem);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_trywait (sem_t * sem);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_wait (sem_t * sem);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_timedwait (sem_t * sem,
|
||||
const struct timespec * abstime);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_post (sem_t * sem);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_post_multiple (sem_t * sem,
|
||||
int count);
|
||||
|
||||
__PTW32_DLLPORT sem_t * __PTW32_CDECL sem_open (const char *, int, ...);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_close (sem_t * sem);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_unlink (const char * name);
|
||||
|
||||
__PTW32_DLLPORT int __PTW32_CDECL sem_getvalue (sem_t * sem,
|
||||
int * sval);
|
||||
|
||||
__PTW32_END_C_DECLS
|
||||
|
||||
#endif /* !SEMAPHORE_H */
|
||||
872
pcappp/include/pcapplusplus/sndfile.h
Normal file
872
pcappp/include/pcapplusplus/sndfile.h
Normal file
@@ -0,0 +1,872 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
** sndfile.h -- system-wide definitions
|
||||
**
|
||||
** API documentation is in the doc/ directory of the source code tarball
|
||||
** and at http://libsndfile.github.io/libsndfile/api.html.
|
||||
*/
|
||||
|
||||
#ifndef SNDFILE_H
|
||||
#define SNDFILE_H
|
||||
|
||||
/* This is the version 1.0.X header file. */
|
||||
#define SNDFILE_1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* The following file types can be read and written.
|
||||
** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise
|
||||
** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and
|
||||
** SF_FORMAT_SUBMASK can be used to separate the major and minor file
|
||||
** types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /* Major formats. */
|
||||
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */
|
||||
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
|
||||
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
|
||||
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
|
||||
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
|
||||
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
|
||||
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
|
||||
SF_FORMAT_VOC = 0x080000, /* VOC files. */
|
||||
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
|
||||
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
|
||||
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
|
||||
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
|
||||
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
|
||||
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
|
||||
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
|
||||
SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */
|
||||
SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */
|
||||
SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */
|
||||
SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */
|
||||
SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */
|
||||
SF_FORMAT_CAF = 0x180000, /* Core Audio File format */
|
||||
SF_FORMAT_WVE = 0x190000, /* Psion WVE format */
|
||||
SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */
|
||||
SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */
|
||||
SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */
|
||||
|
||||
/* Subtypes from here on. */
|
||||
|
||||
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
|
||||
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
|
||||
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
|
||||
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
|
||||
|
||||
SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */
|
||||
|
||||
SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */
|
||||
SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */
|
||||
|
||||
SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */
|
||||
SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */
|
||||
SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */
|
||||
SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */
|
||||
|
||||
SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */
|
||||
SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */
|
||||
|
||||
SF_FORMAT_NMS_ADPCM_16 = 0x0022, /* 16kbs NMS G721-variant encoding. */
|
||||
SF_FORMAT_NMS_ADPCM_24 = 0x0023, /* 24kbs NMS G721-variant encoding. */
|
||||
SF_FORMAT_NMS_ADPCM_32 = 0x0024, /* 32kbs NMS G721-variant encoding. */
|
||||
|
||||
SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */
|
||||
SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */
|
||||
SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */
|
||||
|
||||
SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */
|
||||
|
||||
SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */
|
||||
SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */
|
||||
|
||||
SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */
|
||||
SF_FORMAT_OPUS = 0x0064, /* Xiph/Skype Opus encoding. */
|
||||
|
||||
SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */
|
||||
SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */
|
||||
SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */
|
||||
SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */
|
||||
|
||||
/* Endian-ness options. */
|
||||
|
||||
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
|
||||
SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */
|
||||
SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */
|
||||
SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */
|
||||
|
||||
SF_FORMAT_SUBMASK = 0x0000FFFF,
|
||||
SF_FORMAT_TYPEMASK = 0x0FFF0000,
|
||||
SF_FORMAT_ENDMASK = 0x30000000
|
||||
} ;
|
||||
|
||||
/*
|
||||
** The following are the valid command numbers for the sf_command()
|
||||
** interface. The use of these commands is documented in the file
|
||||
** command.html in the doc directory of the source code distribution.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFC_GET_LIB_VERSION = 0x1000,
|
||||
SFC_GET_LOG_INFO = 0x1001,
|
||||
SFC_GET_CURRENT_SF_INFO = 0x1002,
|
||||
|
||||
|
||||
SFC_GET_NORM_DOUBLE = 0x1010,
|
||||
SFC_GET_NORM_FLOAT = 0x1011,
|
||||
SFC_SET_NORM_DOUBLE = 0x1012,
|
||||
SFC_SET_NORM_FLOAT = 0x1013,
|
||||
SFC_SET_SCALE_FLOAT_INT_READ = 0x1014,
|
||||
SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015,
|
||||
|
||||
SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020,
|
||||
SFC_GET_SIMPLE_FORMAT = 0x1021,
|
||||
|
||||
SFC_GET_FORMAT_INFO = 0x1028,
|
||||
|
||||
SFC_GET_FORMAT_MAJOR_COUNT = 0x1030,
|
||||
SFC_GET_FORMAT_MAJOR = 0x1031,
|
||||
SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032,
|
||||
SFC_GET_FORMAT_SUBTYPE = 0x1033,
|
||||
|
||||
SFC_CALC_SIGNAL_MAX = 0x1040,
|
||||
SFC_CALC_NORM_SIGNAL_MAX = 0x1041,
|
||||
SFC_CALC_MAX_ALL_CHANNELS = 0x1042,
|
||||
SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043,
|
||||
SFC_GET_SIGNAL_MAX = 0x1044,
|
||||
SFC_GET_MAX_ALL_CHANNELS = 0x1045,
|
||||
|
||||
SFC_SET_ADD_PEAK_CHUNK = 0x1050,
|
||||
|
||||
SFC_UPDATE_HEADER_NOW = 0x1060,
|
||||
SFC_SET_UPDATE_HEADER_AUTO = 0x1061,
|
||||
|
||||
SFC_FILE_TRUNCATE = 0x1080,
|
||||
|
||||
SFC_SET_RAW_START_OFFSET = 0x1090,
|
||||
|
||||
SFC_SET_DITHER_ON_WRITE = 0x10A0,
|
||||
SFC_SET_DITHER_ON_READ = 0x10A1,
|
||||
|
||||
SFC_GET_DITHER_INFO_COUNT = 0x10A2,
|
||||
SFC_GET_DITHER_INFO = 0x10A3,
|
||||
|
||||
SFC_GET_EMBED_FILE_INFO = 0x10B0,
|
||||
|
||||
SFC_SET_CLIPPING = 0x10C0,
|
||||
SFC_GET_CLIPPING = 0x10C1,
|
||||
|
||||
SFC_GET_CUE_COUNT = 0x10CD,
|
||||
SFC_GET_CUE = 0x10CE,
|
||||
SFC_SET_CUE = 0x10CF,
|
||||
|
||||
SFC_GET_INSTRUMENT = 0x10D0,
|
||||
SFC_SET_INSTRUMENT = 0x10D1,
|
||||
|
||||
SFC_GET_LOOP_INFO = 0x10E0,
|
||||
|
||||
SFC_GET_BROADCAST_INFO = 0x10F0,
|
||||
SFC_SET_BROADCAST_INFO = 0x10F1,
|
||||
|
||||
SFC_GET_CHANNEL_MAP_INFO = 0x1100,
|
||||
SFC_SET_CHANNEL_MAP_INFO = 0x1101,
|
||||
|
||||
SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110,
|
||||
|
||||
/* Support for Wavex Ambisonics Format */
|
||||
SFC_WAVEX_SET_AMBISONIC = 0x1200,
|
||||
SFC_WAVEX_GET_AMBISONIC = 0x1201,
|
||||
|
||||
/*
|
||||
** RF64 files can be set so that on-close, writable files that have less
|
||||
** than 4GB of data in them are converted to RIFF/WAV, as per EBU
|
||||
** recommendations.
|
||||
*/
|
||||
SFC_RF64_AUTO_DOWNGRADE = 0x1210,
|
||||
|
||||
SFC_SET_VBR_ENCODING_QUALITY = 0x1300,
|
||||
SFC_SET_COMPRESSION_LEVEL = 0x1301,
|
||||
SFC_SET_OGG_PAGE_LATENCY_MS = 0x1302,
|
||||
SFC_SET_OGG_PAGE_LATENCY = 0x1303,
|
||||
|
||||
/* Cart Chunk support */
|
||||
SFC_SET_CART_INFO = 0x1400,
|
||||
SFC_GET_CART_INFO = 0x1401,
|
||||
|
||||
/* Opus files original samplerate metadata */
|
||||
SFC_SET_ORIGINAL_SAMPLERATE = 0x1500,
|
||||
SFC_GET_ORIGINAL_SAMPLERATE = 0x1501,
|
||||
|
||||
/* Following commands for testing only. */
|
||||
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
|
||||
|
||||
/*
|
||||
** These SFC_SET_ADD_* values are deprecated and will disappear at some
|
||||
** time in the future. They are guaranteed to be here up to and
|
||||
** including version 1.0.8 to avoid breakage of existing software.
|
||||
** They currently do nothing and will continue to do nothing.
|
||||
*/
|
||||
SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051,
|
||||
|
||||
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
|
||||
SFC_SET_ADD_DITHER_ON_READ = 0x1071
|
||||
} ;
|
||||
|
||||
|
||||
/*
|
||||
** String types that can be set and read from files. Not all file types
|
||||
** support this and even the file types which support one, may not support
|
||||
** all string types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_STR_TITLE = 0x01,
|
||||
SF_STR_COPYRIGHT = 0x02,
|
||||
SF_STR_SOFTWARE = 0x03,
|
||||
SF_STR_ARTIST = 0x04,
|
||||
SF_STR_COMMENT = 0x05,
|
||||
SF_STR_DATE = 0x06,
|
||||
SF_STR_ALBUM = 0x07,
|
||||
SF_STR_LICENSE = 0x08,
|
||||
SF_STR_TRACKNUMBER = 0x09,
|
||||
SF_STR_GENRE = 0x10
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Use the following as the start and end index when doing metadata
|
||||
** transcoding.
|
||||
*/
|
||||
|
||||
#define SF_STR_FIRST SF_STR_TITLE
|
||||
#define SF_STR_LAST SF_STR_GENRE
|
||||
|
||||
enum
|
||||
{ /* True and false */
|
||||
SF_FALSE = 0,
|
||||
SF_TRUE = 1,
|
||||
|
||||
/* Modes for opening files. */
|
||||
SFM_READ = 0x10,
|
||||
SFM_WRITE = 0x20,
|
||||
SFM_RDWR = 0x30,
|
||||
|
||||
SF_AMBISONIC_NONE = 0x40,
|
||||
SF_AMBISONIC_B_FORMAT = 0x41
|
||||
} ;
|
||||
|
||||
/* Public error values. These are guaranteed to remain unchanged for the duration
|
||||
** of the library major version number.
|
||||
** There are also a large number of private error numbers which are internal to
|
||||
** the library which can change at any time.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_ERR_NO_ERROR = 0,
|
||||
SF_ERR_UNRECOGNISED_FORMAT = 1,
|
||||
SF_ERR_SYSTEM = 2,
|
||||
SF_ERR_MALFORMED_FILE = 3,
|
||||
SF_ERR_UNSUPPORTED_ENCODING = 4
|
||||
} ;
|
||||
|
||||
|
||||
/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP).
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_CHANNEL_MAP_INVALID = 0,
|
||||
SF_CHANNEL_MAP_MONO = 1,
|
||||
SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */
|
||||
SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */
|
||||
SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT,
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT,
|
||||
SF_CHANNEL_MAP_FRONT_CENTER,
|
||||
SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */
|
||||
SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */
|
||||
SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */
|
||||
SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */
|
||||
SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */
|
||||
SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */
|
||||
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_W,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_X,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Y,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Z,
|
||||
|
||||
SF_CHANNEL_MAP_MAX
|
||||
} ;
|
||||
|
||||
|
||||
/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */
|
||||
|
||||
typedef struct SNDFILE_tag SNDFILE ;
|
||||
|
||||
/* The following typedef is system specific and is defined when libsndfile is
|
||||
** compiled. sf_count_t will be a 64 bit value when the underlying OS allows
|
||||
** 64 bit file offsets.
|
||||
** On windows, we need to allow the same header file to be compiler by both GCC
|
||||
** and the Microsoft compiler.
|
||||
*/
|
||||
|
||||
typedef __int64 sf_count_t ;
|
||||
#ifndef SF_COUNT_MAX
|
||||
#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||
#endif
|
||||
|
||||
|
||||
/* A pointer to a SF_INFO structure is passed to sf_open () and filled in.
|
||||
** On write, the SF_INFO structure is filled in by the user and passed into
|
||||
** sf_open ().
|
||||
*/
|
||||
|
||||
struct SF_INFO
|
||||
{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */
|
||||
int samplerate ;
|
||||
int channels ;
|
||||
int format ;
|
||||
int sections ;
|
||||
int seekable ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_INFO SF_INFO ;
|
||||
|
||||
/* The SF_FORMAT_INFO struct is used to retrieve information about the sound
|
||||
** file formats libsndfile supports using the sf_command () interface.
|
||||
**
|
||||
** Using this interface will allow applications to support new file formats
|
||||
** and encoding types when libsndfile is upgraded, without requiring
|
||||
** re-compilation of the application.
|
||||
**
|
||||
** Please consult the libsndfile documentation (particularly the information
|
||||
** on the sf_command () interface) for examples of its use.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int format ;
|
||||
const char *name ;
|
||||
const char *extension ;
|
||||
} SF_FORMAT_INFO ;
|
||||
|
||||
/*
|
||||
** Enums and typedefs for adding dither on read and write.
|
||||
** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
|
||||
** and SFC_SET_DITHER_ON_READ.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFD_DEFAULT_LEVEL = 0,
|
||||
SFD_CUSTOM_LEVEL = 0x40000000,
|
||||
|
||||
SFD_NO_DITHER = 500,
|
||||
SFD_WHITE = 501,
|
||||
SFD_TRIANGULAR_PDF = 502
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ int type ;
|
||||
double level ;
|
||||
const char *name ;
|
||||
} SF_DITHER_INFO ;
|
||||
|
||||
/* Struct used to retrieve information about a file embedded within a
|
||||
** larger file. See SFC_GET_EMBED_FILE_INFO.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t offset ;
|
||||
sf_count_t length ;
|
||||
} SF_EMBED_FILE_INFO ;
|
||||
|
||||
/*
|
||||
** Struct used to retrieve cue marker information from a file
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int32_t indx ;
|
||||
uint32_t position ;
|
||||
int32_t fcc_chunk ;
|
||||
int32_t chunk_start ;
|
||||
int32_t block_start ;
|
||||
uint32_t sample_offset ;
|
||||
char name [256] ;
|
||||
} SF_CUE_POINT ;
|
||||
|
||||
#define SF_CUES_VAR(count) \
|
||||
struct \
|
||||
{ uint32_t cue_count ; \
|
||||
SF_CUE_POINT cue_points [count] ; \
|
||||
}
|
||||
|
||||
typedef SF_CUES_VAR (100) SF_CUES ;
|
||||
|
||||
/*
|
||||
** Structs used to retrieve music sample information from a file.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /*
|
||||
** The loop mode field in SF_INSTRUMENT will be one of the following.
|
||||
*/
|
||||
SF_LOOP_NONE = 800,
|
||||
SF_LOOP_FORWARD,
|
||||
SF_LOOP_BACKWARD,
|
||||
SF_LOOP_ALTERNATING
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ int gain ;
|
||||
char basenote, detune ;
|
||||
char velocity_lo, velocity_hi ;
|
||||
char key_lo, key_hi ;
|
||||
int loop_count ;
|
||||
|
||||
struct
|
||||
{ int mode ;
|
||||
uint32_t start ;
|
||||
uint32_t end ;
|
||||
uint32_t count ;
|
||||
} loops [16] ; /* make variable in a sensible way */
|
||||
} SF_INSTRUMENT ;
|
||||
|
||||
|
||||
|
||||
/* Struct used to retrieve loop information from a file.*/
|
||||
typedef struct
|
||||
{
|
||||
short time_sig_num ; /* any positive integer > 0 */
|
||||
short time_sig_den ; /* any positive power of 2 > 0 */
|
||||
int loop_mode ; /* see SF_LOOP enum */
|
||||
|
||||
int num_beats ; /* this is NOT the amount of quarter notes !!!*/
|
||||
/* a full bar of 4/4 is 4 beats */
|
||||
/* a full bar of 7/8 is 7 beats */
|
||||
|
||||
float bpm ; /* suggestion, as it can be calculated using other fields:*/
|
||||
/* file's length, file's sampleRate and our time_sig_den*/
|
||||
/* -> bpms are always the amount of _quarter notes_ per minute */
|
||||
|
||||
int root_key ; /* MIDI note, or -1 for None */
|
||||
int future [6] ;
|
||||
} SF_LOOP_INFO ;
|
||||
|
||||
|
||||
/* Struct used to retrieve broadcast (EBU) information from a file.
|
||||
** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
|
||||
*/
|
||||
#define SF_BROADCAST_INFO_VAR(coding_hist_size) \
|
||||
struct \
|
||||
{ char description [256] ; \
|
||||
char originator [32] ; \
|
||||
char originator_reference [32] ; \
|
||||
char origination_date [10] ; \
|
||||
char origination_time [8] ; \
|
||||
uint32_t time_reference_low ; \
|
||||
uint32_t time_reference_high ; \
|
||||
short version ; \
|
||||
char umid [64] ; \
|
||||
int16_t loudness_value ; \
|
||||
int16_t loudness_range ; \
|
||||
int16_t max_true_peak_level ; \
|
||||
int16_t max_momentary_loudness ; \
|
||||
int16_t max_shortterm_loudness ; \
|
||||
char reserved [180] ; \
|
||||
uint32_t coding_history_size ; \
|
||||
char coding_history [coding_hist_size] ; \
|
||||
}
|
||||
|
||||
/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */
|
||||
typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ;
|
||||
|
||||
struct SF_CART_TIMER
|
||||
{ char usage [4] ;
|
||||
int32_t value ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_CART_TIMER SF_CART_TIMER ;
|
||||
|
||||
#define SF_CART_INFO_VAR(p_tag_text_size) \
|
||||
struct \
|
||||
{ char version [4] ; \
|
||||
char title [64] ; \
|
||||
char artist [64] ; \
|
||||
char cut_id [64] ; \
|
||||
char client_id [64] ; \
|
||||
char category [64] ; \
|
||||
char classification [64] ; \
|
||||
char out_cue [64] ; \
|
||||
char start_date [10] ; \
|
||||
char start_time [8] ; \
|
||||
char end_date [10] ; \
|
||||
char end_time [8] ; \
|
||||
char producer_app_id [64] ; \
|
||||
char producer_app_version [64] ; \
|
||||
char user_def [64] ; \
|
||||
int32_t level_reference ; \
|
||||
SF_CART_TIMER post_timers [8] ; \
|
||||
char reserved [276] ; \
|
||||
char url [1024] ; \
|
||||
uint32_t tag_text_size ; \
|
||||
char tag_text [p_tag_text_size] ; \
|
||||
}
|
||||
|
||||
typedef SF_CART_INFO_VAR (256) SF_CART_INFO ;
|
||||
|
||||
/* Virtual I/O functionality. */
|
||||
|
||||
typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_tell) (void *user_data) ;
|
||||
|
||||
struct SF_VIRTUAL_IO
|
||||
{ sf_vio_get_filelen get_filelen ;
|
||||
sf_vio_seek seek ;
|
||||
sf_vio_read read ;
|
||||
sf_vio_write write ;
|
||||
sf_vio_tell tell ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ;
|
||||
|
||||
|
||||
/* Open the specified file for read, write or both. On error, this will
|
||||
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
|
||||
** to sf_strerror ().
|
||||
** All calls to sf_open() should be matched with a call to sf_close().
|
||||
*/
|
||||
|
||||
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;
|
||||
|
||||
|
||||
/* Use the existing file descriptor to create a SNDFILE object. If close_desc
|
||||
** is TRUE, the file descriptor will be closed when sf_close() is called. If
|
||||
** it is FALSE, the descriptor will not be closed.
|
||||
** When passed a descriptor like this, the library will assume that the start
|
||||
** of file header is at the current file offset. This allows sound files within
|
||||
** larger container files to be read and/or written.
|
||||
** On error, this will return a NULL pointer. To find the error number, pass a
|
||||
** NULL SNDFILE to sf_strerror ().
|
||||
** All calls to sf_open_fd() should be matched with a call to sf_close().
|
||||
|
||||
*/
|
||||
|
||||
SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
|
||||
|
||||
SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
|
||||
|
||||
|
||||
/* sf_error () returns a error number which can be translated to a text
|
||||
** string using sf_error_number().
|
||||
*/
|
||||
|
||||
int sf_error (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_strerror () returns to the caller a pointer to the current error message for
|
||||
** the given SNDFILE.
|
||||
*/
|
||||
|
||||
const char* sf_strerror (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_error_number () allows the retrieval of the error string for each internal
|
||||
** error number.
|
||||
**
|
||||
*/
|
||||
|
||||
const char* sf_error_number (int errnum) ;
|
||||
|
||||
|
||||
/* The following two error functions are deprecated but they will remain in the
|
||||
** library for the foreseeable future. The function sf_strerror() should be used
|
||||
** in their place.
|
||||
*/
|
||||
|
||||
int sf_perror (SNDFILE *sndfile) ;
|
||||
int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
|
||||
|
||||
|
||||
/* Allow the caller to retrieve information from or change aspects of the
|
||||
** library behaviour.
|
||||
*/
|
||||
|
||||
int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ;
|
||||
|
||||
|
||||
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
|
||||
|
||||
int sf_format_check (const SF_INFO *info) ;
|
||||
|
||||
|
||||
/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
|
||||
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
|
||||
** stdio.h function fseek ().
|
||||
** An offset of zero with whence set to SEEK_SET will position the
|
||||
** read / write pointer to the first data sample.
|
||||
** On success sf_seek returns the current position in (multi-channel)
|
||||
** samples from the start of the file.
|
||||
** Please see the libsndfile documentation for moving the read pointer
|
||||
** separately from the write pointer on files open in mode SFM_RDWR.
|
||||
** On error all of these functions return -1.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_SEEK_SET = SEEK_SET,
|
||||
SF_SEEK_CUR = SEEK_CUR,
|
||||
SF_SEEK_END = SEEK_END
|
||||
} ;
|
||||
|
||||
sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ;
|
||||
|
||||
|
||||
/* Functions for retrieving and setting string data within sound files.
|
||||
** Not all file types support this features; AIFF and WAV do. For both
|
||||
** functions, the str_type parameter must be one of the SF_STR_* values
|
||||
** defined above.
|
||||
** On error, sf_set_string() returns non-zero while sf_get_string()
|
||||
** returns NULL.
|
||||
*/
|
||||
|
||||
int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
|
||||
|
||||
const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
|
||||
|
||||
|
||||
/* Return the library version string. */
|
||||
|
||||
const char * sf_version_string (void) ;
|
||||
|
||||
/* Return the current byterate at this point in the file. The byte rate in this
|
||||
** case is the number of bytes per second of audio data. For instance, for a
|
||||
** stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate
|
||||
** would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec.
|
||||
** For some file formats the returned value will be accurate and exact, for some
|
||||
** it will be a close approximation, for some it will be the average bitrate for
|
||||
** the whole file and for some it will be a time varying value that was accurate
|
||||
** when the file was most recently read or written.
|
||||
** To get the bitrate, multiple this value by 8.
|
||||
** Returns -1 for unknown.
|
||||
*/
|
||||
int sf_current_byterate (SNDFILE *sndfile) ;
|
||||
|
||||
/* Functions for reading/writing the waveform data of a sound file.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of frames.
|
||||
** The number of items actually read/written = frames * number of channels.
|
||||
** sf_xxxx_raw read/writes the raw data bytes from/to the file
|
||||
** sf_xxxx_short passes data in the native short format
|
||||
** sf_xxxx_int passes data in the native int format
|
||||
** sf_xxxx_float passes data in the native float format
|
||||
** sf_xxxx_double passes data in the native double format
|
||||
** All of these read/write function return number of frames read/written.
|
||||
*/
|
||||
|
||||
sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of items.
|
||||
** Otherwise similar to above.
|
||||
** All of these read/write function return number of items read/written.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ;
|
||||
|
||||
|
||||
/* Close the SNDFILE and clean up all memory allocations associated with this
|
||||
** file.
|
||||
** Returns 0 on success, or an error number.
|
||||
*/
|
||||
|
||||
int sf_close (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
|
||||
** to force the writing of data to disk. If the file is opened SFM_READ
|
||||
** no action is taken.
|
||||
*/
|
||||
|
||||
void sf_write_sync (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
|
||||
/* The function sf_wchar_open() is Windows Only!
|
||||
** Open a file passing in a Windows Unicode filename. Otherwise, this is
|
||||
** the same as sf_open().
|
||||
**
|
||||
** In order for this to work, you need to do the following:
|
||||
**
|
||||
** #include <windows.h>
|
||||
** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
|
||||
** #including <sndfile.h>
|
||||
*/
|
||||
|
||||
#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES)
|
||||
SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Getting and setting of chunks from within a sound file.
|
||||
**
|
||||
** These functions allow the getting and setting of chunks within a sound file
|
||||
** (for those formats which allow it).
|
||||
**
|
||||
** These functions fail safely. Specifically, they will not allow you to overwrite
|
||||
** existing chunks or add extra versions of format specific reserved chunks but
|
||||
** should allow you to retrieve any and all chunks (may not be implemented for
|
||||
** all chunks or all file formats).
|
||||
*/
|
||||
|
||||
struct SF_CHUNK_INFO
|
||||
{ char id [64] ; /* The chunk identifier. */
|
||||
unsigned id_size ; /* The size of the chunk identifier. */
|
||||
unsigned datalen ; /* The size of that data. */
|
||||
void *data ; /* Pointer to the data. */
|
||||
} ;
|
||||
|
||||
typedef struct SF_CHUNK_INFO SF_CHUNK_INFO ;
|
||||
|
||||
/* Set the specified chunk info (must be done before any audio data is written
|
||||
** to the file). This will fail for format specific reserved chunks.
|
||||
** The chunk_info->data pointer must be valid until the file is closed.
|
||||
** Returns SF_ERR_NO_ERROR on success or non-zero on failure.
|
||||
*/
|
||||
int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/*
|
||||
** An opaque structure to an iterator over the all chunks of a given id
|
||||
*/
|
||||
typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ;
|
||||
|
||||
/* Get an iterator for all chunks matching chunk_info.
|
||||
** The iterator will point to the first chunk matching chunk_info.
|
||||
** Chunks are matching, if (chunk_info->id) matches the first
|
||||
** (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle.
|
||||
** If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle
|
||||
** is returned.
|
||||
** The values of chunk_info->datalen and chunk_info->data are ignored.
|
||||
** If no matching chunks are found in the sndfile, NULL is returned.
|
||||
** The returned iterator will stay valid until one of the following occurs:
|
||||
** a) The sndfile is closed.
|
||||
** b) A new chunk is added using sf_set_chunk().
|
||||
** c) Another chunk iterator function is called on the same SNDFILE* handle
|
||||
** that causes the iterator to be modified.
|
||||
** The memory for the iterator belongs to the SNDFILE* handle and is freed when
|
||||
** sf_close() is called.
|
||||
*/
|
||||
SF_CHUNK_ITERATOR *
|
||||
sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/* Iterate through chunks by incrementing the iterator.
|
||||
** Increments the iterator and returns a handle to the new one.
|
||||
** After this call, iterator will no longer be valid, and you must use the
|
||||
** newly returned handle from now on.
|
||||
** The returned handle can be used to access the next chunk matching
|
||||
** the criteria as defined in sf_get_chunk_iterator().
|
||||
** If iterator points to the last chunk, this will free all resources
|
||||
** associated with iterator and return NULL.
|
||||
** The returned iterator will stay valid until sf_get_chunk_iterator_next
|
||||
** is called again, the sndfile is closed or a new chunk us added.
|
||||
*/
|
||||
SF_CHUNK_ITERATOR *
|
||||
sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ;
|
||||
|
||||
|
||||
/* Get the size of the specified chunk.
|
||||
** If the specified chunk exists, the size will be returned in the
|
||||
** datalen field of the SF_CHUNK_INFO struct.
|
||||
** Additionally, the id of the chunk will be copied to the id
|
||||
** field of the SF_CHUNK_INFO struct and it's id_size field will
|
||||
** be updated accordingly.
|
||||
** If the chunk doesn't exist chunk_info->datalen will be zero, and the
|
||||
** id and id_size fields will be undefined.
|
||||
** The function will return SF_ERR_NO_ERROR on success or non-zero on
|
||||
** failure.
|
||||
*/
|
||||
int
|
||||
sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/* Get the specified chunk data.
|
||||
** If the specified chunk exists, up to chunk_info->datalen bytes of
|
||||
** the chunk data will be copied into the chunk_info->data buffer
|
||||
** (allocated by the caller) and the chunk_info->datalen field
|
||||
** updated to reflect the size of the data. The id and id_size
|
||||
** field will be updated according to the retrieved chunk
|
||||
** If the chunk doesn't exist chunk_info->datalen will be zero, and the
|
||||
** id and id_size fields will be undefined.
|
||||
** The function will return SF_ERR_NO_ERROR on success or non-zero on
|
||||
** failure.
|
||||
*/
|
||||
int
|
||||
sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SNDFILE_H */
|
||||
452
pcappp/include/pcapplusplus/sndfile.hh
Normal file
452
pcappp/include/pcapplusplus/sndfile.hh
Normal file
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The above modified BSD style license (GPL and LGPL compatible) applies to
|
||||
** this file. It does not apply to libsndfile itself which is released under
|
||||
** the GNU LGPL or the libsndfile test suite which is released under the GNU
|
||||
** GPL.
|
||||
** This means that this header file can be used under this modified BSD style
|
||||
** license, but the LGPL still holds for the libsndfile library itself.
|
||||
*/
|
||||
|
||||
/*
|
||||
** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API.
|
||||
**
|
||||
** All the methods are inlines and all functionality is contained in this
|
||||
** file. There is no separate implementation file.
|
||||
**
|
||||
** API documentation is in the doc/ directory of the source code tarball
|
||||
** and at http://libsndfile.github.io/libsndfile/api.html.
|
||||
*/
|
||||
|
||||
#ifndef SNDFILE_HH
|
||||
#define SNDFILE_HH
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include <string>
|
||||
#include <new> // for std::nothrow
|
||||
|
||||
#if __cplusplus < 201100
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class SndfileHandle
|
||||
{ private :
|
||||
struct SNDFILE_ref
|
||||
{ SNDFILE_ref (void) ;
|
||||
~SNDFILE_ref (void) ;
|
||||
|
||||
SNDFILE *sf ;
|
||||
SF_INFO sfinfo ;
|
||||
int ref ;
|
||||
} ;
|
||||
|
||||
SNDFILE_ref *p ;
|
||||
|
||||
public :
|
||||
/* Default constructor */
|
||||
SndfileHandle (void) : p (nullptr) {} ;
|
||||
SndfileHandle (const char *path, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (std::string const & path, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (int fd, bool close_desc, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
SndfileHandle (LPCWSTR wpath, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
#endif
|
||||
|
||||
~SndfileHandle (void) ;
|
||||
|
||||
SndfileHandle (const SndfileHandle &orig) ;
|
||||
SndfileHandle & operator = (const SndfileHandle &rhs) ;
|
||||
|
||||
/* Mainly for debugging/testing. */
|
||||
int refCount (void) const { return (p == nullptr) ? 0 : p->ref ; }
|
||||
|
||||
operator bool () const { return (p != nullptr) ; }
|
||||
|
||||
bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
|
||||
|
||||
sf_count_t frames (void) const { return p ? p->sfinfo.frames : 0 ; }
|
||||
int format (void) const { return p ? p->sfinfo.format : 0 ; }
|
||||
int channels (void) const { return p ? p->sfinfo.channels : 0 ; }
|
||||
int samplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; }
|
||||
|
||||
int error (void) const ;
|
||||
const char * strError (void) const ;
|
||||
|
||||
int command (int cmd, void *data, int datasize) ;
|
||||
|
||||
sf_count_t seek (sf_count_t frames, int whence) ;
|
||||
|
||||
void writeSync (void) ;
|
||||
|
||||
int setString (int str_type, const char* str) ;
|
||||
|
||||
const char* getString (int str_type) const ;
|
||||
|
||||
static int formatCheck (int format, int channels, int samplerate) ;
|
||||
|
||||
sf_count_t read (short *ptr, sf_count_t items) ;
|
||||
sf_count_t read (int *ptr, sf_count_t items) ;
|
||||
sf_count_t read (float *ptr, sf_count_t items) ;
|
||||
sf_count_t read (double *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t write (const short *ptr, sf_count_t items) ;
|
||||
sf_count_t write (const int *ptr, sf_count_t items) ;
|
||||
sf_count_t write (const float *ptr, sf_count_t items) ;
|
||||
sf_count_t write (const double *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t readf (short *ptr, sf_count_t frames) ;
|
||||
sf_count_t readf (int *ptr, sf_count_t frames) ;
|
||||
sf_count_t readf (float *ptr, sf_count_t frames) ;
|
||||
sf_count_t readf (double *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t writef (const short *ptr, sf_count_t frames) ;
|
||||
sf_count_t writef (const int *ptr, sf_count_t frames) ;
|
||||
sf_count_t writef (const float *ptr, sf_count_t frames) ;
|
||||
sf_count_t writef (const double *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t readRaw (void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
/**< Raw access to the handle. SndfileHandle keeps ownership. */
|
||||
SNDFILE * rawHandle (void) ;
|
||||
|
||||
/**< Take ownership of handle, if reference count is 1. */
|
||||
SNDFILE * takeOwnership (void) ;
|
||||
} ;
|
||||
|
||||
/*==============================================================================
|
||||
** Nothing but implementation below.
|
||||
*/
|
||||
|
||||
inline
|
||||
SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
|
||||
: sf (nullptr), sfinfo (), ref (1)
|
||||
{}
|
||||
|
||||
inline
|
||||
SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
|
||||
{ if (sf != nullptr) sf_close (sf) ; }
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open (path, mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle const char * constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open (path.c_str (), mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle std::string constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
{
|
||||
if (fd < 0)
|
||||
return ;
|
||||
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle fd constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open_virtual (&sfvirtual, mode, &p->sfinfo, user_data) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle std::string constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::~SndfileHandle (void)
|
||||
{ if (p != nullptr && -- p->ref == 0)
|
||||
delete p ;
|
||||
} /* SndfileHandle destructor */
|
||||
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (const SndfileHandle &orig)
|
||||
: p (orig.p)
|
||||
{ if (p != nullptr)
|
||||
++ p->ref ;
|
||||
} /* SndfileHandle copy constructor */
|
||||
|
||||
inline SndfileHandle &
|
||||
SndfileHandle::operator = (const SndfileHandle &rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this ;
|
||||
if (p != nullptr && -- p->ref == 0)
|
||||
delete p ;
|
||||
|
||||
p = rhs.p ;
|
||||
if (p != nullptr)
|
||||
++ p->ref ;
|
||||
|
||||
return *this ;
|
||||
} /* SndfileHandle assignment operator */
|
||||
|
||||
inline int
|
||||
SndfileHandle::error (void) const
|
||||
{ return sf_error (p->sf) ; }
|
||||
|
||||
inline const char *
|
||||
SndfileHandle::strError (void) const
|
||||
{ return sf_strerror (p->sf) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::command (int cmd, void *data, int datasize)
|
||||
{ return sf_command (p->sf, cmd, data, datasize) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::seek (sf_count_t frame_count, int whence)
|
||||
{ return sf_seek (p->sf, frame_count, whence) ; }
|
||||
|
||||
inline void
|
||||
SndfileHandle::writeSync (void)
|
||||
{ sf_write_sync (p->sf) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::setString (int str_type, const char* str)
|
||||
{ return sf_set_string (p->sf, str_type, str) ; }
|
||||
|
||||
inline const char*
|
||||
SndfileHandle::getString (int str_type) const
|
||||
{ return sf_get_string (p->sf, str_type) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::formatCheck (int fmt, int chans, int srate)
|
||||
{
|
||||
SF_INFO sfinfo ;
|
||||
|
||||
sfinfo.frames = 0 ;
|
||||
sfinfo.channels = chans ;
|
||||
sfinfo.format = fmt ;
|
||||
sfinfo.samplerate = srate ;
|
||||
sfinfo.sections = 0 ;
|
||||
sfinfo.seekable = 0 ;
|
||||
|
||||
return sf_format_check (&sfinfo) ;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (short *ptr, sf_count_t items)
|
||||
{ return sf_read_short (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (int *ptr, sf_count_t items)
|
||||
{ return sf_read_int (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (float *ptr, sf_count_t items)
|
||||
{ return sf_read_float (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (double *ptr, sf_count_t items)
|
||||
{ return sf_read_double (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const short *ptr, sf_count_t items)
|
||||
{ return sf_write_short (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const int *ptr, sf_count_t items)
|
||||
{ return sf_write_int (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const float *ptr, sf_count_t items)
|
||||
{ return sf_write_float (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const double *ptr, sf_count_t items)
|
||||
{ return sf_write_double (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (short *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_short (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (int *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_int (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (float *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_float (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (double *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_double (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const short *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_short (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const int *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_int (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const float *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_float (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const double *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_double (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readRaw (void *ptr, sf_count_t bytes)
|
||||
{ return sf_read_raw (p->sf, ptr, bytes) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
|
||||
{ return sf_write_raw (p->sf, ptr, bytes) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::rawHandle (void)
|
||||
{ return (p ? p->sf : nullptr) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::takeOwnership (void)
|
||||
{
|
||||
if (p == nullptr || (p->ref != 1))
|
||||
return nullptr ;
|
||||
|
||||
SNDFILE * sf = p->sf ;
|
||||
p->sf = nullptr ;
|
||||
delete p ;
|
||||
p = nullptr ;
|
||||
return sf ;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle const wchar_t * constructor */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SNDFILE_HH */
|
||||
|
||||
Reference in New Issue
Block a user