return (collection);
}
+ConstHostCollection
+CfgHosts::getAll6(const IOAddress& address) const {
+ ConstHostCollection collection;
+ getAllInternal6<ConstHostCollection>(address, collection);
+ return (collection);
+}
+
+HostCollection
+CfgHosts::getAll6(const IOAddress& address) {
+ HostCollection collection;
+ getAllInternal6<HostCollection>(address, collection);
+ return (collection);
+}
+
template<typename Storage>
void
CfgHosts::getAllInternal(const std::vector<uint8_t>& identifier,
}
}
+template<typename Storage>
+void
+CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
+ // Must not specify address other than IPv6.
+ if (!address.isV6()) {
+ isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
+ " for a host, specified address was " << address);
+ }
+ // Search for the Host using the reserved IPv4 address as a key.
+ const HostContainerIndex1& idx = hosts_.get<1>();
+ HostContainerIndex1Range r = idx.equal_range(address);
+ // Append each Host object to the storage.
+ for (HostContainerIndex1::iterator host = r.first; host != r.second;
+ ++host) {
+ storage.push_back(*host);
+ }
+}
+
ConstHostPtr
CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
isc_throw(isc::NotImplemented, "get6(prefix, len) is not implemented");
}
+ConstHostPtr
+CfgHosts::get6(const SubnetID& subnet_id, const IOAddress& address) const {
+ ConstHostCollection hosts = getAll6(address);
+ for (ConstHostCollection::const_iterator host = hosts.begin();
+ host != hosts.end(); ++host) {
+ if ((*host)->getIPv4SubnetID() == subnet_id) {
+ return (*host);
+ }
+ }
+ return (ConstHostPtr());
+}
+
+
HostPtr
CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
isc_throw(BadValue, "must not use both IPv4 and IPv6 subnet ids of"
" 0 when adding new host reservation");
}
+
+ if (host->getIPv4SubnetID() != 0) {
+ add4(host);
+ }
+
+ if (host->getIPv6SubnetID() != 0) {
+ add6(host);
+ }
+}
+
+void
+CfgHosts::add4(const HostPtr& host) {
+
/// @todo This may need further sanity checks.
HWAddrPtr hwaddr = host->getHWAddress();
DuidPtr duid = host->getDuid();
<< "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
<< "' as this host has already been added");
+ }
+ /// @todo This may need further sanity checks.
+
+ // This is a new instance - add it.
+ hosts_.insert(host);
+}
+
+void
+CfgHosts::add6(const HostPtr& host) {
+
+ /// @todo This may need further sanity checks.
+ HWAddrPtr hwaddr = host->getHWAddress();
+ DuidPtr duid = host->getDuid();
+
// Check for duplicates for the specified IPv6 subnet.
- } else if (host->getIPv6SubnetID() &&
+ if (host->getIPv6SubnetID() &&
get6(host->getIPv6SubnetID(), duid, hwaddr)) {
isc_throw(DuplicateHost, "failed to add new host using the HW"
" address '" << (hwaddr ? hwaddr->toText(false) : "(null)")
<< "' as this host has already been added");
}
- /// @todo This may need further sanity checks.
+ // Now insert it into hosts_, which will be used for finding hosts
+ // based on their HW or DUID addresses. It cannot be used for
+ // finding IPv6 hosts by their IPv6 addresses, as there may be multiple
+ // addresses for a given host. However, insert only if this
+ // host doesn't have v4 subnet-id. If it does, it was just added
+ // by the previous call to add4().
+ if (! host->getIPv4SubnetID()) {
+ hosts_.insert(host);
+ }
- // This is a new instance - add it.
- hosts_.insert(host);
+ // Get all reservations for this host.
+ IPv6ResrvRange reservations = host->getIPv6Reservations();
+
+ if (std::distance(reservations.first, reservations.second) == 0) {
+
+ /// @todo: We don't handle address-less reservations yet
+ return;
+ }
+
+ for (IPv6ResrvIterator it = reservations.first; it != reservations.second;
+ ++it) {
+ hosts6_.insert(HostResrv6Tuple(it->second, host));
+ }
}
} // end of namespace isc::dhcp
virtual HostCollection
getAll4(const asiolink::IOAddress& address);
+ /// @brief Returns a collection of hosts using the specified IPv6 address.
+ ///
+ /// This method may return multiple @c Host objects if they are connected
+ /// to different subnets.
+ ///
+ /// @param address IPv6 address for which the @c Host object is searched.
+ ///
+ /// @return Collection of const @c Host objects.
+ virtual ConstHostCollection
+ getAll6(const asiolink::IOAddress& address) const;
+
+ /// @brief Returns a collection of hosts using the specified IPv6 address.
+ ///
+ /// This method may return multiple @c Host objects if they are connected
+ /// to different subnets.
+ ///
+ /// @param address IPv6 address for which the @c Host object is searched.
+ ///
+ /// @return Collection of const @c Host objects.
+ virtual HostCollection
+ getAll6(const asiolink::IOAddress& address);
+
/// @brief Returns a host connected to the IPv4 subnet and matching
/// specified identifiers.
///
virtual HostPtr
get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len);
+ /// @brief Returns a host connected to the IPv6 subnet and having
+ /// a reservation for a specified IPv6 address.
+ ///
+ /// @param subnet_id Subnet identifier.
+ /// @param address reserved IPv6 address.
+ ///
+ /// @return Const @c Host object using a specified IPv6 address.
+ virtual ConstHostPtr
+ get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
+
+ /// @brief Returns a host connected to the IPv6 subnet and having
+ /// a reservation for a specified IPv6 address.
+ ///
+ /// @param subnet_id Subnet identifier.
+ /// @param address reserved IPv6 address.
+ ///
+ /// @return Const @c Host object using a specified IPv6 address.
+ virtual HostPtr
+ get6(const SubnetID& subnet_id, const asiolink::IOAddress& address);
/// @brief Adds a new host to the collection.
///
void getAllInternal4(const asiolink::IOAddress& address,
Storage& storage) const;
+ /// @brief Returns @c Host objects for the specified IPv6 address.
+ ///
+ /// This private method is called by the @c CfgHosts::getAll6 methods
+ /// to retrieve the @c Host for which the specified IPv6 address is
+ /// reserved. The retrieved objects are appended to the @c storage
+ /// container.
+ ///
+ /// @param address IPv6 address.
+ /// @param [out] storage Container to which the retrieved objects are
+ /// appended.
+ /// @tparam One of the @c ConstHostCollection or @c HostCollection.
+ template<typename Storage>
+ void getAllInternal6(const asiolink::IOAddress& address,
+ Storage& storage) const;
+
/// @brief Returns @c Host object connected to a subnet.
///
/// This private method returns a pointer to the @c Host object identified
const HWAddrPtr& hwaddr,
const DuidPtr& duid) const;
+
+
+ /// @brief Adds a new host to the v4 collection.
+ ///
+ /// This is an internal method called by public @ref add.
+ ///
+ /// @param host Pointer to the new @c Host object being added.
+ ///
+ /// @throw DuplicateHost If a host for a particular HW address or DUID
+ /// has already been added to the IPv4 subnet.
+ virtual void add4(const HostPtr& host);
+
+ /// @brief Adds a new host to the v6 collection.
+ ///
+ /// This is an internal method called by public @ref add.
+ ///
+ /// @param host Pointer to the new @c Host object being added.
+ ///
+ /// @throw DuplicateHost If a host for a particular HW address or DUID
+ /// or for the particular address or prefix has already been added to
+ /// the IPv6 subnet.
+ virtual void add6(const HostPtr& host);
+
/// @brief Multi-index container holding @c Host objects.
+ ///
+ /// It can be used for finding hosts by the following criteria:
+ /// - IPv4 address
+ /// - DUID
+ /// - HW/MAC address
HostContainer hosts_;
+ /// @brief Multi-index container holding @c Host objects with v6 reservations.
+ ///
+ /// It can be used for finding hosts by the following criteria:
+ /// - IPv6 address
+ /// - IPv6 prefix
+ HostContainer6 hosts6_;
};
/// @name Pointers to the @c CfgHosts objects.
return (ipv6_reservations_.equal_range(type));
}
+IPv6ResrvRange
+Host::getIPv6Reservations() const {
+ return (IPv6ResrvRange(ipv6_reservations_.begin(),
+ ipv6_reservations_.end()));
+}
+
bool
Host::hasIPv6Reservation() const {
return (!ipv6_reservations_.empty());
/// the specified type.
IPv6ResrvRange getIPv6Reservations(const IPv6Resrv::Type& type) const;
+ /// @brief Returns all IPv6 reservations.
+ ///
+ /// @return A range of iterators pointing to the reservations of
+ /// the specified type.
+ IPv6ResrvRange getIPv6Reservations() const;
+
/// @brief Checks if there is at least one IPv6 reservation for this host.
///
/// @return true if there is a reservation for the host, false otherwise.
#define HOST_CONTAINER_H
#include <dhcpsrv/host.h>
+#include <dhcpsrv/subnet_id.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
namespace isc {
typedef std::pair<HostContainerIndex1::iterator,
HostContainerIndex1::iterator> HostContainerIndex1Range;
+/// @brief Defines one entry for the Host Container for v6 hosts
+///
+/// It's essentially a pair of (IPv6 reservation, Host pointer).
+struct HostResrv6Tuple {
+
+ /// @brief Default constructor
+ HostResrv6Tuple(const IPv6Resrv& resrv, const ConstHostPtr& host)
+ :resrv_(resrv), host_(host), subnet_id_(host? host->getIPv6SubnetID() : 0) {
+ }
+
+ const IPv6Resrv resrv_;
+ ConstHostPtr host_;
+ const SubnetID subnet_id_;
+
+ const asiolink::IOAddress& getKey() const {
+ return (resrv_.getPrefix());
+ }
+};
+
+/// @brief Multi-index container holding IPv6 reservations.
+///
+/// This container holds HostResrv6Tuples, i.e. pairs of (IPv6Resrv, HostPtr)
+/// pieces of information. This is needed for efficiently finding a host
+/// for a given IPv6 address or prefix.
+typedef boost::multi_index_container<
+
+ /// This containers stores (IPv6Resrv, HostPtr) tuples
+ HostResrv6Tuple,
+
+ /// Start specification of indexes here.
+ boost::multi_index::indexed_by<
+
+ /// First index is used to search by an address.
+ boost::multi_index::ordered_non_unique<
+
+ /// Address is extracted by calling IPv6Resrv::getPrefix()
+ /// and it will return an IOAddress object.
+ boost::multi_index::const_mem_fun<
+ HostResrv6Tuple, const asiolink::IOAddress&,
+ &HostResrv6Tuple::getKey
+ >
+ >,
+
+ /// Second index is used to search by (subnet_id, address) pair
+ /// @todo: Let's make the first index working first.
+ boost::multi_index::ordered_non_unique<
+
+ boost::multi_index::composite_key<
+ HostResrv6Tuple,
+
+ boost::multi_index::member<
+ HostResrv6Tuple, const SubnetID,
+ &HostResrv6Tuple::subnet_id_
+ >,
+
+ /// Address is extracted by calling IPv6Resrv::getPrefix()
+ /// and it will return an IOAddress object.
+ boost::multi_index::const_mem_fun<
+ HostResrv6Tuple, const asiolink::IOAddress&,
+ &HostResrv6Tuple::getKey
+ >
+ >
+ >
+
+> HostContainer6;
+
+
}
}
return (host);
}
+ConstHostPtr
+HostMgr::get6(const SubnetID& subnet_id,
+ const asiolink::IOAddress& addr) const {
+ ConstHostPtr host = getCfgHosts()->get6(subnet_id, addr);
+ if (!host && alternate_source) {
+ host = alternate_source->get6(subnet_id, addr);
+ }
+ return (host);
+}
+
+
void
HostMgr::add(const HostPtr&) {
isc_throw(isc::NotImplemented, "HostMgr::add is not implemented");
virtual ConstHostPtr
get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
+ /// @brief Returns a host from specific subnet and reserved address.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ ///
+ /// @return Const @c host object that has a reservation for specified address.
+ virtual ConstHostPtr
+ get6(const SubnetID& subnet_id, const asiolink::IOAddress& addr) const;
+
/// @brief Adds a new host to the alternate data source.
///
/// This method will throw an exception if no alternate data source is