diff options
Diffstat (limited to 'src/lib/dhcp/duid_factory.h')
-rw-r--r-- | src/lib/dhcp/duid_factory.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/lib/dhcp/duid_factory.h b/src/lib/dhcp/duid_factory.h new file mode 100644 index 0000000..d3d6f71 --- /dev/null +++ b/src/lib/dhcp/duid_factory.h @@ -0,0 +1,185 @@ +// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef DUID_FACTORY_H +#define DUID_FACTORY_H + +#include <dhcp/duid.h> +#include <boost/noncopyable.hpp> +#include <stdint.h> +#include <string> +#include <vector> + +namespace isc { +namespace dhcp { + +/// @brief Factory for generating DUIDs (DHCP Unique Identifiers). +/// +/// DHCPv6 clients and servers are identified by DUIDs (see RFC 8415). +/// DUIDs are unique identifiers carried in the appropriate DHCP +/// options. RFC 8415 defines 4 types of DUIDs: +/// -# DUID-LLT +/// -# DUID-EN +/// -# DUID-LL +/// -# DUID-UUID +/// +/// of which the DUID-LLT is recommended for all general purpose computing +/// devices. Future specifications may define new DUID types. The current +/// implementation of the class only supports DUID types defined in RFC 8415. +/// +/// In most cases DUIDs can be generated automatically, i.e. no manual +/// configuration is required. For example, DUID-LLT is composed of the +/// current time and link layer address and type of one of the network +/// interfaces. Once the DUID is generated it should be stored in the persistent +/// storage and used by a server or client even when the network interface which +/// address had been used to generate the DUID is removed. +/// +/// In some cases administrators may elect to use other types of DUIDs, which +/// are easier to generate (in case of lack of persistent storage or when +/// specifics of the device favors some generation methods), e.g. DUID-EN +/// doesn't rely on the link layer addresses of interfaces present in the +/// system. +/// +/// In some cases administrators may want to influence the value of the +/// generated DUID. For example, DUID-EN includes enterprise identifier and +/// the administrator may want to select this identifier. +/// +/// This class allows for selecting a type of DUID to be generated. It also +/// allows for setting desired values for the components of the DUIDs +/// being generated, while leaving other components unspecified. For example +/// an administrator may elect to set the enterprise id for the DUID-EN +/// and leave the variable length identifier unspecified. The variable +/// length identifier will be autogenerated. +/// +/// This class is also responsible for storing the generated DUID in a +/// file. The location of this file is specified in the class constructor. +/// If this location is not specified the DUID is not stored, i.e. is +/// lost when the server or client shuts down. However, the DUID may be +/// reconstructed according to the configuration of the client or server +/// when they are back online. +class DUIDFactory : public boost::noncopyable { +public: + + /// @brief Constructor. + /// + /// @param storage_location Absolute path to the file where DUID is + /// stored. + DUIDFactory(const std::string& storage_location = ""); + + /// @brief Checks if generated DUID will be stored in the file. + /// + /// @return true if generated DUIDs are stored in a file, false + /// otherwise. + bool isStored() const; + + /// @brief Generates DUID-LLT. + /// + /// This method generates DUID-LLT (Link Layer plus Time). + /// + /// @param htype Hardware type. If this is set to 0 and link layer + /// address is empty a value from existing DUID or a default value + /// of @c HTYPE_ETHER is used. Otherwise a link layer type of selected + /// interface is used. + /// @param time_in Explicit value of time for the DUID. If this is + /// set to 0 a value from existing DUID or current time is used, + /// otherwise a value specified is used. + /// @param ll_identifier Data to be used as link layer address. If + /// this is an empty vector this method will try to use link layer + /// address from existing DUID. If there is no DUID yet, it will + /// iterate over all active interfaces and will pick link layer + /// address of one of them. + /// + /// @throw isc::Unexpected if none of the interfaces includes has a + /// suitable link layer address. + void createLLT(const uint16_t htype, const uint32_t time_in, + const std::vector<uint8_t>& ll_identifier); + + /// @brief Generates DUID-EN. + /// + /// This method generates DUID-EN (DUID Enterprise). + /// + /// @param enterprise_id Enterprise id. If this value is 0, a value + /// from existing DUID is used or ISC's enterprise id if there is + /// no DUID yet. + /// @param identifier Data to be used as variable length identifier. + /// If this is an empty vector, an identifier from existing DUID is + /// used. If there is no DUID yet, the 6-bytes long vector with random + /// values is generated. + void createEN(const uint32_t enterprise_id, + const std::vector<uint8_t>& identifier); + + /// @brief Generates DUID-LL. + /// + /// This method generates DUID-LL (Link Layer). + /// + /// @param htype Hardware type. If this is set to 0 and link layer + /// address is empty a value from existing DUID or a default value + /// of @c HTYPE_ETHER is used. Otherwise a link layer type of selected + /// interface is used. + /// @param ll_identifier Data to be used as link layer address. If + /// this is an empty vector this method will try to use link layer + /// address from existing DUID. If there is no DUID yet, it will + /// iterate over all active interfaces and will pick link layer + /// address of one of them. + /// + /// @throw isc::Unexpected if none of the interfaces includes has a + /// suitable link layer address. + void createLL(const uint16_t htype, + const std::vector<uint8_t>& ll_identifier); + + /// @brief Returns current DUID. + /// + /// This method first checks if the DUID has been generated, i.e. as a + /// result of calling DUIDFactory::createLLT. If the DUID hasn't been + /// generated, this method will try to read the DUID from the persistent + /// storage. If the DUID is found in persistent storage it is returned. + /// Otherwise, the DUID-LLT is generated and returned. In some cases the + /// generation of the DUID-LLT may fail, e.g. when there are no interfaces + /// with a suitable link layer address. In this case, this method will + /// generate DUID-EN, with the ISC enterprise id. If this fails, e.g. as a + /// result of error while storing the generated DUID-EN, exception + /// is thrown. + /// + /// @return Instance of the DUID read from file, or generated. + DuidPtr get(); + +private: + + /// @brief Creates link layer identifier. + /// + /// This method iterates over existing network interfaces and finds the + /// one with a suitable link layer address to generate a DUID-LLT or + /// DUID-LL. It uses selected link layer address to generate identifier + /// held in those DUID types. + /// + /// @param [out] identifier Link layer address for the DUID. + /// @param [out] htype Link layer type to be included in the DUID. + void createLinkLayerId(std::vector<uint8_t>& identifier, + uint16_t& htype) const; + + /// @brief Sets a new DUID as current. + /// + /// The generated DUID is stored in the file, if such file is specified. + /// The new DUID will be returned when @c DUIDFactory::get is called. + /// + /// @param duid_vector New DUID represented as vector of bytes. + void set(const std::vector<uint8_t>& duid_vector); + + /// @brief Reads DUID from file, if file exists. + void readFromFile(); + + /// @brief Location of the file holding generated DUID (if specified). + std::string storage_location_; + + /// @brief Pointer to generated DUID. + DuidPtr duid_; + +}; + +}; // end of isc::dhcp namespace +}; // end of isc namespace + +#endif /* DUID_FACTORY_H */ |