Commit 3979656c authored by Marcin Siodelski's avatar Marcin Siodelski

[master] Merge branch 'trac4302_rebase'

parents 14cc8ad6 634cf7a2
# Copyright (C) 2012-2015 Internet Systems Consortium.
# Copyright (C) 2012-2016 Internet Systems Consortium.
#
# 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
......@@ -395,6 +395,52 @@ SET version = '4', minor = '1';
# This line concludes database upgrade to version 4.1.
# Update index used for searching DHCPv4 reservations by identifier and subnet id.
# This index is now unique (to prevent duplicates) and includes DHCPv4 subnet
# identifier.
DROP INDEX key_dhcp4_identifier_subnet_id ON hosts;
CREATE UNIQUE INDEX key_dhcp4_identifier_subnet_id ON hosts (dhcp_identifier ASC , dhcp_identifier_type ASC , dhcp4_subnet_id ASC);
# Update index used for searching DHCPv6 reservations by identifier and subnet id.
# This index is now unique to prevent duplicates.
DROP INDEX key_dhcp6_identifier_subnet_id ON hosts;
CREATE UNIQUE INDEX key_dhcp6_identifier_subnet_id ON hosts (dhcp_identifier ASC , dhcp_identifier_type ASC , dhcp6_subnet_id ASC);
# Create index to search for reservations using IP address and subnet id.
# This unique index guarantees that there is only one occurence of the
# particular IPv4 address for a given subnet.
CREATE UNIQUE INDEX key_dhcp4_ipv4_address_subnet_id ON hosts (ipv4_address ASC , dhcp4_subnet_id ASC);
# Create index to search for reservations using address/prefix and prefix
# length.
CREATE UNIQUE INDEX key_dhcp6_address_prefix_len ON ipv6_reservations (address ASC , prefix_len ASC);
# Create a table mapping host identifiers to their names. Values in this
# table are used as a foreign key in hosts table to guarantee that only
# identifiers present in host_identifier_type table are used in hosts
# table.
CREATE TABLE IF NOT EXISTS host_identifier_type (
type TINYINT PRIMARY KEY NOT NULL, # Lease type code.
name VARCHAR(32) # Name of the lease type
) ENGINE = INNODB;
START TRANSACTION;
INSERT INTO host_identifier_type VALUES (0, "hw-address"); # Non-temporary v6 addresses
INSERT INTO host_identifier_type VALUES (1, "duid"); # Temporary v6 addresses
INSERT INTO host_identifier_type VALUES (2, "circuit-id"); # Prefix delegations
COMMIT;
# Add a constraint that any identifier type value added to the hosts
# must map to a value in the host_identifier_type table.
ALTER TABLE hosts
ADD CONSTRAINT fk_host_identifier_type FOREIGN KEY (dhcp_identifier_type)
REFERENCES host_identifier_type (type);
# Update the schema version number
UPDATE schema_version
SET version = '4', minor = '2';
# This line concludes database upgrade to version 4.2.
# Notes:
#
# Indexes
......
#!/bin/sh
# Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2014-2016 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
......@@ -178,6 +178,13 @@ EOF
ERRCODE=$?
assert_eq 0 $ERRCODE "dhcp6_options table is missing or broken. (returned status code %d, expected %d)"
# Sixth table: host_identifier_type
mysql -u$db_user -p$db_password $db_name >/dev/null 2>&1 <<EOF
SELECT type, name FROM host_identifier_type;
EOF
ERRCODE=$?
assert_eq 0 $ERRCODE "host_identifier_type table is missing or broken. (returned status code %d, expected %d)"
# Let's wipe the whole database
mysql_wipe
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2016 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
......@@ -98,6 +98,23 @@ public:
virtual ConstHostCollection
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const = 0;
/// @brief Return all hosts connected to any subnet for which reservations
/// have been made using a specified identifier.
///
/// This method returns all @c Host objects which represent reservations
/// for a specified identifier. This method may return multiple hosts
/// because a particular client may have reservations in multiple subnets.
///
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const = 0;
/// @brief Returns a collection of hosts using the specified IPv4 address.
///
/// This method may return multiple @c Host objects if they are connected
......@@ -127,6 +144,23 @@ public:
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid = DuidPtr()) const = 0;
/// @brief Returns a host connected to the IPv4 subnet.
///
/// @param subnet_id Subnet identifier.
/// @param identifier_type Identifier type.
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Const @c Host object for which reservation has been made using
/// the specified identifier.
virtual ConstHostPtr
get4(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const = 0;
/// @brief Returns a host connected to the IPv4 subnet and having
/// a reservation for a specified IPv4 address.
///
......@@ -165,6 +199,21 @@ public:
get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr = HWAddrPtr()) const = 0;
/// @brief Returns a host connected to the IPv6 subnet.
///
/// @param subnet_id Subnet identifier.
/// @param identifier_type Identifier type.
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Const @c Host object for which reservation has been made using
/// the specified identifier.
virtual ConstHostPtr
get6(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const = 0;
/// @brief Returns a host using the specified IPv6 prefix.
///
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2016 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
......@@ -33,6 +33,29 @@ CfgHosts::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) {
return (collection);
}
ConstHostCollection
CfgHosts::getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
// Do not issue logging message here because it will be logged by
// the getAllInternal method.
ConstHostCollection collection;
getAllInternal<ConstHostCollection>(identifier_type, identifier_begin,
identifier_len, collection);
return (collection);
}
HostCollection
CfgHosts::getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len) {
// Do not issue logging message here because it will be logged by
// the getAllInternal method.
HostCollection collection;
getAllInternal<HostCollection>(identifier_type, identifier_begin,
identifier_len, collection);
return (collection);
}
ConstHostCollection
CfgHosts::getAll4(const IOAddress& address) const {
// Do not issue logging message here because it will be logged by
......@@ -71,27 +94,26 @@ CfgHosts::getAll6(const IOAddress& address) {
template<typename Storage>
void
CfgHosts::getAllInternal(const std::vector<uint8_t>& identifier,
const Host::IdentifierType& identifier_type,
CfgHosts::getAllInternal(const Host::IdentifierType& identifier_type,
const uint8_t* identifier,
const size_t identifier_len,
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.
}
try {
// Use Host object to find the textual form of the identifier.
// This may throw exception if the identifier is invalid.
Host host(identifier, identifier_len, 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.
......@@ -106,10 +128,13 @@ CfgHosts::getAllInternal(const std::vector<uint8_t>& identifier,
// 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 =
boost::make_tuple(identifier, identifier_type);
boost::make_tuple(std::vector<uint8_t>(identifier,
identifier + identifier_len),
identifier_type);
// Append each Host object to the storage.
for (HostContainerIndex0::iterator host = idx.lower_bound(t); host != idx.upper_bound(t);
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)
......@@ -133,12 +158,14 @@ CfgHosts::getAllInternal(const HWAddrPtr& hwaddr, const DuidPtr& duid,
.arg(duid ? duid->toText() : "(no-duid)");
// Get hosts using HW address.
if (hwaddr) {
getAllInternal<Storage>(hwaddr->hwaddr_, Host::IDENT_HWADDR, storage);
if (hwaddr && !hwaddr->hwaddr_.empty()) {
getAllInternal<Storage>(Host::IDENT_HWADDR, &hwaddr->hwaddr_[0],
hwaddr->hwaddr_.size(), storage);
}
// Get hosts using DUID.
if (duid) {
getAllInternal<Storage>(duid->getDuid(), Host::IDENT_DUID, storage);
if (duid && !duid->getDuid().empty()) {
getAllInternal<Storage>(Host::IDENT_DUID, &duid->getDuid()[0],
duid->getDuid().size(), storage);
}
}
......@@ -200,13 +227,23 @@ CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
.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));
HostPtr host;
if (hwaddr && !hwaddr->hwaddr_.empty()) {
host = getHostInternal(subnet_id, false, Host::IDENT_HWADDR,
&hwaddr->hwaddr_[0],
hwaddr->hwaddr_.size());
}
if (!host && duid && !duid->getDuid().empty()) {
host = getHostInternal(subnet_id, false, Host::IDENT_DUID,
&duid->getDuid()[0],
duid->getDuid().size());
}
return (host);
}
HostPtr
......@@ -214,7 +251,36 @@ 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));
HostPtr host;
if (hwaddr && !hwaddr->hwaddr_.empty()) {
host = getHostInternal(subnet_id, false, Host::IDENT_HWADDR,
&hwaddr->hwaddr_[0],
hwaddr->hwaddr_.size());
}
if (!host && duid && !duid->getDuid().empty()) {
host = getHostInternal(subnet_id, false, Host::IDENT_DUID,
&duid->getDuid()[0],
duid->getDuid().size());
}
return (host);
}
ConstHostPtr
CfgHosts::get4(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
identifier_len));
}
HostPtr
CfgHosts::get4(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) {
return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
identifier_len));
}
ConstHostPtr
......@@ -246,7 +312,19 @@ 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));
HostPtr host;
if (duid && !duid->getDuid().empty()) {
host = getHostInternal(subnet_id, true, Host::IDENT_DUID,
&duid->getDuid()[0],
duid->getDuid().size());
}
if (!host && hwaddr && !hwaddr->hwaddr_.empty()) {
host = getHostInternal(subnet_id, true, Host::IDENT_HWADDR,
&hwaddr->hwaddr_[0],
hwaddr->hwaddr_.size());
}
return (host);
}
HostPtr
......@@ -254,18 +332,47 @@ 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));
HostPtr host;
if (duid && !duid->getDuid().empty()) {
host = getHostInternal(subnet_id, true, Host::IDENT_DUID,
&duid->getDuid()[0],
duid->getDuid().size());
}
if (!host && hwaddr && !hwaddr->hwaddr_.empty()) {
host = getHostInternal(subnet_id, true, Host::IDENT_HWADDR,
&hwaddr->hwaddr_[0],
hwaddr->hwaddr_.size());
}
return (host);
}
ConstHostPtr
CfgHosts::get6(const IOAddress&, const uint8_t) const {
isc_throw(isc::NotImplemented,
"get6(prefix, len) const is not implemented");
CfgHosts::get6(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) const {
return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
identifier_len));
}
HostPtr
CfgHosts::get6(const IOAddress&, const uint8_t) {
isc_throw(isc::NotImplemented, "get6(prefix, len) is not implemented");
CfgHosts::get6(const SubnetID& subnet_id,
const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len) {
return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
identifier_len));
}
ConstHostPtr
CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
}
HostPtr
CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) {
return (getHostInternal6<HostPtr>(prefix, prefix_len));
}
ConstHostPtr
......@@ -316,6 +423,36 @@ CfgHosts::getHostInternal6(const SubnetID& subnet_id,
}
template<typename ReturnType>
ReturnType
CfgHosts::getHostInternal6(const asiolink::IOAddress& prefix,
const uint8_t prefix_len) const {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_PREFIX)
.arg(prefix.toText()).arg(static_cast<int>(prefix_len));
// Let's get all reservations that match subnet_id, address.
const HostContainer6Index0& idx = hosts6_.get<0>();
HostContainer6Index0Range r = make_pair(idx.lower_bound(prefix),
idx.upper_bound(prefix));
for (HostContainer6Index0::iterator resrv = r.first; resrv != r.second;
++resrv) {
if (resrv->resrv_.getPrefixLen() == prefix_len) {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
HOSTS_CFG_GET_ONE_PREFIX_HOST)
.arg(prefix.toText())
.arg(static_cast<int>(prefix_len))
.arg(resrv->host_->toText());
return (resrv->host_);
}
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
HOSTS_CFG_GET_ONE_PREFIX_NULL)
.arg(prefix.toText())
.arg(static_cast<int>(prefix_len));
return (ReturnType());
}
template<typename Storage>
void
CfgHosts::getAllInternal6(const SubnetID& subnet_id,
......@@ -344,7 +481,7 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id,
HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST)
.arg(subnet_id)
.arg(address.toText())
.arg(resrv->host_);
.arg(resrv->host_->toText());
storage.push_back(resrv->host_);
}
......@@ -357,18 +494,21 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id,
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)
const Host::IdentifierType& identifier_type,
const uint8_t* identifier,
const size_t identifier_len) const {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER)
.arg(subnet6 ? "IPv6" : "IPv4")
.arg(subnet_id)
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
.arg(duid ? duid->toText() : "(no-duid)");
.arg(Host::getIdentifierAsText(identifier_type, identifier, identifier_len));
// Get all hosts for the HW address and DUID. This may return multiple hosts
// Get all hosts for a specified identifier. 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);
getAllInternal<HostCollection>(identifier_type, identifier, identifier_len,
hosts);
HostPtr host;
// Iterate over the returned hosts and select those for which the
......@@ -393,10 +533,10 @@ CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
} 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)")
<< subnet_id << "' and using the identifier '"
<< Host::getIdentifierAsText(identifier_type,
identifier,
identifier_len)
<< "'");
}
}
......@@ -404,24 +544,23 @@ 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)
HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST)
.arg(subnet_id)
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
.arg(duid ? duid->toText() : "(no-duid)")
.arg(Host::getIdentifierAsText(identifier_type, identifier,
identifier_len))
.arg(host->toText());
} else {
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID_NULL)
HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL)
.arg(subnet_id)
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
.arg(duid ? duid->toText() : "(no-duid)");
.arg(Host::getIdentifierAsText(identifier_type, identifier,
identifier_len));
}
return (host);
}
void
CfgHosts::add(const HostPtr& host) {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_ADD_HOST)
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2016 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
......@@ -69,6 +69,40 @@ public:
virtual HostCollection
getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr());
/// @brief Return all hosts connected to any subnet for which reservations
/// have been made using a specified identifier.
///
/// This method returns all @c Host objects which represent reservations
/// for a specified identifier. This method may return multiple hosts
/// because a particular client may have reservations in multiple subnets.
///
/// @param identifier_type One of the supported identifier types.
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Collection of const @c Host objects.
virtual ConstHostCollection
getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len) const;
/// @brief Non-const version of the @c getAll const method.
///
/// This method returns all @c Host objects which represent reservations
/// for a specified identifier. This method may return multiple hosts
/// because a particular client may have reservations in multiple subnets.
///
/// @param identifier_type One of the supported identifier types.
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Collection of non-const @c Host objects.
virtual HostCollection
getAll(const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin,
const size_t identifier_len);
/// @brief Returns a collection of hosts using the specified IPv4 address.
///
/// This method may return multiple @c Host objects if they are connected
......@@ -143,6 +177,34 @@ public:
get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid = DuidPtr());
/// @brief Returns a host connected to the IPv4 subnet.
///
/// @param subnet_id Subnet identifier.
/// @param identifier_type Identifier type.
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Const @c Host object for which reservation has been made using
/// the specified identifier.
virtual ConstHostPtr
get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len) const;
/// @brief Returns a host connected to the IPv4 subnet.
///
/// @param subnet_id Subnet identifier.
/// @param identifier_type Identifier type.
/// @param identifier_begin Pointer to a begining of a buffer containing
/// an identifier.
/// @param identifier_len Identifier length.
///
/// @return Non-const @c Host object for which reservation has been made
/// using the specified identifier.
virtual HostPtr
get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len);
/// @brief Returns a host connected to the IPv4 subnet and having
/// a reservation for a specified IPv4 address.
///
......@@ -183,12 +245,40 @@ public:
get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr = HWAddrPtr());
/// @brief Returns a host connected to the IPv6 subnet.
///
/// @param subnet_id Subnet identifier.
/// @param identifier_type Identifier type.
/// @param identifier_begin Pointer to a begining of a buffer containing