Kea 2.2.0
cfg_hosts.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2020 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 SubnetID& subnet_id) const {
51 // Do not issue logging message here because it will be logged by
52 // the getAllInternal4 method.
53 ConstHostCollection collection;
54 getAllInternal4<ConstHostCollection>(subnet_id, collection);
55 return (collection);
56}
57
59CfgHosts::getAll4(const SubnetID& subnet_id) {
60 // Do not issue logging message here because it will be logged by
61 // the getAllInternal4 method.
62 HostCollection collection;
63 getAllInternal4<HostCollection>(subnet_id, collection);
64 return (collection);
65}
66
68CfgHosts::getAll6(const SubnetID& subnet_id) const {
69 // Do not issue logging message here because it will be logged by
70 // the getAllInternal6 method.
71 ConstHostCollection collection;
72 getAllInternal6<ConstHostCollection>(subnet_id, collection);
73 return (collection);
74}
75
77CfgHosts::getAll6(const SubnetID& subnet_id) {
78 // Do not issue logging message here because it will be logged by
79 // the getAllInternal6 method.
80 HostCollection collection;
81 getAllInternal6<HostCollection>(subnet_id, collection);
82 return (collection);
83}
84
86CfgHosts::getAllbyHostname(const std::string& hostname) const {
87 // Do not issue logging message here because it will be logged by
88 // the getAllbyHostnameInternal method.
89 ConstHostCollection collection;
90 getAllbyHostnameInternal<ConstHostCollection>(hostname, collection);
91 return (collection);
92}
93
95CfgHosts::getAllbyHostname(const std::string& hostname) {
96 // Do not issue logging message here because it will be logged by
97 // the getAllbyHostnameInternal method.
98 HostCollection collection;
99 getAllbyHostnameInternal<HostCollection>(hostname, collection);
100 return (collection);
101}
102
104CfgHosts::getAllbyHostname4(const std::string& hostname,
105 const SubnetID& subnet_id) const {
106 // Do not issue logging message here because it will be logged by
107 // the getAllbyHostnameInternal4 method.
108 ConstHostCollection collection;
109 getAllbyHostnameInternal4<ConstHostCollection>(hostname, subnet_id, collection);
110 return (collection);
111}
112
114CfgHosts::getAllbyHostname4(const std::string& hostname,
115 const SubnetID& subnet_id) {
116 // Do not issue logging message here because it will be logged by
117 // the getAllbyHostnameInternal4 method.
118 HostCollection collection;
119 getAllbyHostnameInternal4<HostCollection>(hostname, subnet_id, collection);
120 return (collection);
121}
122
124CfgHosts::getAllbyHostname6(const std::string& hostname,
125 const SubnetID& subnet_id) const {
126 // Do not issue logging message here because it will be logged by
127 // the getAllbyHostnameInternal6 method.
128 ConstHostCollection collection;
129 getAllbyHostnameInternal6<ConstHostCollection>(hostname, subnet_id, collection);
130 return (collection);
131}
132
134CfgHosts::getAllbyHostname6(const std::string& hostname,
135 const SubnetID& subnet_id) {
136 // Do not issue logging message here because it will be logged by
137 // the getAllbyHostnameInternal6 method.
138 HostCollection collection;
139 getAllbyHostnameInternal6<HostCollection>(hostname, subnet_id, collection);
140 return (collection);
141}
142
145 size_t& /*source_index*/,
146 uint64_t lower_host_id,
147 const HostPageSize& page_size) const {
148 // Do not issue logging message here because it will be logged by
149 // the getPageInternal4 method.
150 ConstHostCollection collection;
151 getPageInternal4<ConstHostCollection>(subnet_id,
152 lower_host_id,
153 page_size,
154 collection);
155 return (collection);
156}
157
160 size_t& /*source_index*/,
161 uint64_t lower_host_id,
162 const HostPageSize& page_size) {
163 // Do not issue logging message here because it will be logged by
164 // the getPageInternal4 method.
165 HostCollection collection;
166 getPageInternal4<HostCollection>(subnet_id,
167 lower_host_id,
168 page_size,
169 collection);
170 return (collection);
171}
172
175 size_t& /*source_index*/,
176 uint64_t lower_host_id,
177 const HostPageSize& page_size) const {
178 // Do not issue logging message here because it will be logged by
179 // the getPageInternal6 method.
180 ConstHostCollection collection;
181 getPageInternal6<ConstHostCollection>(subnet_id,
182 lower_host_id,
183 page_size,
184 collection);
185 return (collection);
186}
187
190 size_t& /*source_index*/,
191 uint64_t lower_host_id,
192 const HostPageSize& page_size) {
193 // Do not issue logging message here because it will be logged by
194 // the getPageInternal6 method.
195 HostCollection collection;
196 getPageInternal6<HostCollection>(subnet_id,
197 lower_host_id,
198 page_size,
199 collection);
200 return (collection);
201}
202
204CfgHosts::getPage4(size_t& /*source_index*/,
205 uint64_t lower_host_id,
206 const HostPageSize& page_size) const {
207 // Do not issue logging message here because it will be logged by
208 // the getPageInternal method.
209 ConstHostCollection collection;
210 getPageInternal<ConstHostCollection>(lower_host_id,
211 page_size,
212 collection);
213 return (collection);
214}
215
217CfgHosts::getPage4(size_t& /*source_index*/,
218 uint64_t lower_host_id,
219 const HostPageSize& page_size) {
220 // Do not issue logging message here because it will be logged by
221 // the getPageInternal method.
222 HostCollection collection;
223 getPageInternal<HostCollection>(lower_host_id,
224 page_size,
225 collection);
226 return (collection);
227}
228
230CfgHosts::getPage6(size_t& /*source_index*/,
231 uint64_t lower_host_id,
232 const HostPageSize& page_size) const {
233 // Do not issue logging message here because it will be logged by
234 // the getPageInternal method.
235 ConstHostCollection collection;
236 getPageInternal<ConstHostCollection>(lower_host_id,
237 page_size,
238 collection);
239 return (collection);
240}
241
243CfgHosts::getPage6(size_t& /*source_index*/,
244 uint64_t lower_host_id,
245 const HostPageSize& page_size) {
246 // Do not issue logging message here because it will be logged by
247 // the getPageInternal method.
248 HostCollection collection;
249 getPageInternal<HostCollection>(lower_host_id,
250 page_size,
251 collection);
252 return (collection);
253}
254
256CfgHosts::getAll4(const IOAddress& address) const {
257 // Do not issue logging message here because it will be logged by
258 // the getAllInternal4 method.
259 ConstHostCollection collection;
260 getAllInternal4<ConstHostCollection>(address, collection);
261 return (collection);
262}
263
266 // Do not issue logging message here because it will be logged by
267 // the getAllInternal4 method.
268 HostCollection collection;
269 getAllInternal4<HostCollection>(address, collection);
270 return (collection);
271}
272
274CfgHosts::getAll6(const IOAddress& address) const {
275 // Do not issue logging message here because it will be logged by
276 // the getAllInternal6 method.
277 ConstHostCollection collection;
278 getAllInternal6<ConstHostCollection>(address, collection);
279 return (collection);
280}
281
284 // Do not issue logging message here because it will be logged by
285 // the getAllInternal6 method.
286 HostCollection collection;
287 getAllInternal6<HostCollection>(address, collection);
288 return (collection);
289}
290
291template<typename Storage>
292void
293CfgHosts::getAllInternal(const Host::IdentifierType& identifier_type,
294 const uint8_t* identifier,
295 const size_t identifier_len,
296 Storage& storage) const {
297
298 // Convert host identifier into textual format for logging purposes.
299 // This conversion is exception free.
300 std::string identifier_text = Host::getIdentifierAsText(identifier_type,
301 identifier,
302 identifier_len);
304 .arg(identifier_text);
305
306 // Use the identifier and identifier type as a composite key.
307 const HostContainerIndex0& idx = hosts_.get<0>();
308 boost::tuple<const std::vector<uint8_t>, const Host::IdentifierType> t =
309 boost::make_tuple(std::vector<uint8_t>(identifier,
310 identifier + identifier_len),
311 identifier_type);
312
313 // Append each Host object to the storage.
314 for (HostContainerIndex0::iterator host = idx.lower_bound(t);
315 host != idx.upper_bound(t);
316 ++host) {
319 .arg(identifier_text)
320 .arg((*host)->toText());
321 storage.push_back(*host);
322 }
323
324 // Log how many hosts have been found.
326 .arg(identifier_text)
327 .arg(storage.size());
328}
329
330template<typename Storage>
331void
332CfgHosts::getAllInternal4(const SubnetID& subnet_id,
333 Storage& storage) const {
334
336 .arg(subnet_id);
337
338 // Use try DHCPv4 subnet id.
339 const HostContainerIndex2& idx = hosts_.get<2>();
340
341 // Append each Host object to the storage.
342 for (HostContainerIndex2::iterator host = idx.lower_bound(subnet_id);
343 host != idx.upper_bound(subnet_id);
344 ++host) {
347 .arg(subnet_id)
348 .arg((*host)->toText());
349 storage.push_back(*host);
350 }
351
352 // Log how many hosts have been found.
354 .arg(subnet_id)
355 .arg(storage.size());
356}
357
358template<typename Storage>
359void
360CfgHosts::getAllInternal6(const SubnetID& subnet_id,
361 Storage& storage) const {
362
364 .arg(subnet_id);
365
366 // Use try DHCPv6 subnet id.
367 const HostContainerIndex3& idx = hosts_.get<3>();
368
369 // Append each Host object to the storage.
370 for (HostContainerIndex3::iterator host = idx.lower_bound(subnet_id);
371 host != idx.upper_bound(subnet_id);
372 ++host) {
375 .arg(subnet_id)
376 .arg((*host)->toText());
377 storage.push_back(*host);
378 }
379
380 // Log how many hosts have been found.
382 .arg(subnet_id)
383 .arg(storage.size());
384}
385
386template<typename Storage>
387void
388CfgHosts::getAllbyHostnameInternal(const std::string& hostname,
389 Storage& storage) const {
390
392 .arg(hostname);
393
394 // Use try hostname.
395 const HostContainerIndex5& idx = hosts_.get<5>();
396
397 // Append each Host object to the storage.
398 for (HostContainerIndex5::iterator host = idx.lower_bound(hostname);
399 host != idx.upper_bound(hostname);
400 ++host) {
403 .arg(hostname)
404 .arg((*host)->toText());
405 storage.push_back(*host);
406 }
407
408 // Log how many hosts have been found.
410 .arg(hostname)
411 .arg(storage.size());
412}
413
414template<typename Storage>
415void
416CfgHosts::getAllbyHostnameInternal4(const std::string& hostname,
417 const SubnetID& subnet_id,
418 Storage& storage) const {
419
422 .arg(hostname)
423 .arg(subnet_id);
424
425 // Use try hostname.
426 const HostContainerIndex5& idx = hosts_.get<5>();
427
428 // Append each Host object to the storage.
429 for (HostContainerIndex5::iterator host = idx.lower_bound(hostname);
430 host != idx.upper_bound(hostname);
431 ++host) {
432 if ((*host)->getIPv4SubnetID() != subnet_id) {
433 continue;
434 }
437 .arg(hostname)
438 .arg(subnet_id)
439 .arg((*host)->toText());
440 storage.push_back(*host);
441 }
442
443 // Log how many hosts have been found.
446 .arg(hostname)
447 .arg(subnet_id)
448 .arg(storage.size());
449}
450
451template<typename Storage>
452void
453CfgHosts::getAllbyHostnameInternal6(const std::string& hostname,
454 const SubnetID& subnet_id,
455 Storage& storage) const {
456
459 .arg(hostname)
460 .arg(subnet_id);
461
462 // Use try hostname.
463 const HostContainerIndex5& idx = hosts_.get<5>();
464
465 // Append each Host object to the storage.
466 for (HostContainerIndex5::iterator host = idx.lower_bound(hostname);
467 host != idx.upper_bound(hostname);
468 ++host) {
469 if ((*host)->getIPv6SubnetID() != subnet_id) {
470 continue;
471 }
474 .arg(hostname)
475 .arg(subnet_id)
476 .arg((*host)->toText());
477 storage.push_back(*host);
478 }
479
480 // Log how many hosts have been found.
483 .arg(hostname)
484 .arg(subnet_id)
485 .arg(storage.size());
486}
487
488template<typename Storage>
489void
490CfgHosts::getPageInternal(uint64_t lower_host_id,
491 const HostPageSize& page_size,
492 Storage& storage) const {
493
495
496 // Use the host id last index.
497 const HostContainerIndex4& idx = hosts_.get<4>();
498 HostContainerIndex4::const_iterator host = idx.lower_bound(lower_host_id);
499
500 // Exclude the lower bound id when it is not zero.
501 if (lower_host_id &&
502 (host != idx.end()) && ((*host)->getHostId() == lower_host_id)) {
503 ++host;
504 }
505
506 // Return hosts within the page size.
507 for (; host != idx.end(); ++host) {
510 .arg((*host)->toText());
511 storage.push_back(*host);
512 if (storage.size() >= page_size.page_size_) {
513 break;
514 }
515 }
516
517 // Log how many hosts have been found.
519 .arg(storage.size());
520}
521
522template<typename Storage>
523void
524CfgHosts::getPageInternal4(const SubnetID& subnet_id,
525 uint64_t lower_host_id,
526 const HostPageSize& page_size,
527 Storage& storage) const {
528
530 .arg(subnet_id);
531
532 // Use the host id last index.
533 const HostContainerIndex4& idx = hosts_.get<4>();
534 HostContainerIndex4::const_iterator host = idx.lower_bound(lower_host_id);
535
536 // Exclude the lower bound id when it is not zero.
537 if (lower_host_id &&
538 (host != idx.end()) && ((*host)->getHostId() == lower_host_id)) {
539 ++host;
540 }
541
542 // Return hosts in the subnet within the page size.
543 for (; host != idx.end(); ++host) {
544 if ((*host)->getIPv4SubnetID() != subnet_id) {
545 continue;
546 }
549 .arg(subnet_id)
550 .arg((*host)->toText());
551 storage.push_back(*host);
552 if (storage.size() >= page_size.page_size_) {
553 break;
554 }
555 }
556
557 // Log how many hosts have been found.
559 .arg(subnet_id)
560 .arg(storage.size());
561}
562
563template<typename Storage>
564void
565CfgHosts::getPageInternal6(const SubnetID& subnet_id,
566 uint64_t lower_host_id,
567 const HostPageSize& page_size,
568 Storage& storage) const {
569
571 .arg(subnet_id);
572
573 // Use the host id last index.
574 const HostContainerIndex4& idx = hosts_.get<4>();
575 HostContainerIndex4::const_iterator host = idx.lower_bound(lower_host_id);
576
577 // Exclude the lower bound id when it is not zero.
578 if (lower_host_id &&
579 (host != idx.end()) && ((*host)->getHostId() == lower_host_id)) {
580 ++host;
581 }
582
583 // Return hosts in the subnet within the page size.
584 for (; host != idx.end(); ++host) {
585 if ((*host)->getIPv6SubnetID() != subnet_id) {
586 continue;
587 }
590 .arg(subnet_id)
591 .arg((*host)->toText());
592 storage.push_back(*host);
593 if (storage.size() >= page_size.page_size_) {
594 break;
595 }
596 }
597
598 // Log how many hosts have been found.
600 .arg(subnet_id)
601 .arg(storage.size());
602}
603
604
605template<typename Storage>
606void
607CfgHosts::getAllInternal4(const IOAddress& address, Storage& storage) const {
609 .arg(address.toText());
610
611 // Must not specify address other than IPv4.
612 if (!address.isV4()) {
613 isc_throw(BadHostAddress, "must specify an IPv4 address when searching"
614 " for a host, specified address was " << address);
615 }
616 // Search for the Host using the reserved IPv4 address as a key.
617 const HostContainerIndex1& idx = hosts_.get<1>();
618 HostContainerIndex1Range r = idx.equal_range(address);
619 // Append each Host object to the storage.
620 for (HostContainerIndex1::iterator host = r.first; host != r.second;
621 ++host) {
624 .arg(address.toText())
625 .arg((*host)->toText());
626 storage.push_back(*host);
627 }
628
630 .arg(address.toText())
631 .arg(storage.size());
632}
633
634template<typename Storage>
635void
636CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
638 .arg(address.toText());
639
640 // Must not specify address other than IPv6.
641 if (!address.isV6()) {
642 isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
643 " for a host, specified address was " << address);
644 }
645 // Search for the Host using the reserved IPv6 address as a key.
646 const HostContainerIndex1& idx = hosts_.get<1>();
647 HostContainerIndex1Range r = idx.equal_range(address);
648 // Append each Host object to the storage.
649 for (HostContainerIndex1::iterator host = r.first; host != r.second;
650 ++host) {
653 .arg(address.toText())
654 .arg((*host)->toText());
655 storage.push_back(*host);
656 }
657
659 .arg(address.toText())
660 .arg(storage.size());
661}
662
664CfgHosts::get4(const SubnetID& subnet_id,
665 const Host::IdentifierType& identifier_type,
666 const uint8_t* identifier_begin,
667 const size_t identifier_len) const {
668 return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
669 identifier_len));
670}
671
673CfgHosts::get4(const SubnetID& subnet_id,
674 const Host::IdentifierType& identifier_type,
675 const uint8_t* identifier_begin,
676 const size_t identifier_len) {
677 return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
678 identifier_len));
679}
680
682CfgHosts::get4(const SubnetID& subnet_id, const IOAddress& address) const {
684 .arg(subnet_id).arg(address.toText());
685
686 ConstHostCollection hosts = getAll4(address);
687 for (ConstHostCollection::const_iterator host = hosts.begin();
688 host != hosts.end(); ++host) {
689 if ((*host)->getIPv4SubnetID() == subnet_id) {
692 .arg(subnet_id)
693 .arg(address.toText())
694 .arg((*host)->toText());
695 return (*host);
696 }
697 }
698
700 .arg(subnet_id).arg(address.toText());
701 return (ConstHostPtr());
702}
703
706 const asiolink::IOAddress& address) const {
708 .arg(subnet_id).arg(address.toText());
709
711 for (auto host : getAll4(address)) {
712 if (host->getIPv4SubnetID() == subnet_id) {
715 .arg(subnet_id)
716 .arg(address.toText())
717 .arg(host->toText());
718 hosts.push_back(host);
719 }
720 }
722 .arg(subnet_id)
723 .arg(address.toText())
724 .arg(hosts.size());
725
726 return (hosts);
727}
728
730CfgHosts::get6(const SubnetID& subnet_id,
731 const Host::IdentifierType& identifier_type,
732 const uint8_t* identifier_begin,
733 const size_t identifier_len) const {
734 return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
735 identifier_len));
736}
737
739CfgHosts::get6(const SubnetID& subnet_id,
740 const Host::IdentifierType& identifier_type,
741 const uint8_t* identifier_begin,
742 const size_t identifier_len) {
743 return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
744 identifier_len));
745}
746
748CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
749 return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
750}
751
753CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) {
754 return (getHostInternal6<HostPtr>(prefix, prefix_len));
755}
756
758CfgHosts::get6(const SubnetID& subnet_id,
759 const asiolink::IOAddress& address) const {
760 // Do not log here because getHostInternal6 logs.
761 return (getHostInternal6<ConstHostPtr, ConstHostCollection>(subnet_id, address));
762}
763
765CfgHosts::get6(const SubnetID& subnet_id,
766 const asiolink::IOAddress& address) {
767 // Do not log here because getHostInternal6 logs.
768 return (getHostInternal6<HostPtr, HostCollection>(subnet_id, address));
769}
770
773 const asiolink::IOAddress& address) const {
775 getAllInternal6(subnet_id, address, hosts);
776 return (hosts);
777}
778
779template<typename ReturnType, typename Storage>
780ReturnType
781CfgHosts::getHostInternal6(const SubnetID& subnet_id,
782 const asiolink::IOAddress& address) const {
784 .arg(subnet_id).arg(address.toText());
785
786 Storage storage;
787 getAllInternal6<Storage>(subnet_id, address, storage);
788 switch (storage.size()) {
789 case 0:
792 .arg(subnet_id)
793 .arg(address.toText());
794 return (HostPtr());
795
796 case 1:
799 .arg(subnet_id)
800 .arg(address.toText())
801 .arg((*storage.begin())->toText());
802 return (*storage.begin());
803
804 default:
805 isc_throw(DuplicateHost, "more than one reservation found"
806 " for the host belonging to the subnet with id '"
807 << subnet_id << "' and using the address '"
808 << address.toText() << "'");
809 }
810
811}
812
813template<typename ReturnType>
814ReturnType
815CfgHosts::getHostInternal6(const asiolink::IOAddress& prefix,
816 const uint8_t prefix_len) const {
818 .arg(prefix.toText()).arg(static_cast<int>(prefix_len));
819
820 // Let's get all reservations that match subnet_id, address.
821 const HostContainer6Index0& idx = hosts6_.get<0>();
822 HostContainer6Index0Range r = make_pair(idx.lower_bound(prefix),
823 idx.upper_bound(prefix));
824 for (HostContainer6Index0::iterator resrv = r.first; resrv != r.second;
825 ++resrv) {
826 if (resrv->resrv_.getPrefixLen() == prefix_len) {
829 .arg(prefix.toText())
830 .arg(static_cast<int>(prefix_len))
831 .arg(resrv->host_->toText());
832 return (resrv->host_);
833 }
834 }
835
838 .arg(prefix.toText())
839 .arg(static_cast<int>(prefix_len));
840 return (ReturnType());
841}
842
843template<typename Storage>
844void
845CfgHosts::getAllInternal6(const SubnetID& subnet_id,
846 const asiolink::IOAddress& address,
847 Storage& storage) const {
849 .arg(subnet_id).arg(address.toText());
850
851 // Must not specify address other than IPv6.
852 if (!address.isV6()) {
853 isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
854 " for a host, specified address was " << address);
855 }
856
857 // Let's get all reservations that match subnet_id, address.
858 const HostContainer6Index1& idx = hosts6_.get<1>();
859 HostContainer6Index1Range r = make_pair(idx.lower_bound(boost::make_tuple(subnet_id, address)),
860 idx.upper_bound(boost::make_tuple(subnet_id, address)));
861
862 // For each IPv6 reservation, add the host to the results list. Fortunately,
863 // in all sane cases, there will be only one such host. (Each host can have
864 // multiple addresses reserved, but for each (address, subnet_id) there should
865 // be at most one host reserving it).
866 for(HostContainer6Index1::iterator resrv = r.first; resrv != r.second; ++resrv) {
869 .arg(subnet_id)
870 .arg(address.toText())
871 .arg(resrv->host_->toText());
872 storage.push_back(resrv->host_);
873 }
874
877 .arg(subnet_id)
878 .arg(address.toText())
879 .arg(storage.size());
880}
881
883CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
884 const Host::IdentifierType& identifier_type,
885 const uint8_t* identifier,
886 const size_t identifier_len) const {
887
889 .arg(subnet6 ? "IPv6" : "IPv4")
890 .arg(subnet_id)
891 .arg(Host::getIdentifierAsText(identifier_type, identifier, identifier_len));
892
893 // Get all hosts for a specified identifier. This may return multiple hosts
894 // for different subnets, but the number of hosts returned should be low
895 // because one host presumably doesn't show up in many subnets.
896 HostCollection hosts;
897 getAllInternal<HostCollection>(identifier_type, identifier, identifier_len,
898 hosts);
899
900 HostPtr host;
901 // Iterate over the returned hosts and select those for which the
902 // subnet id matches.
903 for (HostCollection::const_iterator host_it = hosts.begin();
904 host_it != hosts.end(); ++host_it) {
905 // Check if this is IPv4 subnet or IPv6 subnet.
906 SubnetID host_subnet_id = subnet6 ? (*host_it)->getIPv6SubnetID() :
907 (*host_it)->getIPv4SubnetID();
908
909 if (subnet_id == host_subnet_id) {
910 // If this is the first occurrence of the host for this subnet,
911 // remember it. But, if we find that this is second @c Host object
912 // for the same client, it is a misconfiguration. Most likely,
913 // the administrator has specified one reservation for a HW
914 // address and another one for the DUID, which gives an ambiguous
915 // result, and we don't know which reservation we should choose.
916 // Therefore, throw an exception.
917 if (!host) {
918 host = *host_it;
919
920 } else {
921 isc_throw(DuplicateHost, "more than one reservation found"
922 " for the host belonging to the subnet with id '"
923 << subnet_id << "' and using the identifier '"
924 << Host::getIdentifierAsText(identifier_type,
925 identifier,
926 identifier_len)
927 << "'");
928 }
929 }
930 }
931
932 if (host) {
935 .arg(subnet_id)
936 .arg(Host::getIdentifierAsText(identifier_type, identifier,
937 identifier_len))
938 .arg(host->toText());
939
940 } else {
943 .arg(subnet_id)
944 .arg(Host::getIdentifierAsText(identifier_type, identifier,
945 identifier_len));
946 }
947
948 return (host);
949}
950
951void
952CfgHosts::add(const HostPtr& host) {
954 .arg(host ? host->toText() : "(no-host)");
955
956 // Sanity check that the host is non-null.
957 if (!host) {
958 isc_throw(BadValue, "specified host object must not be NULL when it"
959 " is added to the configuration");
960 }
961
962 // At least one subnet ID must be used
963 if (host->getIPv4SubnetID() == SUBNET_ID_UNUSED &&
964 host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
965 isc_throw(BadValue, "must not use both IPv4 and IPv6 subnet ids of"
966 " 0 when adding new host reservation");
967 }
968
969 add4(host);
970
971 add6(host);
972}
973
974void
975CfgHosts::add4(const HostPtr& host) {
976
977 HWAddrPtr hwaddr = host->getHWAddress();
978 DuidPtr duid = host->getDuid();
979
980 // There should be at least one resource reserved: hostname, IPv4
981 // address, siaddr, sname, file or IPv6 address or prefix.
983 if (host->getHostname().empty() &&
984 (host->getIPv4Reservation().isV4Zero()) &&
985 !host->hasIPv6Reservation() &&
986 host->getNextServer().isV4Zero() &&
987 host->getServerHostname().empty() &&
988 host->getBootFileName().empty() &&
989 host->getCfgOption4()->empty() &&
990 host->getCfgOption6()->empty() &&
991 host->getClientClasses4().empty() &&
992 host->getClientClasses6().empty()) {
993 std::ostringstream s;
994 if (hwaddr) {
995 s << "for DUID: " << hwaddr->toText();
996 } else if (duid) {
997 s << "for HW address: " << duid->toText();
998 }
999 isc_throw(BadValue, "specified reservation " << s.str()
1000 << " must include at least one resource, i.e. "
1001 "hostname, IPv4 address, IPv6 address/prefix, "
1002 "options");
1003 }
1004
1005 // Check for duplicates for the specified IPv4 subnet.
1006 if (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) {
1007 if (hwaddr && !hwaddr->hwaddr_.empty() &&
1008 get4(host->getIPv4SubnetID(), Host::IDENT_HWADDR,
1009 &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
1010 isc_throw(DuplicateHost, "failed to add new host using the HW"
1011 << " address '" << hwaddr->toText(false)
1012 << "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
1013 << "' as this host has already been added");
1014 }
1015 if (duid && !duid->getDuid().empty() &&
1016 get4(host->getIPv4SubnetID(), Host::IDENT_DUID,
1017 &duid->getDuid()[0], duid->getDuid().size())) {
1018 isc_throw(DuplicateHost, "failed to add new host using the "
1019 << "DUID '" << duid->toText()
1020 << "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
1021 << "' as this host has already been added");
1022 }
1023 // Check for duplicates for the specified IPv6 subnet.
1024 } else if (host->getIPv6SubnetID() != SUBNET_ID_UNUSED) {
1025 if (duid && !duid->getDuid().empty() &&
1026 get6(host->getIPv6SubnetID(), Host::IDENT_DUID,
1027 &duid->getDuid()[0], duid->getDuid().size())) {
1028 isc_throw(DuplicateHost, "failed to add new host using the "
1029 << "DUID '" << duid->toText()
1030 << "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
1031 << "' as this host has already been added");
1032 }
1033 if (hwaddr && !hwaddr->hwaddr_.empty() &&
1034 get6(host->getIPv6SubnetID(), Host::IDENT_HWADDR,
1035 &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
1036 isc_throw(DuplicateHost, "failed to add new host using the HW"
1037 << " address '" << hwaddr->toText(false)
1038 << "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
1039 << "' as this host has already been added");
1040 }
1041 }
1042
1043 // Check if the address is already reserved for the specified IPv4 subnet.
1044 if (ip_reservations_unique_ && !host->getIPv4Reservation().isV4Zero() &&
1045 (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) &&
1046 get4(host->getIPv4SubnetID(), host->getIPv4Reservation())) {
1047 isc_throw(ReservedAddress, "failed to add new host using the HW"
1048 " address '" << (hwaddr ? hwaddr->toText(false) : "(null)")
1049 << " and DUID '" << (duid ? duid->toText() : "(null)")
1050 << "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
1051 << "' for the address " << host->getIPv4Reservation()
1052 << ": There's already a reservation for this address");
1053 }
1054
1055 // Check if the (identifier type, identifier) tuple is already used.
1056 const std::vector<uint8_t>& id = host->getIdentifier();
1057 if ((host->getIPv4SubnetID() != SUBNET_ID_UNUSED) && !id.empty()) {
1058 if (get4(host->getIPv4SubnetID(), host->getIdentifierType(), &id[0],
1059 id.size())) {
1060 isc_throw(DuplicateHost, "failed to add duplicate IPv4 host using identifier: "
1061 << Host::getIdentifierAsText(host->getIdentifierType(),
1062 &id[0], id.size()));
1063 }
1064 }
1065
1066 // This is a new instance - add it.
1067 host->setHostId(++next_host_id_);
1068 hosts_.insert(host);
1069}
1070
1071void
1072CfgHosts::add6(const HostPtr& host) {
1073
1074 if (host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
1075 // This is IPv4-only host. No need to add it to v6 tables.
1076 return;
1077 }
1078
1079 HWAddrPtr hwaddr = host->getHWAddress();
1080 DuidPtr duid = host->getDuid();
1081
1082 // Get all reservations for this host.
1083 IPv6ResrvRange reservations = host->getIPv6Reservations();
1084
1085 // Check if there are any IPv6 reservations.
1086 if (std::distance(reservations.first, reservations.second) == 0) {
1087 // If there aren't, we don't need to add this to hosts6_, which is used
1088 // for getting hosts by their IPv6 address reservations.
1089 return;
1090 }
1091
1092 // Now for each reservation, insert corresponding (address, host) tuple.
1093 for (IPv6ResrvIterator it = reservations.first; it != reservations.second;
1094 ++it) {
1095
1096 if (ip_reservations_unique_) {
1097 // If there's an entry for this (subnet-id, address), reject it.
1098 if (get6(host->getIPv6SubnetID(), it->second.getPrefix())) {
1099 isc_throw(DuplicateHost, "failed to add address reservation for "
1100 << "host using the HW address '"
1101 << (hwaddr ? hwaddr->toText(false) : "(null)")
1102 << " and DUID '" << (duid ? duid->toText() : "(null)")
1103 << "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
1104 << "' for address/prefix " << it->second.getPrefix()
1105 << ": There's already reservation for this address/prefix");
1106 }
1107 }
1108 hosts6_.insert(HostResrv6Tuple(it->second, host));
1109 }
1110}
1111
1112bool
1113CfgHosts::del(const SubnetID& /*subnet_id*/, const asiolink::IOAddress& /*addr*/) {
1115 isc_throw(NotImplemented, "sorry, not implemented");
1116 return (false);
1117}
1118
1119size_t
1120CfgHosts::delAll4(const SubnetID& subnet_id) {
1121 HostContainerIndex2& idx = hosts_.get<2>();
1122 size_t erased = idx.erase(subnet_id);
1123
1125 .arg(erased)
1126 .arg(subnet_id);
1127
1128 return (erased);
1129}
1130
1131bool
1132CfgHosts::del4(const SubnetID& /*subnet_id*/,
1133 const Host::IdentifierType& /*identifier_type*/,
1134 const uint8_t* /*identifier_begin*/,
1135 const size_t /*identifier_len*/) {
1137 isc_throw(NotImplemented, "sorry, not implemented");
1138 return (false);
1139}
1140
1141size_t
1142CfgHosts::delAll6(const SubnetID& subnet_id) {
1143 // Delete IPv6 reservations.
1144 HostContainer6Index2& idx6 = hosts6_.get<2>();
1145 size_t erased_addresses = idx6.erase(subnet_id);
1146
1147 // Delete hosts.
1148 HostContainerIndex3& idx = hosts_.get<3>();
1149 size_t erased_hosts = idx.erase(subnet_id);
1150
1152 .arg(erased_hosts)
1153 .arg(erased_addresses)
1154 .arg(subnet_id);
1155
1156 return (erased_hosts);
1157}
1158
1159bool
1160CfgHosts::del6(const SubnetID& /*subnet_id*/,
1161 const Host::IdentifierType& /*identifier_type*/,
1162 const uint8_t* /*identifier_begin*/,
1163 const size_t /*identifier_len*/) {
1165 isc_throw(NotImplemented, "sorry, not implemented");
1166 return (false);
1167}
1168
1169bool
1171 ip_reservations_unique_ = unique;
1172 return (true);
1173}
1174
1175
1178 uint16_t family = CfgMgr::instance().getFamily();
1179 if (family == AF_INET) {
1180 return (toElement4());
1181 } else if (family == AF_INET6) {
1182 return (toElement6());
1183 } else {
1184 isc_throw(ToElementError, "CfgHosts::toElement: unknown "
1185 "address family: " << family);
1186 }
1187}
1188
1190CfgHosts::toElement4() const {
1191 CfgHostsList result;
1192 // Iterate using arbitrary the index 0
1193 const HostContainerIndex0& idx = hosts_.get<0>();
1194 for (HostContainerIndex0::const_iterator host = idx.begin();
1195 host != idx.end(); ++host) {
1196
1197 // Convert host to element representation
1198 ElementPtr map = (*host)->toElement4();
1199
1200 // Push it on the list
1201 SubnetID subnet_id = (*host)->getIPv4SubnetID();
1202 result.add(subnet_id, map);
1203 }
1204 return (result.externalize());
1205}
1206
1208CfgHosts::toElement6() const {
1209 CfgHostsList result;
1210 // Iterate using arbitrary the index 0
1211 const HostContainerIndex0& idx = hosts_.get<0>();
1212 for (HostContainerIndex0::const_iterator host = idx.begin();
1213 host != idx.end(); ++host) {
1214
1215 // Convert host to Element representation
1216 ElementPtr map = (*host)->toElement6();
1217
1218 // Push it on the list
1219 SubnetID subnet_id = (*host)->getIPv6SubnetID();
1220 result.add(subnet_id, map);
1221 }
1222 return (result.externalize());
1223}
1224
1225} // end of namespace isc::dhcp
1226} // 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:1120
virtual void add(const HostPtr &host)
Adds a new host to the collection.
Definition: cfg_hosts.cc:952
virtual ConstHostCollection getPage6(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const
Returns range of hosts in a DHCPv6 subnet.
Definition: cfg_hosts.cc:174
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:1132
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr)
Attempts to delete a hosts by address.
Definition: cfg_hosts.cc:1113
virtual bool setIPReservationsUnique(const bool unique)
Controls whether IP reservations are unique or non-unique.
Definition: cfg_hosts.cc:1170
virtual size_t delAll6(const SubnetID &subnet_id)
Attempts to delete all hosts for a given IPv6 subnet.
Definition: cfg_hosts.cc:1142
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:730
virtual ConstHostCollection getAllbyHostname(const std::string &hostname) const
Return all hosts with a hostname.
Definition: cfg_hosts.cc:86
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:1160
virtual ConstHostCollection getPage4(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const
Returns range of hosts in a DHCPv4 subnet.
Definition: cfg_hosts.cc:144
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const
Return all hosts in a DHCPv4 subnet.
Definition: cfg_hosts.cc:50
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:664
virtual ConstHostCollection getAll6(const SubnetID &subnet_id) const
Return all hosts in a DHCPv6 subnet.
Definition: cfg_hosts.cc:68
virtual ConstHostCollection getAllbyHostname6(const std::string &hostname, const SubnetID &subnet_id) const
Return all hosts with a hostname in a DHCPv6 subnet.
Definition: cfg_hosts.cc:124
isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: cfg_hosts.cc:1177
virtual ConstHostCollection getAllbyHostname4(const std::string &hostname, const SubnetID &subnet_id) const
Return all hosts with a hostname in a DHCPv4 subnet.
Definition: cfg_hosts.cc:104
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:280
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
Exception thrown when the duplicate Host object is detected.
Wraps value holding size of the page with host reservations.
IdentifierType
Type of the host identifier.
Definition: host.h:307
@ IDENT_HWADDR
Definition: host.h:308
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
Definition: host.cc:256
#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:24
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_COUNT
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
Definition: host.h:241
HostContainer::nth_index< 4 >::type HostContainerIndex4
Fifth index type in the HostContainer.
const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS4_HOST
const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ALL
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID6
std::pair< HostContainerIndex1::iterator, HostContainerIndex1::iterator > HostContainerIndex1Range
Results range returned using the HostContainerIndex1.
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_HOST
isc::log::Logger hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
Definition: hosts_log.h:51
const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOST
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4
const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4_HOST
const isc::log::MessageID HOSTS_CFG_ADD_HOST
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4
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:785
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_NULL
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Definition: host.h:791
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID6_HOST
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6
HostContainer6::nth_index< 0 >::type HostContainer6Index0
First index type in the HostContainer6.
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID4
const isc::log::MessageID HOSTS_CFG_GET_ONE_PREFIX_NULL
const isc::log::MessageID HOSTS_CFG_GET_ALL_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID4_HOST
const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
Definition: host.h:243
const isc::log::MessageID HOSTS_CFG_GET_ALL_IDENTIFIER_HOST
HostContainer6::nth_index< 1 >::type HostContainer6Index1
Second index type in the HostContainer6.
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:794
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
const isc::log::MessageID HOSTS_CFG_GET_ONE_PREFIX_HOST
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_HOST
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6_HOST
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST
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
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6
const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS4
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL
std::pair< HostContainer6Index0::iterator, HostContainer6Index0::iterator > HostContainer6Index0Range
Results range returned using the HostContainer6Index0.
const isc::log::MessageID HOSTS_CFG_GET_ONE_PREFIX
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition: host.h:788
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_HOST
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_HOST
HostContainer::nth_index< 0 >::type HostContainerIndex0
First index type in the HostContainer.
const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS4_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID4_COUNT
const int HOSTS_DBG_TRACE_DETAIL_DATA
Records detailed results of lookups.
Definition: hosts_log.h:43
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4
const isc::log::MessageID HOSTS_CFG_DEL_ALL_SUBNET6
const int HOSTS_DBG_RESULTS
Records the results of the lookups.
Definition: hosts_log.h:33
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID6_COUNT
const isc::log::MessageID HOSTS_CFG_DEL_ALL_SUBNET4
HostContainer::nth_index< 5 >::type HostContainerIndex5
Sixth index type in the HostContainer.
const isc::log::MessageID HOSTS_CFG_GET_ALL_ADDRESS6_HOST
HostContainer::nth_index< 2 >::type HostContainerIndex2
Third index type in the HostContainer.
const isc::log::MessageID HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_NULL
const isc::log::MessageID HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4_COUNT
const isc::log::MessageID HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4_COUNT
Defines the logger used by the top-level component of kea-lfc.