|
@@ -13,6 +13,7 @@
|
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
#include <dhcpsrv/cfg_hosts.h>
|
|
|
+#include <dhcpsrv/hosts_log.h>
|
|
|
#include <exceptions/exceptions.h>
|
|
|
#include <ostream>
|
|
|
|
|
@@ -23,6 +24,8 @@ namespace dhcp {
|
|
|
|
|
|
ConstHostCollection
|
|
|
CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
|
|
|
+ // Do not issue logging message here because it will be logged by
|
|
|
+ // the getAllInternal method.
|
|
|
ConstHostCollection collection;
|
|
|
getAllInternal<ConstHostCollection>(hwaddr, duid, collection);
|
|
|
return (collection);
|
|
@@ -30,6 +33,8 @@ CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
|
|
|
|
|
|
HostCollection
|
|
|
CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) {
|
|
|
+ // Do not issue logging message here because it will be logged by
|
|
|
+ // the getAllInternal method.
|
|
|
HostCollection collection;
|
|
|
getAllInternal<HostCollection>(hwaddr, duid, collection);
|
|
|
return (collection);
|
|
@@ -37,6 +42,8 @@ CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) {
|
|
|
|
|
|
ConstHostCollection
|
|
|
CfgHosts::getAll4(const IOAddress& address) const {
|
|
|
+ // Do not issue logging message here because it will be logged by
|
|
|
+ // the getAllInternal4 method.
|
|
|
ConstHostCollection collection;
|
|
|
getAllInternal4<ConstHostCollection>(address, collection);
|
|
|
return (collection);
|
|
@@ -44,6 +51,8 @@ CfgHosts::getAll4(const IOAddress& address) const {
|
|
|
|
|
|
HostCollection
|
|
|
CfgHosts::getAll4(const IOAddress& address) {
|
|
|
+ // Do not issue logging message here because it will be logged by
|
|
|
+ // the getAllInternal4 method.
|
|
|
HostCollection collection;
|
|
|
getAllInternal4<HostCollection>(address, collection);
|
|
|
return (collection);
|
|
@@ -51,6 +60,8 @@ CfgHosts::getAll4(const IOAddress& address) {
|
|
|
|
|
|
ConstHostCollection
|
|
|
CfgHosts::getAll6(const IOAddress& address) const {
|
|
|
+ // Do not issue logging message here because it will be logged by
|
|
|
+ // the getAllInternal6 method.
|
|
|
ConstHostCollection collection;
|
|
|
getAllInternal6<ConstHostCollection>(address, collection);
|
|
|
return (collection);
|
|
@@ -58,6 +69,8 @@ CfgHosts::getAll6(const IOAddress& address) const {
|
|
|
|
|
|
HostCollection
|
|
|
CfgHosts::getAll6(const IOAddress& address) {
|
|
|
+ // Do not issue logging message here because it will be logged by
|
|
|
+ // the getAllInternal6 method.
|
|
|
HostCollection collection;
|
|
|
getAllInternal6<HostCollection>(address, collection);
|
|
|
return (collection);
|
|
@@ -68,6 +81,35 @@ void
|
|
|
CfgHosts::getAllInternal(const std::vector<uint8_t>& identifier,
|
|
|
const Host::IdentifierType& identifier_type,
|
|
|
Storage& storage) const {
|
|
|
+ // We will need to transform the identifier into the textual format.
|
|
|
+ // Until we do it, we mark it as invalid.
|
|
|
+ std::string identifier_text = "(invalid)";
|
|
|
+ if (!identifier.empty()) {
|
|
|
+ try {
|
|
|
+ // Use Host object to find the textual form of the identifier.
|
|
|
+ // This may throw exception if the identifier is invalid.
|
|
|
+ Host host(&identifier[0], identifier.size(), identifier_type,
|
|
|
+ SubnetID(0), SubnetID(0), IOAddress::IPV4_ZERO_ADDRESS());
|
|
|
+ identifier_text = host.getIdentifierAsText();
|
|
|
+
|
|
|
+ } catch (...) {
|
|
|
+ // Suppress exception and keep using (invalid) as an
|
|
|
+ // identifier. We will log that the identifier is
|
|
|
+ // invalid and return.
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // This will log that we're invoking this function with the specified
|
|
|
+ // identifier. The identifier may also be marked as (invalid) if it
|
|
|
+ // had 0 length or its type is unsupported.
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_IDENTIFIER)
|
|
|
+ .arg(identifier_text);
|
|
|
+
|
|
|
+ // Do nothing if the identifier specified is invalid.
|
|
|
+ if (identifier_text == "(invalid)") {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// Use the identifier and identifier type as a composite key.
|
|
|
const HostContainerIndex0& idx = hosts_.get<0>();
|
|
|
boost::tuple<const std::vector<uint8_t>, const Host::IdentifierType> t =
|
|
@@ -76,14 +118,27 @@ CfgHosts::getAllInternal(const std::vector<uint8_t>& identifier,
|
|
|
// Append each Host object to the storage.
|
|
|
for (HostContainerIndex0::iterator host = idx.lower_bound(t); host != idx.upper_bound(t);
|
|
|
++host) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
|
|
|
+ HOSTS_CFG_GET_ALL_IDENTIFIER_HOST)
|
|
|
+ .arg(identifier_text)
|
|
|
+ .arg((*host)->toText());
|
|
|
storage.push_back(*host);
|
|
|
}
|
|
|
+
|
|
|
+ // Log how many hosts have been found.
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT)
|
|
|
+ .arg(identifier_text)
|
|
|
+ .arg(storage.size());
|
|
|
}
|
|
|
|
|
|
template<typename Storage>
|
|
|
void
|
|
|
CfgHosts::getAllInternal(const HWAddrPtr& hwaddr, const DuidPtr& duid,
|
|
|
Storage& storage) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_HWADDR_DUID)
|
|
|
+ .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
|
|
|
+ .arg(duid ? duid->toText() : "(no-duid)");
|
|
|
+
|
|
|
// Get hosts using HW address.
|
|
|
if (hwaddr) {
|
|
|
getAllInternal<Storage>(hwaddr->hwaddr_, Host::IDENT_HWADDR, storage);
|
|
@@ -97,6 +152,9 @@ CfgHosts::getAllInternal(const HWAddrPtr& hwaddr, const DuidPtr& duid,
|
|
|
template<typename Storage>
|
|
|
void
|
|
|
CfgHosts::getAllInternal4(const IOAddress& address, Storage& storage) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_ADDRESS4)
|
|
|
+ .arg(address.toText());
|
|
|
+
|
|
|
// Must not specify address other than IPv4.
|
|
|
if (!address.isV4()) {
|
|
|
isc_throw(BadHostAddress, "must specify an IPv4 address when searching"
|
|
@@ -108,13 +166,24 @@ CfgHosts::getAllInternal4(const IOAddress& address, Storage& storage) const {
|
|
|
// Append each Host object to the storage.
|
|
|
for (HostContainerIndex1::iterator host = r.first; host != r.second;
|
|
|
++host) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
|
|
|
+ HOSTS_CFG_GET_ALL_ADDRESS4_HOST)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg((*host)->toText());
|
|
|
storage.push_back(*host);
|
|
|
}
|
|
|
+
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_ADDRESS4_COUNT)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg(storage.size());
|
|
|
}
|
|
|
|
|
|
template<typename Storage>
|
|
|
void
|
|
|
CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_ADDRESS6)
|
|
|
+ .arg(address.toText());
|
|
|
+
|
|
|
// Must not specify address other than IPv6.
|
|
|
if (!address.isV6()) {
|
|
|
isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
|
|
@@ -126,14 +195,23 @@ CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
|
|
|
// Append each Host object to the storage.
|
|
|
for (HostContainerIndex1::iterator host = r.first; host != r.second;
|
|
|
++host) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
|
|
|
+ HOSTS_CFG_GET_ALL_ADDRESS6_HOST)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg((*host)->toText());
|
|
|
storage.push_back(*host);
|
|
|
}
|
|
|
+
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_ADDRESS6_COUNT)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg(storage.size());
|
|
|
}
|
|
|
|
|
|
|
|
|
ConstHostPtr
|
|
|
CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
|
|
|
const DuidPtr& duid) const {
|
|
|
+ // Do not log here because getHostInternal logs.
|
|
|
// The false value indicates that it is an IPv4 subnet.
|
|
|
return (getHostInternal(subnet_id, false, hwaddr, duid));
|
|
|
}
|
|
@@ -141,19 +219,31 @@ CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
|
|
|
HostPtr
|
|
|
CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
|
|
|
const DuidPtr& duid) {
|
|
|
+ // Do not log here because getHostInternal logs.
|
|
|
// The false value indicates that it is an IPv4 subnet.
|
|
|
return (getHostInternal(subnet_id, false, hwaddr, duid));
|
|
|
}
|
|
|
|
|
|
ConstHostPtr
|
|
|
CfgHosts::get4(const SubnetID& subnet_id, const IOAddress& address) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4)
|
|
|
+ .arg(subnet_id).arg(address.toText());
|
|
|
+
|
|
|
ConstHostCollection hosts = getAll4(address);
|
|
|
for (ConstHostCollection::const_iterator host = hosts.begin();
|
|
|
host != hosts.end(); ++host) {
|
|
|
if ((*host)->getIPv4SubnetID() == subnet_id) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
|
|
+ HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_HOST)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg((*host)->toText());
|
|
|
return (*host);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_NULL)
|
|
|
+ .arg(subnet_id).arg(address.toText());
|
|
|
return (ConstHostPtr());
|
|
|
}
|
|
|
|
|
@@ -161,6 +251,7 @@ CfgHosts::get4(const SubnetID& subnet_id, const IOAddress& address) const {
|
|
|
ConstHostPtr
|
|
|
CfgHosts::get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
|
|
const HWAddrPtr& hwaddr) const {
|
|
|
+ // Do not log here because getHostInternal logs.
|
|
|
// The true value indicates that it is an IPv6 subnet.
|
|
|
return (getHostInternal(subnet_id, true, hwaddr, duid));
|
|
|
}
|
|
@@ -168,6 +259,7 @@ CfgHosts::get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
|
|
HostPtr
|
|
|
CfgHosts::get6(const SubnetID& subnet_id, const DuidPtr& duid,
|
|
|
const HWAddrPtr& hwaddr) {
|
|
|
+ // Do not log here because getHostInternal logs.
|
|
|
// The true value indicates that it is an IPv6 subnet.
|
|
|
return (getHostInternal(subnet_id, true, hwaddr, duid));
|
|
|
}
|
|
@@ -186,20 +278,49 @@ CfgHosts::get6(const IOAddress&, const uint8_t) {
|
|
|
ConstHostPtr
|
|
|
CfgHosts::get6(const SubnetID& subnet_id,
|
|
|
const asiolink::IOAddress& address) const {
|
|
|
- ConstHostCollection storage;
|
|
|
- getAllInternal6(subnet_id, address, storage);
|
|
|
+ // Do not log here because getHostInternal6 logs.
|
|
|
+ return (getHostInternal6<ConstHostPtr, ConstHostCollection>(subnet_id, address));
|
|
|
+}
|
|
|
|
|
|
+HostPtr
|
|
|
+CfgHosts::get6(const SubnetID& subnet_id,
|
|
|
+ const asiolink::IOAddress& address) {
|
|
|
+ // Do not log here because getHostInternal6 logs.
|
|
|
+ return (getHostInternal6<HostPtr, HostCollection>(subnet_id, address));
|
|
|
+}
|
|
|
+
|
|
|
+template<typename ReturnType, typename Storage>
|
|
|
+ReturnType
|
|
|
+CfgHosts::getHostInternal6(const SubnetID& subnet_id,
|
|
|
+ const asiolink::IOAddress& address) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6)
|
|
|
+ .arg(subnet_id).arg(address.toText());
|
|
|
+
|
|
|
+ Storage storage;
|
|
|
+ getAllInternal6<Storage>(subnet_id, address, storage);
|
|
|
switch (storage.size()) {
|
|
|
case 0:
|
|
|
- return (ConstHostPtr());
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
|
|
+ HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_NULL)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(address.toText());
|
|
|
+ return (HostPtr());
|
|
|
+
|
|
|
case 1:
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
|
|
+ HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_HOST)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg((*storage.begin())->toText());
|
|
|
return (*storage.begin());
|
|
|
+
|
|
|
default:
|
|
|
isc_throw(DuplicateHost, "more than one reservation found"
|
|
|
" for the host belonging to the subnet with id '"
|
|
|
<< subnet_id << "' and using the address '"
|
|
|
<< address.toText() << "'");
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
template<typename Storage>
|
|
@@ -207,6 +328,9 @@ void
|
|
|
CfgHosts::getAllInternal6(const SubnetID& subnet_id,
|
|
|
const asiolink::IOAddress& address,
|
|
|
Storage& storage) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6)
|
|
|
+ .arg(subnet_id).arg(address.toText());
|
|
|
+
|
|
|
// Must not specify address other than IPv6.
|
|
|
if (!address.isV6()) {
|
|
|
isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
|
|
@@ -223,30 +347,30 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id,
|
|
|
// multiple addresses reserved, but for each (address, subnet_id) there should
|
|
|
// be at most one host reserving it).
|
|
|
for(HostContainer6Index1::iterator resrv = r.first; resrv != r.second; ++resrv) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
|
|
|
+ HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg(resrv->host_);
|
|
|
storage.push_back(resrv->host_);
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-HostPtr
|
|
|
-CfgHosts::get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) {
|
|
|
- HostCollection storage;
|
|
|
- getAllInternal6<HostCollection>(subnet_id, address, storage);
|
|
|
- switch (storage.size()) {
|
|
|
- case 0:
|
|
|
- return (HostPtr());
|
|
|
- case 1:
|
|
|
- return (*storage.begin());
|
|
|
- default:
|
|
|
- isc_throw(DuplicateHost, "more than one reservation found"
|
|
|
- " for the host belonging to the subnet with id '"
|
|
|
- << subnet_id << "' and using the address '"
|
|
|
- << address.toText() << "'");
|
|
|
- }
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
|
|
+ HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_COUNT)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(address.toText())
|
|
|
+ .arg(storage.size());
|
|
|
}
|
|
|
|
|
|
HostPtr
|
|
|
CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
|
|
|
const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID)
|
|
|
+ .arg(subnet6 ? "IPv6" : "IPv4")
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
|
|
|
+ .arg(duid ? duid->toText() : "(no-duid)");
|
|
|
+
|
|
|
// 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.
|
|
@@ -284,17 +408,38 @@ CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (host) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
|
|
+ HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
|
|
|
+ .arg(duid ? duid->toText() : "(no-duid)")
|
|
|
+ .arg(host->toText());
|
|
|
+
|
|
|
+ } else {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
|
|
+ HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID_NULL)
|
|
|
+ .arg(subnet_id)
|
|
|
+ .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
|
|
|
+ .arg(duid ? duid->toText() : "(no-duid)");
|
|
|
+ }
|
|
|
+
|
|
|
return (host);
|
|
|
}
|
|
|
|
|
|
|
|
|
void
|
|
|
CfgHosts::add(const HostPtr& host) {
|
|
|
+ LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_ADD_HOST)
|
|
|
+ .arg(host ? host->toText() : "(no-host)");
|
|
|
+
|
|
|
// Sanity check that the host is non-null.
|
|
|
if (!host) {
|
|
|
isc_throw(BadValue, "specified host object must not be NULL when it"
|
|
|
" is added to the configuration");
|
|
|
}
|
|
|
+
|
|
|
// At least one subnet ID must be non-zero
|
|
|
if (host->getIPv4SubnetID() == 0 && host->getIPv6SubnetID() == 0) {
|
|
|
isc_throw(BadValue, "must not use both IPv4 and IPv6 subnet ids of"
|
|
@@ -308,7 +453,6 @@ CfgHosts::add(const HostPtr& host) {
|
|
|
|
|
|
void
|
|
|
CfgHosts::add4(const HostPtr& host) {
|
|
|
-
|
|
|
/// @todo This may need further sanity checks.
|
|
|
HWAddrPtr hwaddr = host->getHWAddress();
|
|
|
DuidPtr duid = host->getDuid();
|
|
@@ -316,7 +460,7 @@ CfgHosts::add4(const HostPtr& host) {
|
|
|
// There should be at least one resource reserved: hostname, IPv4
|
|
|
// address, IPv6 address or prefix.
|
|
|
if (host->getHostname().empty() &&
|
|
|
- (host->getIPv4Reservation() == IOAddress("0.0.0.0")) &&
|
|
|
+ (host->getIPv4Reservation().isV4Zero()) &&
|
|
|
(!host->hasIPv6Reservation())) {
|
|
|
std::ostringstream s;
|
|
|
if (hwaddr) {
|
|
@@ -357,7 +501,6 @@ CfgHosts::add4(const HostPtr& host) {
|
|
|
|
|
|
void
|
|
|
CfgHosts::add6(const HostPtr& host) {
|
|
|
-
|
|
|
/// @todo This may need further sanity checks.
|
|
|
HWAddrPtr hwaddr = host->getHWAddress();
|
|
|
DuidPtr duid = host->getDuid();
|