diff options
author | Marcin Siodelski <marcin@isc.org> | 2014-10-23 21:34:53 +0200 |
---|---|---|
committer | Marcin Siodelski <marcin@isc.org> | 2014-10-23 21:34:53 +0200 |
commit | 1b6096afc89fad84e92228e504d2e1fae19384dd (patch) | |
tree | 9bd9f52f86bbf07be979dbe51900a5b03c40745b /src/lib/dhcpsrv/cfg_hosts.cc | |
parent | update commit hash (diff) | |
download | kea-1b6096afc89fad84e92228e504d2e1fae19384dd.tar.xz kea-1b6096afc89fad84e92228e504d2e1fae19384dd.zip |
[3562] Implemented storage class for Hosts.
Diffstat (limited to 'src/lib/dhcpsrv/cfg_hosts.cc')
-rw-r--r-- | src/lib/dhcpsrv/cfg_hosts.cc | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/cfg_hosts.cc b/src/lib/dhcpsrv/cfg_hosts.cc new file mode 100644 index 0000000000..68fb00bd4e --- /dev/null +++ b/src/lib/dhcpsrv/cfg_hosts.cc @@ -0,0 +1,190 @@ +// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include <dhcpsrv/cfg_hosts.h> +#include <exceptions/exceptions.h> + +using namespace isc::asiolink; + +namespace isc { +namespace dhcp { + +ConstHostCollection +CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) const { + ConstHostCollection collection; + getAllInternal<ConstHostCollection>(hwaddr, duid, collection); + return (collection); +} + +HostCollection +CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) { + HostCollection collection; + getAllInternal<HostCollection>(hwaddr, duid, collection); + return (collection); +} + +ConstHostCollection +CfgHosts::getAll4(const IOAddress&) const { + isc_throw(isc::NotImplemented, "getAll4(address) const is not implemented"); +} + +HostCollection +CfgHosts::getAll4(const IOAddress&) { + isc_throw(isc::NotImplemented, "getAll4(address) is not implemented"); +} + +template<typename Storage> +void +CfgHosts::getAllInternal(const std::vector<uint8_t>& identifier, + const Host::IdentifierType& identifier_type, + Storage& storage) const { + // Search for the Host using the identifier and identifier type as a + // composite key. + const HostContainerIndex0& idx = hosts_.get<0>(); + std::pair<HostContainerIndex0::iterator, HostContainerIndex0::iterator> r = + idx.equal_range(boost::make_tuple(identifier, identifier_type)); + // Append each Host object to the storage. + for (HostContainerIndex0::iterator host = r.first; host != r.second; + ++host) { + storage.push_back(*host); + } +} + +template<typename Storage> +void +CfgHosts::getAllInternal(const HWAddrPtr& hwaddr, const DuidPtr& duid, + Storage& storage) const { + // Get hosts using HW address. + if (hwaddr) { + getAllInternal<Storage>(hwaddr->hwaddr_, Host::IDENT_HWADDR, storage); + } + // Get hosts using DUID. + if (duid) { + getAllInternal<Storage>(duid->getDuid(), Host::IDENT_DUID, storage); + } +} + +ConstHostPtr +CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, + const DuidPtr& duid) const { + // The false value indicates that it is an IPv4 subnet. + return (getHostInternal(subnet_id, false, hwaddr, duid)); +} + +HostPtr +CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, + const DuidPtr& duid) { + // The false value indicates that it is an IPv4 subnet. + return (getHostInternal(subnet_id, false, hwaddr, duid)); +} + +ConstHostPtr +CfgHosts::get6(const SubnetID& subnet_id, const DuidPtr& duid, + const HWAddrPtr& hwaddr) const { + // The true value indicates that it is an IPv6 subnet. + return (getHostInternal(subnet_id, true, hwaddr, duid)); +} + +HostPtr +CfgHosts::get6(const SubnetID& subnet_id, const DuidPtr& duid, + const HWAddrPtr& hwaddr) { + // The true value indicates that it is an IPv6 subnet. + return (getHostInternal(subnet_id, true, hwaddr, duid)); +} + +ConstHostPtr +CfgHosts::get6(const IOAddress&, const uint8_t) const { + isc_throw(isc::NotImplemented, + "get6(prefix, len) const is not implemented"); +} + +HostPtr +CfgHosts::get6(const IOAddress&, const uint8_t) { + isc_throw(isc::NotImplemented, "get6(prefix, len) is not implemented"); +} + +HostPtr +CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6, + const HWAddrPtr& hwaddr, const DuidPtr& duid) const { + // Get all hosts for the HW address and DUID. This may return multiple hosts + // for different subnets, but the number of hosts returned should be low + // because one host presumably doesn't show up in many subnets. + HostCollection hosts; + getAllInternal<HostCollection>(hwaddr, duid, hosts); + + HostPtr host; + // Iterate over the returned hosts and select those for which the + // subnet id matches. + for (HostCollection::const_iterator host_it = hosts.begin(); + host_it != hosts.end(); ++host_it) { + // Check if this is IPv4 subnet or IPv6 subnet. + SubnetID host_subnet_id = subnet6 ? (*host_it)->getIPv6SubnetID() : + (*host_it)->getIPv4SubnetID(); + + if (subnet_id == host_subnet_id) { + // If this is the first occurrence of the host for this subnet, + // remember it. But, if we find that this is second @c Host object + // for the same client, it is a misconfiguration. Most likely, + // the administrator has specified one reservation for a HW + // address and another one for the DUID, which gives an ambiguous + // result, and we don't know which reservation we should choose. + // Therefore, throw an exception. + if (!host) { + host = *host_it; + + } else { + isc_throw(DuplicateHost, "more than one reservation found" + " for the host belonging to the subnet with id '" + << subnet_id << "' and using the HW address '" + << (hwaddr ? hwaddr->toText(false) : "(null)") + << "' and DUID '" + << (duid ? duid->toText() : "(null)") + << "'"); + } + } + } + return (host); +} + + +void +CfgHosts::add(const HostPtr& host) { + /// @todo This may need to be sanity-checked. For example, a duplicate + /// should be rejected. + HWAddrPtr hwaddr = host->getHWAddress(); + DuidPtr duid = host->getDuid(); + // Check for duplicates for the specified IPv4 subnet. + if (get4(host->getIPv4SubnetID(), host->getHWAddress(), host->getDuid())) { + isc_throw(DuplicateHost, "failed to add new host using the HW" + " address '" << (hwaddr ? hwaddr->toText(false) : "(null)") + << " and DUID '" << (duid ? duid->toText() : "(null)") + << "' to the IPv4 subnet id '" << host->getIPv4SubnetID() + << "' as this host has already been added"); + + // Checek for duplicates for the specified IPv6 subnet. + } else if (get6(host->getIPv6SubnetID(), host->getDuid(), + host->getHWAddress())) { + isc_throw(DuplicateHost, "failed to add new host using the HW" + " address '" << (hwaddr ? hwaddr->toText(false) : "(null)") + << " and DUID '" << (duid ? duid->toText() : "(null)") + << "' to the IPv6 subnet id '" << host->getIPv6SubnetID() + << "' as this host has already been added"); + } + + // This is a new instance - add it. + hosts_.insert(host); +} + +} // end of namespace isc::dhcp +} // end of namespace isc |