// Copyright (C) 2012-2022 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 SUBNET_H #define SUBNET_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace isc { namespace dhcp { class Subnet : public virtual Network { public: /// @brief checks if specified address is in range. /// /// @param addr this address will be checked if it is included in a specific /// range /// @return true if address is in range, false otherwise bool inRange(const isc::asiolink::IOAddress& addr) const; /// @brief checks if the specified address is in pools. /// /// Note the difference between inRange() and inPool() for addresses /// (i.e. *not* prefixes). For a given subnet (e.g. 2001::/64) there /// may be one or more pools defined that may or may not cover /// entire subnet, e.g. pool 2001::1-2001::10). inPool() returning /// true implies inRange(), but the reverse implication is not /// always true. For the given example, 2001::1234:abcd would return /// true for inRange(), but false for inPool() check. /// /// @param type type of pools to iterate over /// @param addr this address will be checked if it belongs to any pools in /// that subnet /// @return true if the address is in any of the pools bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const; /// @brief checks if the specified address is in allowed pools. /// /// This takes also into account client classes /// /// @param type type of pools to iterate over /// @param addr this address will be checked if it belongs to any pools in /// that subnet /// @param client_classes client class list which must be allowed /// @return true if the address is in any of the allowed pools bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr, const ClientClasses& client_classes) const; /// @brief returns the last address that was tried from this subnet. /// /// This method returns the last address that was attempted to be allocated /// from this subnet. This is used as helper information for the next /// iteration of the allocation algorithm. /// /// @note: this routine is Kea thread safe. /// /// @todo: Define map somewhere in the /// AllocEngine::IterativeAllocator and keep the data there /// /// @param type lease type to be returned /// @return address/prefix that was last tried from this subnet isc::asiolink::IOAddress getLastAllocated(Lease::Type type) const; /// @brief Returns the timestamp when the @c setLastAllocated function /// was called. /// /// @note: this routine is Kea thread safe. /// /// @param lease_type Lease type for which last allocation timestamp should /// be returned. /// /// @return Time when a lease of a specified type has been allocated from /// this subnet. The negative infinity time is returned if a lease type is /// not recognized (which is unlikely). boost::posix_time::ptime getLastAllocatedTime(const Lease::Type& lease_type) const; /// @brief sets the last address that was tried from this subnet. /// /// This method sets the last address that was attempted to be allocated /// from this subnet. This is used as helper information for the next /// iteration of the allocation algorithm. /// /// @note: this routine is Kea thread safe. /// /// @todo: Define map somewhere in the /// AllocEngine::IterativeAllocator and keep the data there /// @param addr address/prefix to that was tried last /// @param type lease type to be set void setLastAllocated(Lease::Type type, const isc::asiolink::IOAddress& addr); /// @brief Returns unique ID for that subnet. /// /// @return unique ID for that subnet SubnetID getID() const { return (id_); } /// @brief Returns subnet parameters (prefix and prefix length). /// /// @return (prefix, prefix length) pair std::pair get() const { return (std::make_pair(prefix_, prefix_len_)); } /// @brief Adds a new pool for the subnet. /// /// This method checks that the address range represented by the pool /// matches the subnet prefix, if the pool type is different than /// IA_PD. The prefixes from the IA_PD pools don't need to match the /// prefix from the subnet from which they are handed out to the /// requesting router because the requesting router may use the /// delegated prefixes in different networks (using different subnets). /// /// A DHCPv4 pool being added must not overlap with any existing DHCPv4 /// pool. A DHCPv6 pool being added must not overlap with any existing /// DHCPv6 pool. /// /// Pools held within a subnet are sorted by first pool address/prefix /// from the lowest to the highest. /// /// @param pool pool to be added /// /// @throw isc::BadValue if the pool type is invalid, in the case of address /// pools if the address range of the pool does not match the subnet prefix, /// or if the pool overlaps with an existing pool within the subnet. void addPool(const PoolPtr& pool); /// @brief Deletes all pools of specified type. /// /// This method is used for testing purposes only /// /// @param type type of pools to be deleted void delPools(Lease::Type type); /// @brief Returns a pool that specified address belongs to. /// /// This method uses binary search to retrieve the pool. Thus, the number /// of comparisons performed by this method is logarithmic in the number /// of pools belonging to a subnet. /// /// If there is no pool that the address belongs to (hint is invalid), other /// pool of specified type will be returned. /// /// With anypool set to true, this is means give me a pool, preferably /// the one that addr belongs to. With anypool set to false, it means /// give me a pool that addr belongs to (or NULL if here is no such pool) /// /// @param type pool type that the pool is looked for /// @param addr address that the returned pool should cover (optional) /// @param anypool other pool may be returned as well, not only the one /// that addr belongs to /// @return found pool (or NULL) const PoolPtr getPool(Lease::Type type, const isc::asiolink::IOAddress& addr, bool anypool = true) const; /// @brief Returns a pool that specified address belongs to with classes. /// /// Variant using only pools allowing given classes. /// /// @param type pool type that the pool is looked for /// @param client_classes client class list which must be allowed /// @param addr address that the returned pool should cover (optional) const PoolPtr getPool(Lease::Type type, const ClientClasses& client_classes, const isc::asiolink::IOAddress& addr) const; /// @brief Returns a pool without any address specified. /// /// @param type pool type that the pool is looked for /// @return returns one of the pools defined PoolPtr getAnyPool(Lease::Type type) { return (getPool(type, default_pool())); } /// @brief Returns the default address that will be used for pool selection. /// /// It must be implemented in derived classes (should return :: for Subnet6 /// and 0.0.0.0 for Subnet4). virtual isc::asiolink::IOAddress default_pool() const = 0; /// @brief Returns all pools (const variant). /// /// The reference is only valid as long as the object that returned it. /// /// @param type lease type to be set /// @return a collection of all pools const PoolCollection& getPools(Lease::Type type) const; /// @brief Returns the number of possible leases for specified lease type. /// /// @param type type of the lease uint64_t getPoolCapacity(Lease::Type type) const; /// @brief Returns the number of possible leases for specified lease type /// allowed for a client which belongs to classes. /// /// @param type type of the lease /// @param client_classes list of classes the client belongs to /// @return number of leases matching lease type and classes uint64_t getPoolCapacity(Lease::Type type, const ClientClasses& client_classes) const; /// @brief Returns textual representation of the subnet (e.g. /// "2001:db8::/64"). /// /// @return textual representation virtual std::string toText() const; /// @brief Resets subnet-id counter to its initial value (1). /// /// This should be called during reconfiguration, before any new /// subnet objects are created. It will ensure that the subnet_id will /// be consistent between reconfigures. static void resetSubnetID() { static_id_ = 1; } /// @brief Retrieves pointer to a shared network associated with a subnet. /// /// By implementing it as a template function we overcome a need to /// include shared_network.h header file to specify return type explicitly. /// The header can't be included because it would cause circular dependency /// between subnet.h and shared_network.h. /// /// This method uses an argument to hold a return value to allow the compiler /// to infer the return type without a need to call this function with an /// explicit return type as template argument. /// /// @param [out] shared_network Pointer to the shared network where returned /// value should be assigned. /// /// @tparam Type of the shared network, i.e. @ref SharedNetwork4 or a /// @ref SharedNetwork6. template void getSharedNetwork(SharedNetworkPtrType& shared_network) const { shared_network = boost::dynamic_pointer_cast< typename SharedNetworkPtrType::element_type>(parent_network_.lock()); } /// @brief Assigns shared network to a subnet. /// /// This method replaces any shared network associated with a subnet with /// a new shared network. /// /// @param shared_network Pointer to a new shared network to be associated /// with the subnet. void setSharedNetwork(const NetworkPtr& shared_network) { parent_network_ = shared_network; } /// @brief Returns shared network name. /// /// @return shared network name std::string getSharedNetworkName() const { return (shared_network_name_); } /// @brief Sets new shared network name. /// /// In certain cases the subnet must be associated with the shared network /// but the shared network object is not available. In particular, subnets /// are returned from the configuration database with only names of the /// shared networks. The actual shared networks must be fetched from the /// database using a separate query. In order to not loose associations /// of subnets with shared networks, the configuration backends will use /// this method to store the shared network names. The servers will later /// use those names to associate subnets with shared network instances. /// /// @param shared_network_name New shared network name. void setSharedNetworkName(const std::string& shared_network_name) { shared_network_name_ = shared_network_name; } /// @brief Returns all pools (non-const variant). /// /// The reference is only valid as long as the object that returned it. /// /// @param type lease type to be set /// @return a collection of all pools PoolCollection& getPoolsWritable(Lease::Type type); protected: /// @brief Protected constructor. // /// By making the constructor protected, we make sure that no one will /// ever instantiate that class. Subnet4 and Subnet6 should be used instead. /// /// This constructor assigns a new subnet-id (see @ref generateNextID). /// This subnet-id has unique value that is strictly monotonously increasing /// for each subnet, until it is explicitly reset back to 1 during /// reconfiguration process. /// /// @param prefix subnet prefix /// @param len prefix length for the subnet /// @param id arbitrary subnet id, value of 0 triggers autogeneration /// of subnet id Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, const SubnetID id); /// @brief virtual destructor. /// /// A virtual destructor is needed because other classes /// derive from this class. virtual ~Subnet() { }; /// @brief keeps the subnet-id value. /// /// It is incremented every time a new Subnet object is created. It is reset /// (@ref resetSubnetID) every time reconfiguration /// occurs. /// /// Static value initialized in subnet.cc. static SubnetID static_id_; /// @brief returns the next unique Subnet-ID. /// /// This method generates and returns the next unique subnet-id. /// It is a strictly monotonously increasing value (1,2,3,...) for /// each new Subnet object created. It can be explicitly reset /// back to 1 during reconfiguration (@ref resetSubnetID). /// /// @return the next unique Subnet-ID static SubnetID generateNextID() { if (static_id_ == SUBNET_ID_MAX) { resetSubnetID(); } return (static_id_++); } /// @brief Checks if used pool type is valid. /// /// Allowed type for Subnet4 is Pool::TYPE_V4. /// Allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}. /// This method is implemented in derived classes. /// /// @param type type to be checked /// @throw BadValue if invalid value is used virtual void checkType(Lease::Type type) const = 0; /// @brief Returns a sum of possible leases in all pools. /// /// @param pools list of pools /// @return sum of possible leases uint64_t sumPoolCapacity(const PoolCollection& pools) const; /// @brief Returns a sum of possible leases in all pools allowing classes. /// /// @param pools list of pools /// @param client_classes list of classes /// @return sum of possible/allowed leases uint64_t sumPoolCapacity(const PoolCollection& pools, const ClientClasses& client_classes) const; /// @brief Checks if the specified pool overlaps with an existing pool. /// /// @param pool_type Pool type. /// @param pool Pointer to a pool for which the method should check if /// it overlaps with any existing pool within this subnet. /// /// @return true if pool overlaps with an existing pool of a specified /// type, false otherwise bool poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const; /// @brief Unparse a subnet object. /// /// @return A pointer to unparsed subnet configuration. virtual data::ElementPtr toElement() const; /// @brief Converts subnet prefix to a pair of prefix/length pair. /// /// IPv4 and IPv6 specific conversion functions should apply extra checks /// on the returned values, i.e. whether length is in range and the IP /// address has a valid type. /// /// @param prefix Prefix to be parsed. /// @throw BadValue if provided prefix is not valid. static std::pair parsePrefixCommon(const std::string& prefix); /// @brief subnet-id /// /// Subnet-id is a unique value that can be used to find or identify /// a Subnet4 or Subnet6. SubnetID id_; /// @brief collection of IPv4 or non-temporary IPv6 pools in that subnet. PoolCollection pools_; /// @brief collection of IPv6 temporary address pools in that subnet. PoolCollection pools_ta_; /// @brief collection of IPv6 prefix pools in that subnet. PoolCollection pools_pd_; /// @brief a prefix of the subnet. isc::asiolink::IOAddress prefix_; /// @brief a prefix length of the subnet. uint8_t prefix_len_; /// @brief last allocated address. /// /// This is the last allocated address that was previously allocated from /// this particular subnet. Some allocation algorithms (e.g. iterative) use /// that value, others do not. It should be noted that although the value /// is usually correct, there are cases when it is invalid, e.g. after /// removing a pool, restarting or changing allocation algorithms. For /// that purpose it should be only considered a help that should not be /// fully trusted. isc::asiolink::IOAddress last_allocated_ia_; /// @brief last allocated temporary address. /// /// See @ref last_allocated_ia_ for details. isc::asiolink::IOAddress last_allocated_ta_; /// @brief last allocated IPv6 prefix. /// /// See @ref last_allocated_ia_ for details. isc::asiolink::IOAddress last_allocated_pd_; /// @brief Timestamp indicating when a lease of a specified type has been /// last allocated from this subnet. /// /// @note: This map is protected by the mutex. std::map last_allocated_time_; /// @brief Shared network name. std::string shared_network_name_; private: /// @brief returns the last address that was tried from this subnet. /// /// Should be called in a thread safe context. /// /// This method returns the last address that was attempted to be allocated /// from this subnet. This is used as helper information for the next /// iteration of the allocation algorithm. /// /// @todo: Define map somewhere in the /// AllocEngine::IterativeAllocator and keep the data there /// /// @param type lease type to be returned /// @return address/prefix that was last tried from this subnet isc::asiolink::IOAddress getLastAllocatedInternal(Lease::Type type) const; /// @brief Returns the timestamp when the @c setLastAllocated function /// was called. /// /// Should be called in a thread safe context. /// /// @param lease_type Lease type for which last allocation timestamp should /// be returned. /// /// @return Time when a lease of a specified type has been allocated from /// this subnet. The negative infinity time is returned if a lease type is /// not recognized (which is unlikely). boost::posix_time::ptime getLastAllocatedTimeInternal(const Lease::Type& lease_type) const; /// @brief sets the last address that was tried from this subnet. /// /// Should be called in a thread safe context. /// /// This method sets the last address that was attempted to be allocated /// from this subnet. This is used as helper information for the next /// iteration of the allocation algorithm. /// /// @note: this routine is Kea thread safe. /// /// @todo: Define map somewhere in the /// AllocEngine::IterativeAllocator and keep the data there /// @param addr address/prefix to that was tried last /// @param type lease type to be set void setLastAllocatedInternal(Lease::Type type, const isc::asiolink::IOAddress& addr); /// @brief Mutex to protect the internal state. boost::scoped_ptr mutex_; }; /// @brief A generic pointer to either Subnet4 or Subnet6 object typedef boost::shared_ptr SubnetPtr; class Subnet4; /// @brief A const pointer to a @c Subnet4 object. typedef boost::shared_ptr ConstSubnet4Ptr; /// @brief A pointer to a @c Subnet4 object. typedef boost::shared_ptr Subnet4Ptr; /// @brief A configuration holder for IPv4 subnet. /// /// This class represents an IPv4 subnet. /// @note Subnet and Network use virtual inheritance to avoid /// a diamond issue with UserContext class Subnet4 : public Subnet, public Network4 { public: /// @brief Constructor with all parameters. /// /// This constructor calls Subnet::Subnet, where subnet-id is generated. /// /// @param prefix Subnet4 prefix /// @param length prefix length /// @param t1 renewal timer (in seconds) /// @param t2 rebind timer (in seconds) /// @param valid_lifetime preferred lifetime of leases (in seconds) /// @param id arbitrary subnet id, default value of 0 triggers /// autogeneration of subnet id Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length, const util::Triplet& t1, const util::Triplet& t2, const util::Triplet& valid_lifetime, const SubnetID id = 0); /// @brief Factory function creating an instance of the @c Subnet4. /// /// This function should be used to create an instance of the subnet /// object within a hooks library in cases when the library may be /// unloaded before the object is destroyed. This ensures that the /// ownership of the object by the Kea process is retained. /// /// @param prefix Subnet4 prefix /// @param length prefix length /// @param t1 renewal timer (in seconds) /// @param t2 rebind timer (in seconds) /// @param valid_lifetime preferred lifetime of leases (in seconds) /// @param id arbitrary subnet id, default value of 0 triggers /// autogeneration of subnet id /// /// @return Pointer to the @c Subnet4 instance. static Subnet4Ptr create(const isc::asiolink::IOAddress& prefix, uint8_t length, const util::Triplet& t1, const util::Triplet& t2, const util::Triplet& valid_lifetime, const SubnetID id = 0); /// @brief Returns next subnet within shared network. /// /// If the current subnet doesn't belong to any shared network or if /// the next subnet is the same as first subnet (specified in the /// argument) a NULL pointer is returned. /// /// @param first_subnet Pointer to the subnet from which iterations have /// started. /// /// @return Pointer to the next subnet or NULL pointer if the next subnet /// is the first subnet or if the current subnet doesn't belong to a /// shared network. Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet) const; /// @brief Returns next subnet within shared network that matches /// client classes. /// /// @param first_subnet Pointer to the subnet from which iterations have /// started. /// @param client_classes List of classes that the client belongs to. /// The subnets not matching the classes aren't returned by this /// method. /// /// @return Pointer to the next subnet or NULL pointer if the next subnet /// is the first subnet or if the current subnet doesn't belong to a /// shared network. Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet, const ClientClasses& client_classes) const; /// @brief Checks whether this subnet and parent shared network supports /// the client that belongs to specified classes. /// /// This method extends the @ref Network::clientSupported method with /// additional checks whether shared network owning this class supports /// the client belonging to specified classes. If the class doesn't /// belong to a shared network this method only checks if the subnet /// supports specified classes. /// /// @param client_classes List of classes the client belongs to. /// @return true if client can be supported, false otherwise. virtual bool clientSupported(const isc::dhcp::ClientClasses& client_classes) const; /// @brief Returns DHCP4o6 configuration parameters. /// /// This structure is always available. If the 4o6 is not enabled, its /// enabled_ field will be set to false. Cfg4o6& get4o6() { return (dhcp4o6_); } /// @brief Returns const DHCP4o6 configuration parameters. /// /// This structure is always available. If the 4o6 is not enabled, its /// enabled_ field will be set to false. const Cfg4o6& get4o6() const { return (dhcp4o6_); } /// @brief Unparse a subnet object. /// /// @return A pointer to unparsed subnet configuration. virtual data::ElementPtr toElement() const; /// @brief Converts subnet prefix to a pair of prefix/length pair. /// /// @param prefix Prefix to be parsed. /// @throw BadValue if provided invalid IPv4 prefix. static std::pair parsePrefix(const std::string& prefix); private: /// @brief Returns default address for pool selection. /// /// @return ANY IPv4 address virtual isc::asiolink::IOAddress default_pool() const { return (isc::asiolink::IOAddress("0.0.0.0")); } /// @brief Checks if used pool type is valid. /// /// Allowed type for Subnet4 is Pool::TYPE_V4. /// /// @param type type to be checked /// @throw BadValue if invalid value is used virtual void checkType(Lease::Type type) const; /// @brief All the information related to DHCP4o6 Cfg4o6 dhcp4o6_; }; class Subnet6; /// @brief A const pointer to a @c Subnet6 object. typedef boost::shared_ptr ConstSubnet6Ptr; /// @brief A pointer to a Subnet6 object typedef boost::shared_ptr Subnet6Ptr; /// @brief A configuration holder for IPv6 subnet. /// /// This class represents an IPv6 subnet. /// @note Subnet and Network use virtual inheritance to avoid /// a diamond issue with UserContext class Subnet6 : public Subnet, public Network6 { public: /// @brief Constructor with all parameters. /// /// This constructor calls Subnet::Subnet, where subnet-id is generated. /// /// @param prefix Subnet6 prefix /// @param length prefix length /// @param t1 renewal timer (in seconds) /// @param t2 rebind timer (in seconds) /// @param preferred_lifetime preferred lifetime of leases (in seconds) /// @param valid_lifetime preferred lifetime of leases (in seconds) /// @param id arbitrary subnet id, default value of 0 triggers /// autogeneration of subnet id Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length, const util::Triplet& t1, const util::Triplet& t2, const util::Triplet& preferred_lifetime, const util::Triplet& valid_lifetime, const SubnetID id = 0); /// @brief Factory function creating an instance of the @c Subnet4. /// /// This function should be used to create an instance of the subnet /// object within a hooks library in cases when the library may be /// unloaded before the object is destroyed. This ensures that the /// ownership of the object by the Kea process is retained. /// /// @param prefix Subnet6 prefix /// @param length prefix length /// @param t1 renewal timer (in seconds) /// @param t2 rebind timer (in seconds) /// @param preferred_lifetime preferred lifetime of leases (in seconds) /// @param valid_lifetime preferred lifetime of leases (in seconds) /// @param id arbitrary subnet id, default value of 0 triggers /// autogeneration of subnet id /// /// @return Pointer to the @c Subnet6 instance. static Subnet6Ptr create(const isc::asiolink::IOAddress& prefix, uint8_t length, const util::Triplet& t1, const util::Triplet& t2, const util::Triplet& preferred_lifetime, const util::Triplet& valid_lifetime, const SubnetID id = 0); /// @brief Returns next subnet within shared network. /// /// If the current subnet doesn't belong to any shared network or if /// the next subnet is the same as first subnet (specified in the /// arguments) a NULL pointer is returned. /// /// @param first_subnet Pointer to the subnet from which iterations have /// started. /// /// @return Pointer to the next subnet or NULL pointer if the next subnet /// is the first subnet or if the current subnet doesn't belong to a /// shared network. Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet) const; /// @brief Returns next subnet within shared network that matches /// client classes. /// /// @param first_subnet Pointer to the subnet from which iterations have /// started. /// @param client_classes List of classes that the client belongs to. /// The subnets not matching the classes aren't returned by this /// method. /// /// @return Pointer to the next subnet or NULL pointer if the next subnet /// is the first subnet or if the current subnet doesn't belong to a /// shared network. Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet, const ClientClasses& client_classes) const; /// @brief Checks whether this subnet and parent shared network supports /// the client that belongs to specified classes. /// /// This method extends the @ref Network::clientSupported method with /// additional checks whether shared network owning this class supports /// the client belonging to specified classes. If the class doesn't /// belong to a shared network this method only checks if the subnet /// supports specified classes. /// /// @param client_classes List of classes the client belongs to. /// @return true if client can be supported, false otherwise. virtual bool clientSupported(const isc::dhcp::ClientClasses& client_classes) const; /// @brief Unparse a subnet object. /// /// @return A pointer to unparsed subnet configuration. virtual data::ElementPtr toElement() const; /// @brief Converts subnet prefix to a pair of prefix/length pair. /// /// @param prefix Prefix to be parsed. /// @throw BadValue if provided invalid IPv4 prefix. static std::pair parsePrefix(const std::string& prefix); private: /// @brief Returns default address for pool selection /// @return ANY IPv6 address virtual isc::asiolink::IOAddress default_pool() const { return (isc::asiolink::IOAddress("::")); } /// @brief Checks if used pool type is valid /// /// allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}. /// /// @param type type to be checked /// @throw BadValue if invalid value is used virtual void checkType(Lease::Type type) const; }; /// @name Definition of the multi index container holding subnet information /// //@{ /// @brief Tag for the index for searching by subnet identifier. struct SubnetSubnetIdIndexTag { }; /// @brief Tag for the index for searching by subnet prefix. struct SubnetPrefixIndexTag { }; /// @brief Tag for the index for searching by server identifier. struct SubnetServerIdIndexTag { }; /// @brief Tag for the index for searching by subnet modification time. struct SubnetModificationTimeIndexTag { }; /// @brief A simple collection of @c Subnet4 objects /// /// This container provides a set of indexes which can be used to retrieve /// subnets by subnet identifier and subnet prefix. /// /// The random access index is used for direct iteration over the collection. typedef boost::multi_index_container< // Multi index container holds pointers to the subnets. Subnet4Ptr, // The following holds all indexes. boost::multi_index::indexed_by< // First index allows for searching using subnet identifier. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Second index allows for searching using an output from toText function. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun > > > Subnet4SimpleCollection; /// @brief A collection of @c Subnet4 objects. /// /// This container provides a set of indexes which can be used to retrieve /// subnets by various properties. /// /// This multi index container can hold pointers to @ref Subnet4 /// objects representing subnets. It provides indexes for subnet lookups /// using subnet properties such as: subnet identifier, /// subnet prefix or server identifier specified for a subnet. It also /// provides a random access index which allows for using the container /// like a vector. /// /// The random access index is used by the DHCP servers which perform /// a full scan on subnets to find the one that matches some specific /// criteria for subnet selection. /// /// The remaining indexes are used for searching for a specific subnet /// as a result of receiving a command over the control API, e.g. /// when 'subnet-get' command is received. /// /// @todo We should consider optimizing subnet selection by leveraging /// the indexing capabilities of this container, e.g. searching for /// a subnet by interface name, relay address etc. typedef boost::multi_index_container< // Multi index container holds pointers to the subnets. Subnet4Ptr, // The following holds all indexes. boost::multi_index::indexed_by< // First index allows for searching using subnet identifier. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Second index allows for searching using an output from toText function. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Third index allows for searching using an output from getServerId. boost::multi_index::ordered_non_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Forth index allows for searching using subnet modification time. boost::multi_index::ordered_non_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun > > > Subnet4Collection; /// @brief A simple collection of @c Subnet6 objects /// /// This container provides a set of indexes which can be used to retrieve /// subnets by subnet identifier and subnet prefix. /// /// The random access index is used for direct iteration over the collection. typedef boost::multi_index_container< // Multi index container holds pointers to the subnets. Subnet6Ptr, // The following holds all indexes. boost::multi_index::indexed_by< // First index allows for searching using subnet identifier. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Second index allows for searching using an output from toText function. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun > > > Subnet6SimpleCollection; /// @brief A collection of @c Subnet6 objects /// /// This container provides a set of indexes which can be used to retrieve /// subnets by various properties. /// /// This multi index container can hold pointers to @ref Subnet6 objects /// representing subnets. It provides indexes for subnet lookups using /// subnet properties such as: subnet identifier or subnet prefix. It /// also provides a random access index which allows for using the /// container like a vector. /// /// The random access index is used by the DHCP servers which perform /// a full scan on subnets to find the one that matches some specific /// criteria for subnet selection. /// /// The remaining indexes are used for searching for a specific subnet /// as a result of receiving a command over the control API, e.g. /// when 'subnet-get' command is received. /// /// @todo We should consider optimizing subnet selection by leveraging /// the indexing capabilities of this container, e.g. searching for /// a subnet by interface name, relay address etc. typedef boost::multi_index_container< // Multi index container holds pointers to the subnets. Subnet6Ptr, // The following holds all indexes. boost::multi_index::indexed_by< // First index allows for searching using subnet identifier. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Second index allows for searching using an output from toText function. boost::multi_index::ordered_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun >, // Third index allows for searching using subnet modification time. boost::multi_index::ordered_non_unique< boost::multi_index::tag, boost::multi_index::const_mem_fun > > > Subnet6Collection; /// @brief A class containing static convenience methods to fetch the subnets /// from the containers. /// /// @tparam ReturnPtrType Type of the returned object, i.e. @c Subnet4Ptr /// or @c Subnet6Ptr. /// @tparam CollectionType One of the @c Subnet4SimpleCollection, /// @c Subnet4Collection, @c Subnet6SimpleCollection or @c Subnet6Collection. template class SubnetFetcher { public: /// @brief Fetches subnets by id. /// /// @param collection Const reference to the collection from which the /// subnet is to be fetched. /// @param subnet_id Id of the subnet to be fetched. /// @return Pointer to the fetched subnet or null if no such subnet /// could be found. static ReturnPtrType get(const CollectionType& collection, const SubnetID& subnet_id) { auto& index = collection.template get(); auto s = index.find(subnet_id); if (s != index.end()) { return (*s); } // No subnet found. Return null pointer. return (ReturnPtrType()); } }; /// @brief Type of the @c SubnetFetcher used for IPv4. using SubnetFetcher4 = SubnetFetcher; /// @brief Type of the @c SubnetFetcher used for IPv6. using SubnetFetcher6 = SubnetFetcher; //@} /// @brief adapters for linking templates to qualified names /// @{ namespace { template struct AdapterSubnet {}; template <> struct AdapterSubnet { using type = Subnet4; }; template <> struct AdapterSubnet { using type = Subnet6; }; } // namespace template using SubnetT = typename AdapterSubnet::type; template using SubnetTPtr = boost::shared_ptr>; /// @} } // end of isc::dhcp namespace } // end of isc namespace #endif // SUBNET_H