755 lines
28 KiB
C++
755 lines
28 KiB
C++
#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 */
|