/* * Copyright (c) 2012, Nasel * 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. * * 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 TINS_DHCPV6_H #define TINS_DHCPV6_H #include #include "pdu.h" #include "endianness.h" #include "small_uint.h" #include "ipv6_address.h" #include "pdu_option.h" namespace Tins { /** * Represents a DHCPv6 PDU. */ class DHCPv6 : public PDU { public: /** * Represents a DHCPv6 option. */ class dhcpv6_option { public: typedef std::vector container_type; typedef container_type::value_type data_type; typedef uint16_t option_type; /** * \brief Constructs a PDUOption. * \param opt The option type. * \param length The option's data length. * \param data The option's data(if any). */ dhcpv6_option(option_type opt = 0, size_t length = 0, const data_type *data = 0) : option_(opt), option_size_(length) { if(data) value_.insert(value_.end(), data, data + length); } /** * \brief Constructs a PDUOption from iterators, which * indicate the data to be stored in it. * * \param opt The option type. * \param start The beginning of the option data. * \param end The end of the option data. */ template dhcpv6_option(option_type opt, ForwardIterator start, ForwardIterator end) : option_(opt), option_size_(std::distance(start, end)) { value_.insert(value_.end(), start, end); } /** * Retrieves this option's type. * \return uint8_t containing this option's size. */ uint16_t option() const { return option_; } /** * Sets this option's type * \param opt The option type to be set. */ void option(uint16_t opt) { option_ = opt; } /** * Retrieves this option's data. * * If this method is called when data_size() == 0, * dereferencing the returned pointer will result in undefined * behaviour. * * \return const data_type& containing this option's value. */ const data_type *data_ptr() const { return &*value_.begin(); } /** * Retrieves the length of this option's data. */ uint16_t data_size() const { return option_size_; } private: option_type option_; uint16_t option_size_; container_type value_; }; /** * The message types. */ enum MessageType { SOLICIT = 1, ADVERTISE, REQUEST, CONFIRM, RENEW, REBIND, REPLY, RELEASE, DECLINE, RECONFIGURE, INFO_REQUEST, RELAY_FORWARD, RELAY_REPLY, LEASE_QUERY, LEASE_QUERY_REPLY, LEASE_QUERY_DONE, LEASE_QUERY_DATA }; /** * The DHCPv6 options. */ enum Option { CLIENTID = 1, SERVERID, IA_NA, IA_TA, IA_ADDR, OPTION_REQUEST, PREFERENCE, ELAPSED_TIME, RELAY_MSG, AUTH = 11, UNICAST, STATUS_CODE, RAPID_COMMIT, USER_CLASS, VENDOR_CLASS, VENDOR_OPTS, INTERFACE_ID, RECONF_MSG, RECONF_ACCEPT, SIP_SERVER_D, SIP_SERVER_A, DNS_SERVERS, DOMAIN_LIST, IA_PD, IAPREFIX, NIS_SERVERS, NISP_SERVERS, NIS_DOMAIN_NAME, NISP_DOMAIN_NAME, SNTP_SERVERS, INFORMATION_REFRESH_TIME, BCMCS_SERVER_D, BCMCS_SERVER_A, GEOCONF_CIVIC = 36, REMOTE_ID, SUBSCRIBER_ID, CLIENT_FQDN, PANA_AGENT, NEW_POSIX_TIMEZONE, NEW_TZDB_TIMEZONE, ERO, LQ_QUERY, CLIENT_DATA, CLT_TIME, LQ_RELAY_DATA, LQ_CLIENT_LINK, MIP6_HNIDF, MIP6_VDINF, V6_LOST, CAPWAP_AC_V6, RELAY_ID, NTP_SERVER, V6_ACCESS_DOMAIN, SIP_UA_CS_LIST, BOOTFILE_URL, BOOTFILE_PARAM, CLIENT_ARCH_TYPE, NII, GEOLOCATION, AFTR_NAME, ERP_LOCAL_DOMAIN_NAME, RSOO, PD_EXCLUDE, VSS, MIP6_IDINF, MIP6_UDINF, MIP6_HNP, MIP6_HAA, MIP6_HAF, RDNSS_SELECTION, KRB_PRINCIPAL_NAME, KRB_REALM_NAME, KRB_DEFAULT_REALM_NAME, KRB_KDC }; /** * The type used to store the DHCPv6 options. */ typedef std::list options_type; /** * The type used to store IP addresses. */ typedef IPv6Address ipaddress_type; /** * This PDU's flag. */ static const PDU::PDUType pdu_flag = PDU::DHCPv6; /** * The type used to store the Identity Association for Non-Temporary * Addresses option. */ struct ia_na_type { typedef std::vector options_type; uint32_t id, t1, t2; options_type options; ia_na_type(uint32_t id = 0, uint32_t t1 = 0, uint32_t t2 = 0, const options_type& options = options_type()) : id(id), t1(t1), t2(t2), options(options) {} }; /** * The type used to store the Identity Association for Temporary * Addresses option. */ struct ia_ta_type { typedef std::vector options_type; uint32_t id; options_type options; ia_ta_type(uint32_t id = 0, const options_type& options = options_type()) : id(id), options(options) {} }; /** * The type used to store the Identity Association Address option. */ struct ia_address_type { typedef std::vector options_type; ipaddress_type address; uint32_t preferred_lifetime, valid_lifetime; options_type options; ia_address_type(ipaddress_type address = ipaddress_type(), uint32_t preferred_lifetime = 0, uint32_t valid_lifetime = 0, const options_type& options = options_type()) : address(address), preferred_lifetime(preferred_lifetime), valid_lifetime(valid_lifetime), options(options) {} }; /** * The type used to store the Authentication option. */ struct authentication_type { typedef std::vector auth_info_type; uint8_t protocol, algorithm, rdm; uint64_t replay_detection; auth_info_type auth_info; authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0, uint8_t rdm = 0, uint64_t replay_detection = 0, const auth_info_type &auth_info = auth_info_type()) : protocol(protocol), algorithm(algorithm), rdm(rdm), replay_detection(replay_detection), auth_info(auth_info) {} }; /** * The type used to store the Status Code option. */ struct status_code_type { uint16_t code; std::string message; status_code_type(uint16_t code = 0, const std::string &message = "") : code(code), message(message) { } }; /** * The type used to store the Vendor-specific Information option. */ struct vendor_info_type { typedef std::vector data_type; uint32_t enterprise_number; data_type data; vendor_info_type(uint32_t enterprise_number = 0, const data_type &data = data_type()) : enterprise_number(enterprise_number), data(data) { } }; /** * The type used to store the User Class option's user class data. */ typedef std::vector class_option_data_type; /** * The type used to store the User Class option. */ typedef std::vector user_class_type; /** * The type used to store the Vendor Class option. */ struct vendor_class_type { typedef std::vector class_data_type; uint32_t enterprise_number; class_data_type vendor_class_data; vendor_class_type(uint32_t enterprise_number = 0, const class_data_type &vendor_class_data = class_data_type()) : enterprise_number(enterprise_number), vendor_class_data(vendor_class_data) { } }; /** * The type used to represent DUIDs Based on Link-layer Address Plus * Time. */ struct duid_llt { static const uint16_t duid_id = 1; typedef std::vector lladdress_type; uint16_t hw_type; uint32_t time; lladdress_type lladdress; duid_llt(uint16_t hw_type = 0, uint32_t time = 0, const lladdress_type &lladdress = lladdress_type()) : hw_type(hw_type), time(time), lladdress(lladdress) {} PDU::serialization_type serialize() const; static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz); }; /** * The type used to represent DUIDs Based on Enterprise Number */ struct duid_en { static const uint16_t duid_id = 2; typedef std::vector identifier_type; uint32_t enterprise_number; identifier_type identifier; duid_en(uint32_t enterprise_number = 0, const identifier_type &identifier = identifier_type()) : enterprise_number(enterprise_number), identifier(identifier) {} PDU::serialization_type serialize() const; static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz); }; /** * The type used to represent DUIDs Based on Link-layer Address. */ struct duid_ll { static const uint16_t duid_id = 3; typedef std::vector lladdress_type; uint16_t hw_type; lladdress_type lladdress; duid_ll(uint16_t hw_type = 0, const lladdress_type &lladdress = lladdress_type()) : hw_type(hw_type), lladdress(lladdress) {} PDU::serialization_type serialize() const; static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz); }; /** * Type type used to represent DUIDs. This will be stored as the * value for the Client/Server Identifier options. */ struct duid_type { typedef PDU::serialization_type data_type; uint16_t id; data_type data; duid_type(uint16_t id = 0, const data_type &data = data_type()) : id(id), data(data) {} duid_type(const duid_llt &identifier) : id(duid_llt::duid_id), data(identifier.serialize()) {} duid_type(const duid_en &identifier) : id(duid_en::duid_id), data(identifier.serialize()) {} duid_type(const duid_ll &identifier) : id(duid_en::duid_id), data(identifier.serialize()) {} }; /** * The type used to store the Option Request option. */ typedef std::vector