28 const uint8_t* identifier_begin,
29 const size_t identifier_len)
const {
33 getAllInternal<ConstHostCollection>(identifier_type, identifier_begin,
34 identifier_len, collection);
40 const uint8_t* identifier_begin,
const size_t identifier_len) {
44 getAllInternal<HostCollection>(identifier_type, identifier_begin,
45 identifier_len, collection);
54 getAllInternal4<ConstHostCollection>(address, collection);
63 getAllInternal4<HostCollection>(address, collection);
72 getAllInternal6<ConstHostCollection>(address, collection);
81 getAllInternal6<HostCollection>(address, collection);
85template<
typename Storage>
88 const uint8_t* identifier,
89 const size_t identifier_len,
90 Storage& storage)
const {
98 .arg(identifier_text);
103 boost::make_tuple(std::vector<uint8_t>(identifier,
104 identifier + identifier_len),
108 for (HostContainerIndex0::iterator host = idx.lower_bound(t);
109 host != idx.upper_bound(t);
112 HOSTS_CFG_GET_ALL_IDENTIFIER_HOST)
113 .arg(identifier_text)
114 .arg((*host)->toText());
115 storage.push_back(*host);
120 .arg(identifier_text)
121 .arg(storage.size());
124template<
typename Storage>
126CfgHosts::getAllInternal4(
const IOAddress& address, Storage& storage)
const {
131 if (!address.
isV4()) {
132 isc_throw(BadHostAddress,
"must specify an IPv4 address when searching"
133 " for a host, specified address was " << address);
139 for (HostContainerIndex1::iterator host = r.first; host != r.second;
142 HOSTS_CFG_GET_ALL_ADDRESS4_HOST)
144 .arg((*host)->toText());
145 storage.push_back(*host);
150 .arg(storage.size());
153template<
typename Storage>
155CfgHosts::getAllInternal6(
const IOAddress& address, Storage& storage)
const {
160 if (!address.
isV6()) {
161 isc_throw(BadHostAddress,
"must specify an IPv6 address when searching"
162 " for a host, specified address was " << address);
168 for (HostContainerIndex1::iterator host = r.first; host != r.second;
171 HOSTS_CFG_GET_ALL_ADDRESS6_HOST)
173 .arg((*host)->toText());
174 storage.push_back(*host);
179 .arg(storage.size());
185 const uint8_t* identifier_begin,
186 const size_t identifier_len)
const {
187 return (getHostInternal(subnet_id,
false, identifier_type, identifier_begin,
194 const uint8_t* identifier_begin,
195 const size_t identifier_len) {
196 return (getHostInternal(subnet_id,
false, identifier_type, identifier_begin,
203 .arg(subnet_id).arg(address.
toText());
206 for (ConstHostCollection::const_iterator host = hosts.begin();
207 host != hosts.end(); ++host) {
208 if ((*host)->getIPv4SubnetID() == subnet_id) {
210 HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_HOST)
213 .arg((*host)->toText());
219 .arg(subnet_id).arg(address.
toText());
227 const uint8_t* identifier_begin,
228 const size_t identifier_len)
const {
229 return (getHostInternal(subnet_id,
true, identifier_type, identifier_begin,
236 const uint8_t* identifier_begin,
237 const size_t identifier_len) {
238 return (getHostInternal(subnet_id,
true, identifier_type, identifier_begin,
244 return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
249 return (getHostInternal6<HostPtr>(prefix, prefix_len));
256 return (getHostInternal6<ConstHostPtr, ConstHostCollection>(subnet_id, address));
263 return (getHostInternal6<HostPtr, HostCollection>(subnet_id, address));
266template<
typename ReturnType,
typename Storage>
268CfgHosts::getHostInternal6(
const SubnetID& subnet_id,
271 .arg(subnet_id).arg(address.
toText());
274 getAllInternal6<Storage>(subnet_id, address, storage);
275 switch (storage.size()) {
278 HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_NULL)
285 HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_HOST)
288 .arg((*storage.begin())->toText());
289 return (*storage.begin());
293 " for the host belonging to the subnet with id '"
294 << subnet_id <<
"' and using the address '"
295 << address.
toText() <<
"'");
300template<
typename ReturnType>
303 const uint8_t prefix_len)
const {
305 .arg(prefix.
toText()).arg(
static_cast<int>(prefix_len));
310 idx.upper_bound(prefix));
311 for (HostContainer6Index0::iterator resrv = r.first; resrv != r.second;
313 if (resrv->resrv_.getPrefixLen() == prefix_len) {
315 HOSTS_CFG_GET_ONE_PREFIX_HOST)
317 .arg(
static_cast<int>(prefix_len))
318 .arg(resrv->host_->toText());
319 return (resrv->host_);
324 HOSTS_CFG_GET_ONE_PREFIX_NULL)
326 .arg(
static_cast<int>(prefix_len));
327 return (ReturnType());
330template<
typename Storage>
332CfgHosts::getAllInternal6(
const SubnetID& subnet_id,
334 Storage& storage)
const {
336 .arg(subnet_id).arg(address.
toText());
339 if (!address.
isV6()) {
340 isc_throw(BadHostAddress,
"must specify an IPv6 address when searching"
341 " for a host, specified address was " << address);
347 idx.upper_bound(boost::make_tuple(subnet_id, address)));
353 for(HostContainer6Index1::iterator resrv = r.first; resrv != r.second; ++resrv) {
355 HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST)
358 .arg(resrv->host_->toText());
359 storage.push_back(resrv->host_);
363 HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_COUNT)
366 .arg(storage.size());
370CfgHosts::getHostInternal(
const SubnetID& subnet_id,
const bool subnet6,
372 const uint8_t* identifier,
373 const size_t identifier_len)
const {
376 .arg(subnet6 ?
"IPv6" :
"IPv4")
384 getAllInternal<HostCollection>(identifier_type, identifier, identifier_len,
390 for (HostCollection::const_iterator host_it = hosts.begin();
391 host_it != hosts.end(); ++host_it) {
393 SubnetID host_subnet_id = subnet6 ? (*host_it)->getIPv6SubnetID() :
394 (*host_it)->getIPv4SubnetID();
396 if (subnet_id == host_subnet_id) {
408 isc_throw(DuplicateHost,
"more than one reservation found"
409 " for the host belonging to the subnet with id '"
410 << subnet_id <<
"' and using the identifier '"
421 HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST)
425 .arg(host->toText());
429 HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL)
441 .arg(host ? host->toText() :
"(no-host)");
446 " is added to the configuration");
450 if (host->getIPv4SubnetID() == SUBNET_ID_UNUSED &&
451 host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
453 " 0 when adding new host reservation");
462CfgHosts::add4(
const HostPtr& host) {
465 DuidPtr duid = host->getDuid();
470 if (host->getHostname().empty() &&
471 (host->getIPv4Reservation().isV4Zero()) &&
472 !host->hasIPv6Reservation() &&
473 host->getNextServer().isV4Zero() &&
474 host->getServerHostname().empty() &&
475 host->getBootFileName().empty() &&
476 host->getCfgOption4()->empty() &&
477 host->getCfgOption6()->empty() &&
478 host->getClientClasses4().empty() &&
479 host->getClientClasses6().empty()) {
480 std::ostringstream s;
482 s <<
"for DUID: " << hwaddr->toText();
484 s <<
"for HW address: " << duid->toText();
487 <<
" must include at least one resource, i.e. "
488 "hostname, IPv4 address, IPv6 address/prefix, "
493 if (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) {
494 if (hwaddr && !hwaddr->hwaddr_.empty() &&
496 &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
497 isc_throw(DuplicateHost,
"failed to add new host using the HW"
498 <<
" address '" << hwaddr->toText(
false)
499 <<
"' to the IPv4 subnet id '" << host->getIPv4SubnetID()
500 <<
"' as this host has already been added");
502 if (duid && !duid->getDuid().empty() &&
504 &duid->getDuid()[0], duid->getDuid().size())) {
505 isc_throw(DuplicateHost,
"failed to add new host using the "
506 <<
"DUID '" << duid->toText()
507 <<
"' to the IPv4 subnet id '" << host->getIPv4SubnetID()
508 <<
"' as this host has already been added");
511 }
else if (host->getIPv6SubnetID() != SUBNET_ID_UNUSED) {
512 if (duid && !duid->getDuid().empty() &&
514 &duid->getDuid()[0], duid->getDuid().size())) {
515 isc_throw(DuplicateHost,
"failed to add new host using the "
516 <<
"DUID '" << duid->toText()
517 <<
"' to the IPv6 subnet id '" << host->getIPv6SubnetID()
518 <<
"' as this host has already been added");
520 if (hwaddr && !hwaddr->hwaddr_.empty() &&
522 &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
523 isc_throw(DuplicateHost,
"failed to add new host using the HW"
524 <<
" address '" << hwaddr->toText(
false)
525 <<
"' to the IPv6 subnet id '" << host->getIPv6SubnetID()
526 <<
"' as this host has already been added");
531 if (!host->getIPv4Reservation().isV4Zero() &&
532 (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) &&
533 get4(host->getIPv4SubnetID(), host->getIPv4Reservation())) {
534 isc_throw(ReservedAddress,
"failed to add new host using the HW"
535 " address '" << (hwaddr ? hwaddr->toText(
false) :
"(null)")
536 <<
" and DUID '" << (duid ? duid->toText() :
"(null)")
537 <<
"' to the IPv4 subnet id '" << host->getIPv4SubnetID()
538 <<
"' for the address " << host->getIPv4Reservation()
539 <<
": There's already a reservation for this address");
543 const std::vector<uint8_t>&
id = host->getIdentifier();
544 if ((host->getIPv4SubnetID() != SUBNET_ID_UNUSED) && !
id.empty()) {
545 if (
get4(host->getIPv4SubnetID(), host->getIdentifierType(), &
id[0],
547 isc_throw(DuplicateHost,
"failed to add duplicate IPv4 host using identifier: "
558CfgHosts::add6(
const HostPtr& host) {
560 if (host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
566 DuidPtr duid = host->getDuid();
572 if (std::distance(reservations.first, reservations.second) == 0) {
583 if (
get6(host->getIPv6SubnetID(), it->second.getPrefix())) {
584 isc_throw(DuplicateHost,
"failed to add address reservation for "
585 <<
"host using the HW address '"
586 << (hwaddr ? hwaddr->toText(
false) :
"(null)")
587 <<
" and DUID '" << (duid ? duid->toText() :
"(null)")
588 <<
"' to the IPv6 subnet id '" << host->getIPv6SubnetID()
589 <<
"' for address/prefix " << it->second.getPrefix()
590 <<
": There's already reservation for this address/prefix");
592 hosts6_.insert(HostResrv6Tuple(it->second, host));
606 size_t erased = idx.erase(subnet_id);
629 size_t erased_addresses = idx6.erase(subnet_id);
633 size_t erased_hosts = idx.erase(subnet_id);
637 .arg(erased_addresses)
640 return (erased_hosts);
656 if (family == AF_INET) {
657 return (toElement4());
658 }
else if (family == AF_INET6) {
659 return (toElement6());
662 "address family: " << family);
667CfgHosts::toElement4()
const {
671 for (HostContainerIndex0::const_iterator host = idx.begin();
672 host != idx.end(); ++host) {
678 SubnetID subnet_id = (*host)->getIPv4SubnetID();
679 result.
add(subnet_id, map);
685CfgHosts::toElement6()
const {
689 for (HostContainerIndex0::const_iterator host = idx.begin();
690 host != idx.end(); ++host) {
696 SubnetID subnet_id = (*host)->getIPv6SubnetID();
697 result.add(subnet_id, map);
699 return (result.externalize());
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when a function is not implemented.
The IOAddress class represents an IP addresses (version agnostic)
std::string toText() const
Convert the address to a string.
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 address.
Utility class to represent host reservation configurations internally as a map keyed by subnet IDs,...
void add(SubnetID id, isc::data::ElementPtr resv)
Add a host reservation to the map.
isc::data::ElementPtr externalize() const
Externalize the map to a list Element.
virtual size_t delAll4(const SubnetID &subnet_id)
Attempts to delete all hosts for a given IPv4 subnet.
virtual void add(const HostPtr &host)
Adds a new host to the collection.
virtual bool del4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len)
Attempts to delete a host by (subnet4-id, identifier, identifier-type)
virtual ConstHostCollection getAll6(const asiolink::IOAddress &address) const
Returns a collection of hosts using the specified IPv6 address.
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr)
Attempts to delete a host by address.
virtual ConstHostCollection getAll4(const asiolink::IOAddress &address) const
Returns a collection of hosts using the specified IPv4 address.
virtual size_t delAll6(const SubnetID &subnet_id)
Attempts to delete all hosts for a given IPv6 subnet.
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv6 subnet.
virtual bool del6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len)
Attempts to delete a host by (subnet6-id, identifier, identifier-type)
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv4 subnet.
isc::data::ElementPtr toElement() const
Unparse a configuration object.
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
uint16_t getFamily() const
Returns address family.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Exception thrown when the duplicate Host object is detected.
IdentifierType
Type of the host identifier.
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< Element > ElementPtr
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
std::pair< HostContainerIndex1::iterator, HostContainerIndex1::iterator > HostContainerIndex1Range
Results range returned using the HostContainerIndex1.
isc::log::Logger hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
std::pair< HostContainer6Index1::iterator, HostContainer6Index1::iterator > HostContainer6Index1Range
Results range returned using the HostContainer6Index1.
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
boost::shared_ptr< DUID > DuidPtr
HostContainer6::nth_index< 0 >::type HostContainer6Index0
First index type in the HostContainer6.
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
HostContainer6::nth_index< 1 >::type HostContainer6Index1
Second index type in the HostContainer6.
std::vector< HostPtr > HostCollection
Collection of the Host objects.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
HostContainer::nth_index< 1 >::type HostContainerIndex1
Second index type in the HostContainer.
HostContainer6::nth_index< 2 >::type HostContainer6Index2
Third index type in the HostContainer6.
HostContainer::nth_index< 3 >::type HostContainerIndex3
Forth index type in the HostContainer.
const int HOSTS_DBG_TRACE
Logging levels for the host reservations management.
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
std::pair< HostContainer6Index0::iterator, HostContainer6Index0::iterator > HostContainer6Index0Range
Results range returned using the HostContainer6Index0.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
HostContainer::nth_index< 0 >::type HostContainerIndex0
First index type in the HostContainer.
const int HOSTS_DBG_TRACE_DETAIL_DATA
Records detailed results of lookups.
const int HOSTS_DBG_RESULTS
Records the results of the lookups.
HostContainer::nth_index< 2 >::type HostContainerIndex2
Third index type in the HostContainer.
Defines the logger used by the top-level component of kea-dhcp-ddns.