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);
85 template<
typename Storage>
88 const uint8_t* identifier,
89 const size_t identifier_len,
90 Storage& storage)
const {
94 std::string identifier_text = Host::getIdentifierAsText(identifier_type,
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());
124 template<
typename Storage>
126 CfgHosts::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());
153 template<
typename Storage>
155 CfgHosts::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,
243 CfgHosts::get6(
const IOAddress& prefix,
const uint8_t prefix_len)
const {
244 return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
248 CfgHosts::get6(
const IOAddress& prefix,
const uint8_t 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));
266 template<
typename ReturnType,
typename Storage>
268 CfgHosts::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() <<
"'");
300 template<
typename ReturnType>
302 CfgHosts::getHostInternal6(
const asiolink::IOAddress& prefix,
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)
316 .arg(prefix.toText())
317 .arg(
static_cast<int>(prefix_len))
318 .arg(resrv->host_->toText());
319 return (resrv->host_);
324 HOSTS_CFG_GET_ONE_PREFIX_NULL)
325 .arg(prefix.toText())
326 .arg(
static_cast<int>(prefix_len));
327 return (ReturnType());
330 template<
typename Storage>
332 CfgHosts::getAllInternal6(
const SubnetID& subnet_id,
333 const asiolink::IOAddress& address,
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)
357 .arg(address.toText())
358 .arg(resrv->host_->toText());
359 storage.push_back(resrv->host_);
363 HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_COUNT)
365 .arg(address.toText())
366 .arg(storage.size());
370 CfgHosts::getHostInternal(
const SubnetID& subnet_id,
const bool subnet6,
371 const Host::IdentifierType& identifier_type,
372 const uint8_t* identifier,
373 const size_t identifier_len)
const {
376 .arg(subnet6 ?
"IPv6" :
"IPv4")
378 .arg(Host::getIdentifierAsText(identifier_type, identifier, identifier_len));
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 '"
411 << Host::getIdentifierAsText(identifier_type,
421 HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST)
423 .arg(Host::getIdentifierAsText(identifier_type, identifier,
425 .arg(host->toText());
429 HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL)
431 .arg(Host::getIdentifierAsText(identifier_type, identifier,
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");
462 CfgHosts::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();
486 isc_throw(BadValue,
"specified reservation " << s.str()
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() &&
495 get4(host->getIPv4SubnetID(), Host::IDENT_HWADDR,
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() &&
503 get4(host->getIPv4SubnetID(), Host::IDENT_DUID,
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() &&
513 get6(host->getIPv6SubnetID(), Host::IDENT_DUID,
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() &&
521 get6(host->getIPv6SubnetID(), Host::IDENT_HWADDR,
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: "
548 << Host::getIdentifierAsText(host->getIdentifierType(),
558 CfgHosts::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);
654 CfgHosts::toElement()
const {
655 uint16_t family = CfgMgr::instance().getFamily();
656 if (family == AF_INET) {
657 return (toElement4());
658 }
else if (family == AF_INET6) {
659 return (toElement6());
662 "address family: " << family);
667 CfgHosts::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);
685 CfgHosts::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());