455 lines
16 KiB
C++
455 lines
16 KiB
C++
#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
|