#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 { 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 */ explicit 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(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(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 */ 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 */ 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 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 data && dataLen >= sizeof(dhcpv6_header); } } # endif // PACKETPP_DHCPV6_LAYER