Kea 1.5.0
cfg_hosts.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8#include <dhcp/duid.h>
9#include <dhcp/hwaddr.h>
10#include <dhcpsrv/cfg_hosts.h>
12#include <dhcpsrv/hosts_log.h>
13#include <dhcpsrv/cfgmgr.h>
15#include <util/encode/hex.h>
16#include <ostream>
17#include <string>
18#include <vector>
19
20using namespace isc::asiolink;
21using namespace isc::data;
22
23namespace isc {
24namespace dhcp {
25
28 const uint8_t* identifier_begin,
29 const size_t identifier_len) const {
30 // Do not issue logging message here because it will be logged by
31 // the getAllInternal method.
32 ConstHostCollection collection;
33 getAllInternal<ConstHostCollection>(identifier_type, identifier_begin,
34 identifier_len, collection);
35 return (collection);
36}
37
40 const uint8_t* identifier_begin, const size_t identifier_len) {
41 // Do not issue logging message here because it will be logged by
42 // the getAllInternal method.
43 HostCollection collection;
44 getAllInternal<HostCollection>(identifier_type, identifier_begin,
45 identifier_len, collection);
46 return (collection);
47}
48
50CfgHosts::getAll4(const IOAddress& address) const {
51 // Do not issue logging message here because it will be logged by
52 // the getAllInternal4 method.
53 ConstHostCollection collection;
54 getAllInternal4<ConstHostCollection>(address, collection);
55 return (collection);
56}
57
60 // Do not issue logging message here because it will be logged by
61 // the getAllInternal4 method.
62 HostCollection collection;
63 getAllInternal4<HostCollection>(address, collection);
64 return (collection);
65}
66
68CfgHosts::getAll6(const IOAddress& address) const {
69 // Do not issue logging message here because it will be logged by
70 // the getAllInternal6 method.
71 ConstHostCollection collection;
72 getAllInternal6<ConstHostCollection>(address, collection);
73 return (collection);
74}
75
78 // Do not issue logging message here because it will be logged by
79 // the getAllInternal6 method.
80 HostCollection collection;
81 getAllInternal6<HostCollection>(address, collection);
82 return (collection);
83}
84
85template<typename Storage>
86void
87CfgHosts::getAllInternal(const Host::IdentifierType& identifier_type,
88 const uint8_t* identifier,
89 const size_t identifier_len,
90 Storage& storage) const {
91
92 // Convert host identifier into textual format for logging purposes.
93 // This conversion is exception free.
94 std::string identifier_text = Host::getIdentifierAsText(identifier_type,
95 identifier,
96 identifier_len);
97 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_IDENTIFIER)
98 .arg(identifier_text);
99
100 // Use the identifier and identifier type as a composite key.
101 const HostContainerIndex0& idx = hosts_.get<0>();
102 boost::tuple<const std::vector<uint8_t>, const Host::IdentifierType> t =
103 boost::make_tuple(std::vector<uint8_t>(identifier,
104 identifier + identifier_len),
105 identifier_type);
106
107 // Append each Host object to the storage.
108 for (HostContainerIndex0::iterator host = idx.lower_bound(t);
109 host != idx.upper_bound(t);
110 ++host) {
112 HOSTS_CFG_GET_ALL_IDENTIFIER_HOST)
113 .arg(identifier_text)
114 .arg((*host)->toText());
115 storage.push_back(*host);
116 }
117
118 // Log how many hosts have been found.
119 LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT)
120 .arg(identifier_text)
121 .arg(storage.size());
122}
123
124template<typename Storage>
125void
126CfgHosts::getAllInternal4(const IOAddress& address, Storage& storage) const {
127 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_ADDRESS4)
128 .arg(address.toText());
129
130 // Must not specify address other than IPv4.
131 if (!address.isV4()) {
132 isc_throw(BadHostAddress, "must specify an IPv4 address when searching"
133 " for a host, specified address was " << address);
134 }
135 // Search for the Host using the reserved IPv4 address as a key.
136 const HostContainerIndex1& idx = hosts_.get<1>();
137 HostContainerIndex1Range r = idx.equal_range(address);
138 // Append each Host object to the storage.
139 for (HostContainerIndex1::iterator host = r.first; host != r.second;
140 ++host) {
142 HOSTS_CFG_GET_ALL_ADDRESS4_HOST)
143 .arg(address.toText())
144 .arg((*host)->toText());
145 storage.push_back(*host);
146 }
147
148 LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_ADDRESS4_COUNT)
149 .arg(address.toText())
150 .arg(storage.size());
151}
152
153template<typename Storage>
154void
155CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
156 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_ADDRESS6)
157 .arg(address.toText());
158
159 // Must not specify address other than IPv6.
160 if (!address.isV6()) {
161 isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
162 " for a host, specified address was " << address);
163 }
164 // Search for the Host using the reserved IPv6 address as a key.
165 const HostContainerIndex1& idx = hosts_.get<1>();
166 HostContainerIndex1Range r = idx.equal_range(address);
167 // Append each Host object to the storage.
168 for (HostContainerIndex1::iterator host = r.first; host != r.second;
169 ++host) {
171 HOSTS_CFG_GET_ALL_ADDRESS6_HOST)
172 .arg(address.toText())
173 .arg((*host)->toText());
174 storage.push_back(*host);
175 }
176
177 LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_ADDRESS6_COUNT)
178 .arg(address.toText())
179 .arg(storage.size());
180}
181
183CfgHosts::get4(const SubnetID& subnet_id,
184 const Host::IdentifierType& identifier_type,
185 const uint8_t* identifier_begin,
186 const size_t identifier_len) const {
187 return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
188 identifier_len));
189}
190
192CfgHosts::get4(const SubnetID& subnet_id,
193 const Host::IdentifierType& identifier_type,
194 const uint8_t* identifier_begin,
195 const size_t identifier_len) {
196 return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
197 identifier_len));
198}
199
201CfgHosts::get4(const SubnetID& subnet_id, const IOAddress& address) const {
202 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4)
203 .arg(subnet_id).arg(address.toText());
204
205 ConstHostCollection hosts = getAll4(address);
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)
211 .arg(subnet_id)
212 .arg(address.toText())
213 .arg((*host)->toText());
214 return (*host);
215 }
216 }
217
218 LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_NULL)
219 .arg(subnet_id).arg(address.toText());
220 return (ConstHostPtr());
221}
222
223
225CfgHosts::get6(const SubnetID& subnet_id,
226 const Host::IdentifierType& identifier_type,
227 const uint8_t* identifier_begin,
228 const size_t identifier_len) const {
229 return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
230 identifier_len));
231}
232
234CfgHosts::get6(const SubnetID& subnet_id,
235 const Host::IdentifierType& identifier_type,
236 const uint8_t* identifier_begin,
237 const size_t identifier_len) {
238 return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
239 identifier_len));
240}
241
243CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
244 return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
245}
246
248CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) {
249 return (getHostInternal6<HostPtr>(prefix, prefix_len));
250}
251
253CfgHosts::get6(const SubnetID& subnet_id,
254 const asiolink::IOAddress& address) const {
255 // Do not log here because getHostInternal6 logs.
256 return (getHostInternal6<ConstHostPtr, ConstHostCollection>(subnet_id, address));
257}
258
260CfgHosts::get6(const SubnetID& subnet_id,
261 const asiolink::IOAddress& address) {
262 // Do not log here because getHostInternal6 logs.
263 return (getHostInternal6<HostPtr, HostCollection>(subnet_id, address));
264}
265
266template<typename ReturnType, typename Storage>
267ReturnType
268CfgHosts::getHostInternal6(const SubnetID& subnet_id,
269 const asiolink::IOAddress& address) const {
270 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6)
271 .arg(subnet_id).arg(address.toText());
272
273 Storage storage;
274 getAllInternal6<Storage>(subnet_id, address, storage);
275 switch (storage.size()) {
276 case 0:
278 HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_NULL)
279 .arg(subnet_id)
280 .arg(address.toText());
281 return (HostPtr());
282
283 case 1:
285 HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_HOST)
286 .arg(subnet_id)
287 .arg(address.toText())
288 .arg((*storage.begin())->toText());
289 return (*storage.begin());
290
291 default:
292 isc_throw(DuplicateHost, "more than one reservation found"
293 " for the host belonging to the subnet with id '"
294 << subnet_id << "' and using the address '"
295 << address.toText() << "'");
296 }
297
298}
299
300template<typename ReturnType>
301ReturnType
302CfgHosts::getHostInternal6(const asiolink::IOAddress& prefix,
303 const uint8_t prefix_len) const {
304 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_PREFIX)
305 .arg(prefix.toText()).arg(static_cast<int>(prefix_len));
306
307 // Let's get all reservations that match subnet_id, address.
308 const HostContainer6Index0& idx = hosts6_.get<0>();
309 HostContainer6Index0Range r = make_pair(idx.lower_bound(prefix),
310 idx.upper_bound(prefix));
311 for (HostContainer6Index0::iterator resrv = r.first; resrv != r.second;
312 ++resrv) {
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_);
320 }
321 }
322
324 HOSTS_CFG_GET_ONE_PREFIX_NULL)
325 .arg(prefix.toText())
326 .arg(static_cast<int>(prefix_len));
327 return (ReturnType());
328}
329
330template<typename Storage>
331void
332CfgHosts::getAllInternal6(const SubnetID& subnet_id,
333 const asiolink::IOAddress& address,
334 Storage& storage) const {
335 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6)
336 .arg(subnet_id).arg(address.toText());
337
338 // Must not specify address other than IPv6.
339 if (!address.isV6()) {
340 isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
341 " for a host, specified address was " << address);
342 }
343
344 // Let's get all reservations that match subnet_id, address.
345 const HostContainer6Index1& idx = hosts6_.get<1>();
346 HostContainer6Index1Range r = make_pair(idx.lower_bound(boost::make_tuple(subnet_id, address)),
347 idx.upper_bound(boost::make_tuple(subnet_id, address)));
348
349 // For each IPv6 reservation, add the host to the results list. Fortunately,
350 // in all sane cases, there will be only one such host. (Each host can have
351 // multiple addresses reserved, but for each (address, subnet_id) there should
352 // be at most one host reserving it).
353 for(HostContainer6Index1::iterator resrv = r.first; resrv != r.second; ++resrv) {
355 HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST)
356 .arg(subnet_id)
357 .arg(address.toText())
358 .arg(resrv->host_->toText());
359 storage.push_back(resrv->host_);
360 }
361
363 HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_COUNT)
364 .arg(subnet_id)
365 .arg(address.toText())
366 .arg(storage.size());
367}
368
370CfgHosts::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 {
374
375 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER)
376 .arg(subnet6 ? "IPv6" : "IPv4")
377 .arg(subnet_id)
378 .arg(Host::getIdentifierAsText(identifier_type, identifier, identifier_len));
379
380 // Get all hosts for a specified identifier. This may return multiple hosts
381 // for different subnets, but the number of hosts returned should be low
382 // because one host presumably doesn't show up in many subnets.
383 HostCollection hosts;
384 getAllInternal<HostCollection>(identifier_type, identifier, identifier_len,
385 hosts);
386
387 HostPtr host;
388 // Iterate over the returned hosts and select those for which the
389 // subnet id matches.
390 for (HostCollection::const_iterator host_it = hosts.begin();
391 host_it != hosts.end(); ++host_it) {
392 // Check if this is IPv4 subnet or IPv6 subnet.
393 SubnetID host_subnet_id = subnet6 ? (*host_it)->getIPv6SubnetID() :
394 (*host_it)->getIPv4SubnetID();
395
396 if (subnet_id == host_subnet_id) {
397 // If this is the first occurrence of the host for this subnet,
398 // remember it. But, if we find that this is second @c Host object
399 // for the same client, it is a misconfiguration. Most likely,
400 // the administrator has specified one reservation for a HW
401 // address and another one for the DUID, which gives an ambiguous
402 // result, and we don't know which reservation we should choose.
403 // Therefore, throw an exception.
404 if (!host) {
405 host = *host_it;
406
407 } else {
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,
412 identifier,
413 identifier_len)
414 << "'");
415 }
416 }
417 }
418
419 if (host) {
421 HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST)
422 .arg(subnet_id)
423 .arg(Host::getIdentifierAsText(identifier_type, identifier,
424 identifier_len))
425 .arg(host->toText());
426
427 } else {
429 HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL)
430 .arg(subnet_id)
431 .arg(Host::getIdentifierAsText(identifier_type, identifier,
432 identifier_len));
433 }
434
435 return (host);
436}
437
438void
439CfgHosts::add(const HostPtr& host) {
440 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_ADD_HOST)
441 .arg(host ? host->toText() : "(no-host)");
442
443 // Sanity check that the host is non-null.
444 if (!host) {
445 isc_throw(BadValue, "specified host object must not be NULL when it"
446 " is added to the configuration");
447 }
448
449 // At least one subnet ID must be used
450 if (host->getIPv4SubnetID() == SUBNET_ID_UNUSED &&
451 host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
452 isc_throw(BadValue, "must not use both IPv4 and IPv6 subnet ids of"
453 " 0 when adding new host reservation");
454 }
455
456 add4(host);
457
458 add6(host);
459}
460
461void
462CfgHosts::add4(const HostPtr& host) {
463
464 HWAddrPtr hwaddr = host->getHWAddress();
465 DuidPtr duid = host->getDuid();
466
467 // There should be at least one resource reserved: hostname, IPv4
468 // address, siaddr, sname, file or IPv6 address or prefix.
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;
481 if (hwaddr) {
482 s << "for DUID: " << hwaddr->toText();
483 } else if (duid) {
484 s << "for HW address: " << duid->toText();
485 }
486 isc_throw(BadValue, "specified reservation " << s.str()
487 << " must include at least one resource, i.e. "
488 "hostname, IPv4 address, IPv6 address/prefix, "
489 "options");
490 }
491
492 // Check for duplicates for the specified IPv4 subnet.
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");
501 }
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");
509 }
510 // Check for duplicates for the specified IPv6 subnet.
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");
519 }
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");
527 }
528 }
529
530 // Check if the address is already reserved for the specified IPv4 subnet.
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");
540 }
541
542 // Check if the (identifier type, identifier) tuple is already used.
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],
546 id.size())) {
547 isc_throw(DuplicateHost, "failed to add duplicate IPv4 host using identifier: "
548 << Host::getIdentifierAsText(host->getIdentifierType(),
549 &id[0], id.size()));
550 }
551 }
552
553 // This is a new instance - add it.
554 hosts_.insert(host);
555}
556
557void
558CfgHosts::add6(const HostPtr& host) {
559
560 if (host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
561 // This is IPv4-only host. No need to add it to v6 tables.
562 return;
563 }
564
565 HWAddrPtr hwaddr = host->getHWAddress();
566 DuidPtr duid = host->getDuid();
567
568 // Get all reservations for this host.
569 IPv6ResrvRange reservations = host->getIPv6Reservations();
570
571 // Check if there are any IPv6 reservations.
572 if (std::distance(reservations.first, reservations.second) == 0) {
573 // If there aren't, we don't need to add this to hosts6_, which is used
574 // for getting hosts by their IPv6 address reservations.
575 return;
576 }
577
578 // Now for each reservation, insert corresponding (address, host) tuple.
579 for (IPv6ResrvIterator it = reservations.first; it != reservations.second;
580 ++it) {
581
582 // If there's an entry for this (subnet-id, address), reject it.
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");
591 }
592 hosts6_.insert(HostResrv6Tuple(it->second, host));
593 }
594}
595
596bool
597CfgHosts::del(const SubnetID& /*subnet_id*/, const asiolink::IOAddress& /*addr*/) {
599 isc_throw(NotImplemented, "sorry, not implemented");
600 return (false);
601}
602
603size_t
604CfgHosts::delAll4(const SubnetID& subnet_id) {
605 HostContainerIndex2& idx = hosts_.get<2>();
606 size_t erased = idx.erase(subnet_id);
607
608 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET4)
609 .arg(erased)
610 .arg(subnet_id);
611
612 return (erased);
613}
614
615bool
616CfgHosts::del4(const SubnetID& /*subnet_id*/,
617 const Host::IdentifierType& /*identifier_type*/,
618 const uint8_t* /*identifier_begin*/,
619 const size_t /*identifier_len*/) {
621 isc_throw(NotImplemented, "sorry, not implemented");
622 return (false);
623}
624
625size_t
626CfgHosts::delAll6(const SubnetID& subnet_id) {
627 // Delete IPv6 reservations.
628 HostContainer6Index2& idx6 = hosts6_.get<2>();
629 size_t erased_addresses = idx6.erase(subnet_id);
630
631 // Delete hosts.
632 HostContainerIndex3& idx = hosts_.get<3>();
633 size_t erased_hosts = idx.erase(subnet_id);
634
635 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET6)
636 .arg(erased_hosts)
637 .arg(erased_addresses)
638 .arg(subnet_id);
639
640 return (erased_hosts);
641}
642
643bool
644CfgHosts::del6(const SubnetID& /*subnet_id*/,
645 const Host::IdentifierType& /*identifier_type*/,
646 const uint8_t* /*identifier_begin*/,
647 const size_t /*identifier_len*/) {
649 isc_throw(NotImplemented, "sorry, not implemented");
650 return (false);
651}
652
655 uint16_t family = CfgMgr::instance().getFamily();
656 if (family == AF_INET) {
657 return (toElement4());
658 } else if (family == AF_INET6) {
659 return (toElement6());
660 } else {
661 isc_throw(ToElementError, "CfgHosts::toElement: unknown "
662 "address family: " << family);
663 }
664}
665
667CfgHosts::toElement4() const {
668 CfgHostsList result;
669 // Iterate using arbitrary the index 0
670 const HostContainerIndex0& idx = hosts_.get<0>();
671 for (HostContainerIndex0::const_iterator host = idx.begin();
672 host != idx.end(); ++host) {
673
674 // Convert host to element representation
675 ElementPtr map = (*host)->toElement4();
676
677 // Push it on the list
678 SubnetID subnet_id = (*host)->getIPv4SubnetID();
679 result.add(subnet_id, map);
680 }
681 return (result.externalize());
682}
683
685CfgHosts::toElement6() const {
686 CfgHostsList result;
687 // Iterate using arbitrary the index 0
688 const HostContainerIndex0& idx = hosts_.get<0>();
689 for (HostContainerIndex0::const_iterator host = idx.begin();
690 host != idx.end(); ++host) {
691
692 // Convert host to Element representation
693 ElementPtr map = (*host)->toElement6();
694
695 // Push it on the list
696 SubnetID subnet_id = (*host)->getIPv6SubnetID();
697 result.add(subnet_id, map);
698 }
699 return (result.externalize());
700}
701
702} // end of namespace isc::dhcp
703} // end of namespace isc
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.
Cannot unparse error.
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.
Definition: cfg_hosts.cc:604
virtual void add(const HostPtr &host)
Adds a new host to the collection.
Definition: cfg_hosts.cc:439
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)
Definition: cfg_hosts.cc:616
virtual ConstHostCollection getAll6(const asiolink::IOAddress &address) const
Returns a collection of hosts using the specified IPv6 address.
Definition: cfg_hosts.cc:68
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr)
Attempts to delete a host by address.
Definition: cfg_hosts.cc:597
virtual ConstHostCollection getAll4(const asiolink::IOAddress &address) const
Returns a collection of hosts using the specified IPv4 address.
Definition: cfg_hosts.cc:50
virtual size_t delAll6(const SubnetID &subnet_id)
Attempts to delete all hosts for a given IPv6 subnet.
Definition: cfg_hosts.cc:626
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.
Definition: cfg_hosts.cc:225
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)
Definition: cfg_hosts.cc:644
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.
Definition: cfg_hosts.cc:183
isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: cfg_hosts.cc:654
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...
Definition: cfg_hosts.cc:27
uint16_t getFamily() const
Returns address family.
Definition: cfgmgr.h:242
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
Exception thrown when the duplicate Host object is detected.
IdentifierType
Type of the host identifier.
Definition: host.h:252
@ IDENT_HWADDR
Definition: host.h:253
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
Definition: host.cc:239
#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.
Definition: macros.h:14
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
Definition: host.h:186
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.
Definition: hosts_log.h:51
std::pair< HostContainer6Index1::iterator, HostContainer6Index1::iterator > HostContainer6Index1Range
Results range returned using the HostContainer6Index1.
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition: host.h:725
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Definition: host.h:731
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:21
HostContainer6::nth_index< 0 >::type HostContainer6Index0
First index type in the HostContainer6.
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
Definition: host.h:188
HostContainer6::nth_index< 1 >::type HostContainer6Index1
Second index type in the HostContainer6.
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:734
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
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.
Definition: hosts_log.h:27
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
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.
Definition: host.h:728
HostContainer::nth_index< 0 >::type HostContainerIndex0
First index type in the HostContainer.
const int HOSTS_DBG_TRACE_DETAIL_DATA
Records detailed results of lookups.
Definition: hosts_log.h:43
const int HOSTS_DBG_RESULTS
Records the results of the lookups.
Definition: hosts_log.h:33
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.