// 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 #include #include #include #include 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& 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& 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& 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& 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& 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 */