Kea 2.5.5
lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2023 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
9#include <dhcp/libdhcp++.h>
10#include <dhcp/option_custom.h>
11#include <dhcpsrv/cfgmgr.h>
12#include <dhcpsrv/dhcpsrv_log.h>
13#include <dhcpsrv/lease_mgr.h>
15#include <stats/stats_mgr.h>
16#include <util/encode/hex.h>
17
18#include <boost/foreach.hpp>
19#include <boost/algorithm/string.hpp>
20
21#include <algorithm>
22#include <iostream>
23#include <iterator>
24#include <limits>
25#include <map>
26#include <sstream>
27#include <string>
28
29#include <time.h>
30
31using namespace isc::asiolink;
32using namespace isc::data;
33using namespace isc::db;
34using namespace isc::dhcp;
35using namespace isc::util;
36using namespace std;
37
38namespace isc {
39namespace dhcp {
40
41IOServicePtr LeaseMgr::io_service_ = IOServicePtr();
42
43LeasePageSize::LeasePageSize(const size_t page_size)
44 : page_size_(page_size) {
45
46 if (page_size_ == 0) {
47 isc_throw(OutOfRange, "page size of retrieved leases must not be 0");
48 }
49
50 if (page_size_ > std::numeric_limits<uint32_t>::max()) {
51 isc_throw(OutOfRange, "page size of retrieved leases must not be greater than "
52 << std::numeric_limits<uint32_t>::max());
53 }
54}
55
58 uint32_t iaid, SubnetID subnet_id) const {
59 Lease6Collection col = getLeases6(type, duid, iaid, subnet_id);
60
61 if (col.size() > 1) {
62 isc_throw(MultipleRecords, "More than one lease found for type "
63 << static_cast<int>(type) << ", duid "
64 << duid.toText() << ", iaid " << iaid
65 << " and subnet-id " << subnet_id);
66 }
67 if (col.empty()) {
68 return (Lease6Ptr());
69 }
70 return (*col.begin());
71}
72
73void
75 using namespace stats;
76
77 StatsMgr& stats_mgr = StatsMgr::instance();
78
80 if (!query) {
82 return;
83 }
84
85 // Zero out the global stats.
86 // Cumulative counters ("reclaimed-declined-addresses", "reclaimed-leases",
87 // "cumulative-assigned-addresses") never get zeroed.
88 int64_t zero = 0;
89 stats_mgr.setValue("declined-addresses", zero);
90
91 // Create if it does not exit reclaimed declined leases global stats.
92 if (!stats_mgr.getObservation("reclaimed-declined-addresses")) {
93 stats_mgr.setValue("reclaimed-declined-addresses", zero);
94 }
95
96 // Create if it does not exit reclaimed leases global stats.
97 if (!stats_mgr.getObservation("reclaimed-leases")) {
98 stats_mgr.setValue("reclaimed-leases", zero);
99 }
100
101 // Create if it does not exit cumulative global stats.
102 if (!stats_mgr.getObservation("cumulative-assigned-addresses")) {
103 stats_mgr.setValue("cumulative-assigned-addresses", zero);
104 }
105
106 // Clear subnet level stats. This ensures we don't end up with corner
107 // cases that leave stale values in place.
108 const Subnet4Collection* subnets =
109 CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
110
111 for (Subnet4Collection::const_iterator subnet = subnets->begin();
112 subnet != subnets->end(); ++subnet) {
113 SubnetID subnet_id = (*subnet)->getID();
114 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
115 "assigned-addresses"),
116 zero);
117
118 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
119 "declined-addresses"),
120 zero);
121
122 const std::string name_rec_dec(StatsMgr::generateName("subnet", subnet_id,
123 "reclaimed-declined-addresses"));
124 if (!stats_mgr.getObservation(name_rec_dec)) {
125 stats_mgr.setValue(name_rec_dec, zero);
126 }
127
128 const std::string name_rec(StatsMgr::generateName("subnet", subnet_id,
129 "reclaimed-leases"));
130 if (!stats_mgr.getObservation(name_rec)) {
131 stats_mgr.setValue(name_rec, zero);
132 }
133
134 for (const auto& pool : (*subnet)->getPools(Lease::TYPE_V4)) {
135 const std::string name_aa(StatsMgr::generateName("subnet", subnet_id,
136 StatsMgr::generateName("pool", pool->getID(),
137 "assigned-addresses")));
138 if (!stats_mgr.getObservation(name_aa)) {
139 stats_mgr.setValue(name_aa, zero);
140 }
141
142 const std::string& name_da(StatsMgr::generateName("subnet", subnet_id,
143 StatsMgr::generateName("pool", pool->getID(),
144 "declined-addresses")));
145 if (!stats_mgr.getObservation(name_da)) {
146 stats_mgr.setValue(name_da, zero);
147 }
148
149 const std::string& name_rec_dec(StatsMgr::generateName("subnet", subnet_id,
150 StatsMgr::generateName("pool", pool->getID(),
151 "reclaimed-declined-addresses")));
152 if (!stats_mgr.getObservation(name_rec_dec)) {
153 stats_mgr.setValue(name_rec_dec, zero);
154 }
155
156 const std::string& name_rec(StatsMgr::generateName("subnet", subnet_id,
157 StatsMgr::generateName("pool", pool->getID(),
158 "reclaimed-leases")));
159 if (!stats_mgr.getObservation(name_rec)) {
160 stats_mgr.setValue(name_rec, zero);
161 }
162 }
163 }
164
165 // Get counts per state per subnet. Iterate over the result set
166 // updating the subnet and global values.
167 LeaseStatsRow row;
168 while (query->getNextRow(row)) {
170 // Add to subnet level value.
171 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
172 "assigned-addresses"),
173 row.state_count_);
174 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
175 // Set subnet level value.
176 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
177 "declined-addresses"),
178 row.state_count_);
179
180 // Add to the global value.
181 stats_mgr.addValue("declined-addresses", row.state_count_);
182
183 // Add to subnet level value.
184 // Declined leases also count as assigned.
185 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
186 "assigned-addresses"),
187 row.state_count_);
188 }
189 }
190
192 if (!query) {
194 return;
195 }
196
197 // Get counts per state per subnet and pool. Iterate over the result set
198 // updating the subnet and pool and global values.
199 while (query->getNextRow(row)) {
201 // Add to subnet and pool level value.
202 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
203 StatsMgr::generateName("pool", row.pool_id_,
204 "assigned-addresses")),
205 row.state_count_);
206 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
207 // Set subnet and pool level value.
208 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
209 StatsMgr::generateName("pool", row.pool_id_,
210 "declined-addresses")),
211 row.state_count_);
212
213 // Add to subnet and pool level value.
214 // Declined leases also count as assigned.
215 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
216 StatsMgr::generateName("pool", row.pool_id_,
217 "assigned-addresses")),
218 row.state_count_);
219 }
220 }
221}
222
224 : first_subnet_id_(0), last_subnet_id_(0), select_mode_(select_mode) {
225 if (select_mode != ALL_SUBNETS && select_mode != ALL_SUBNET_POOLS) {
226 isc_throw(BadValue, "LeaseStatsQuery: mode must be either ALL_SUBNETS or ALL_SUBNET_POOLS");
227 }
228}
229
231 : first_subnet_id_(subnet_id), last_subnet_id_(0),
232 select_mode_(SINGLE_SUBNET) {
233
234 if (first_subnet_id_ == 0) {
235 isc_throw(BadValue, "LeaseStatsQuery: subnet_id_ must be > 0");
236 }
237}
238
240 const SubnetID& last_subnet_id)
241 : first_subnet_id_(first_subnet_id), last_subnet_id_(last_subnet_id),
242 select_mode_(SUBNET_RANGE) {
243
244 if (first_subnet_id_ == 0) {
245 isc_throw(BadValue, "LeaseStatsQuery: first_subnet_id_ must be > 0");
246 }
247
248 if (last_subnet_id_ == 0) {
249 isc_throw(BadValue, "LeaseStatsQuery: last_subnet_id_ must be > 0");
250 }
251
254 "LeaseStatsQuery: last_subnet_id_must be > first_subnet_id_");
255 }
256}
257
260 return(LeaseStatsQueryPtr());
261}
262
265 return(LeaseStatsQueryPtr());
266}
267
270 return(LeaseStatsQueryPtr());
271}
272
275 const SubnetID& /* last_subnet_id */) {
276 return(LeaseStatsQueryPtr());
277}
278
279bool
281 return (false);
282}
283
284void
286 using namespace stats;
287
288 StatsMgr& stats_mgr = StatsMgr::instance();
289
291 if (!query) {
293 return;
294 }
295
296 // Zero out the global stats.
297 // Cumulative counters ("reclaimed-declined-addresses", "reclaimed-leases",
298 // "cumulative-assigned-nas", "cumulative-assigned-pds") never get zeroed.
299 int64_t zero = 0;
300 stats_mgr.setValue("declined-addresses", zero);
301
302 if (!stats_mgr.getObservation("reclaimed-declined-addresses")) {
303 stats_mgr.setValue("reclaimed-declined-addresses", zero);
304 }
305
306 if (!stats_mgr.getObservation("reclaimed-leases")) {
307 stats_mgr.setValue("reclaimed-leases", zero);
308 }
309
310 // Create if it does not exit cumulative nas global stats.
311 if (!stats_mgr.getObservation("cumulative-assigned-nas")) {
312 stats_mgr.setValue("cumulative-assigned-nas", zero);
313 }
314
315 // Create if it does not exit cumulative pds global stats.
316 if (!stats_mgr.getObservation("cumulative-assigned-pds")) {
317 stats_mgr.setValue("cumulative-assigned-pds", zero);
318 }
319
320 // Clear subnet level stats. This ensures we don't end up with corner
321 // cases that leave stale values in place.
322 const Subnet6Collection* subnets =
323 CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
324
325 for (Subnet6Collection::const_iterator subnet = subnets->begin();
326 subnet != subnets->end(); ++subnet) {
327 SubnetID subnet_id = (*subnet)->getID();
328 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
329 "assigned-nas"),
330 zero);
331
332 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
333 "assigned-pds"),
334 zero);
335
336 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
337 "declined-addresses"),
338 zero);
339
340 if (!stats_mgr.getObservation(
341 StatsMgr::generateName("subnet", subnet_id,
342 "reclaimed-declined-addresses"))) {
343 stats_mgr.setValue(
344 StatsMgr::generateName("subnet", subnet_id,
345 "reclaimed-declined-addresses"),
346 zero);
347 }
348
349 if (!stats_mgr.getObservation(
350 StatsMgr::generateName("subnet", subnet_id,
351 "reclaimed-leases"))) {
352 stats_mgr.setValue(
353 StatsMgr::generateName("subnet", subnet_id,
354 "reclaimed-leases"),
355 zero);
356 }
357
358 for (const auto& pool : (*subnet)->getPools(Lease::TYPE_NA)) {
359 const std::string& name_anas(StatsMgr::generateName("subnet", subnet_id,
360 StatsMgr::generateName("pool", pool->getID(),
361 "assigned-nas")));
362 if (!stats_mgr.getObservation(name_anas)) {
363 stats_mgr.setValue(name_anas, zero);
364 }
365
366 const std::string& name_da(StatsMgr::generateName("subnet", subnet_id,
367 StatsMgr::generateName("pool", pool->getID(),
368 "declined-addresses")));
369 if (!stats_mgr.getObservation(name_da)) {
370 stats_mgr.setValue(name_da, zero);
371 }
372
373 const std::string name_rec_dec(StatsMgr::generateName("subnet", subnet_id,
374 StatsMgr::generateName("pool", pool->getID(),
375 "reclaimed-declined-addresses")));
376 if (!stats_mgr.getObservation(name_rec_dec)) {
377 stats_mgr.setValue(name_rec_dec, zero);
378 }
379
380 const std::string& name_rec(StatsMgr::generateName("subnet", subnet_id,
381 StatsMgr::generateName("pool", pool->getID(),
382 "reclaimed-leases")));
383 if (!stats_mgr.getObservation(name_rec)) {
384 stats_mgr.setValue(name_rec, zero);
385 }
386 }
387
388 for (const auto& pool : (*subnet)->getPools(Lease::TYPE_PD)) {
389 const std::string& name_apds(StatsMgr::generateName("subnet", subnet_id,
390 StatsMgr::generateName("pd-pool", pool->getID(),
391 "assigned-pds")));
392 if (!stats_mgr.getObservation(name_apds)) {
393 stats_mgr.setValue(name_apds, zero);
394 }
395
396 const std::string& name_rec(StatsMgr::generateName("subnet", subnet_id,
397 StatsMgr::generateName("pd-pool", pool->getID(),
398 "reclaimed-leases")));
399 if (!stats_mgr.getObservation(name_rec)) {
400 stats_mgr.setValue(name_rec, zero);
401 }
402 }
403 }
404
405 // Get counts per state per subnet. Iterate over the result set
406 // updating the subnet and global values.
407 LeaseStatsRow row;
408 while (query->getNextRow(row)) {
409 switch(row.lease_type_) {
410 case Lease::TYPE_NA:
412 // Add to subnet level value.
413 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
414 "assigned-nas"),
415 row.state_count_);
416 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
417 // Set subnet level value.
418 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
419 "declined-addresses"),
420 row.state_count_);
421
422 // Add to the global value.
423 stats_mgr.addValue("declined-addresses", row.state_count_);
424
425 // Add to subnet level value.
426 // Declined leases also count as assigned.
427 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
428 "assigned-nas"),
429 row.state_count_);
430 }
431 break;
432
433 case Lease::TYPE_PD:
435 // Set subnet level value.
436 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
437 "assigned-pds"),
438 row.state_count_);
439 }
440 break;
441
442 default:
443 // We don't support TYPE_TAs yet
444 break;
445 }
446 }
447
449 if (!query) {
451 return;
452 }
453
454 // Get counts per state per subnet and pool. Iterate over the result set
455 // updating the subnet and pool and global values.
456 while (query->getNextRow(row)) {
457 switch(row.lease_type_) {
458 case Lease::TYPE_NA:
460 // Add to subnet and pool level value.
461 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
462 StatsMgr::generateName("pool", row.pool_id_,
463 "assigned-nas")),
464 row.state_count_);
465 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
466 // Set subnet and pool level value.
467 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
468 StatsMgr::generateName("pool", row.pool_id_,
469 "declined-addresses")),
470 row.state_count_);
471
472 // Add to subnet and pool level value.
473 // Declined leases also count as assigned.
474 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
475 StatsMgr::generateName("pool", row.pool_id_,
476 "assigned-nas")),
477 row.state_count_);
478 }
479 break;
480
481 case Lease::TYPE_PD:
483 // Set subnet and pool level value.
484 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
485 StatsMgr::generateName("pd-pool", row.pool_id_,
486 "assigned-pds")),
487 row.state_count_);
488 }
489 break;
490
491 default:
492 // We don't support TYPE_TAs yet
493 break;
494 }
495 }
496}
497
500 return(LeaseStatsQueryPtr());
501}
502
505 return(LeaseStatsQueryPtr());
506}
507
510 return(LeaseStatsQueryPtr());
511}
512
515 const SubnetID& /* last_subnet_id */) {
516 return(LeaseStatsQueryPtr());
517}
518
519std::string
521 isc_throw(NotImplemented, "LeaseMgr::getDBVersion() called");
522}
523
524void
526 std::string extended_info_tables;
527 try {
528 extended_info_tables = parameters.at("extended-info-tables");
529 } catch (const exception&) {
530 extended_info_tables = "false";
531 }
532 // If extended_info_tables is 'true' we will enable them.
533 if (extended_info_tables == "true") {
535 }
536}
537
538bool
541 static OptionDefinitionPtr rai_def;
542
543 bool changed = false;
544 if (!lease) {
545 return (changed);
546 }
547
549 return (changed);
550 }
551
552 ConstElementPtr user_context = lease->getContext();
553 if (!user_context) {
554 return (changed);
555 }
556
557 if (!rai_def) {
560 }
561
562 if (!rai_def) {
563 // The definition is set when libdhcp++ is loaded so it is impossible
564 // to not be able to get it... so should not happen!
565 isc_throw(Unexpected, "can't find RAI option definition?!");
566 }
567
569 ConstElementPtr extended_info;
570 ElementPtr mutable_user_context;
571 ElementPtr mutable_isc;
572 string verifying = "";
573 bool removed_extended_info = false;
574
575 try {
576 verifying = "user context";
577 if (user_context->getType() != Element::map) {
578 isc_throw(BadValue, "user context is not a map");
579 }
580 if (user_context->empty()) {
581 changed = true;
582 lease->setContext(ConstElementPtr());
583 return (changed);
584 }
585
586 verifying = "isc";
587 isc = user_context->get("ISC");
588 if (!isc) {
589 return (changed);
590 }
591 mutable_user_context =
592 boost::const_pointer_cast<Element>(user_context);
593 if (!mutable_user_context) {
594 // Should not happen...
595 mutable_user_context = copy(user_context, 0);
596 lease->setContext(mutable_user_context);
597 }
598
599 if (isc->getType() != Element::map) {
600 isc_throw(BadValue, "ISC entry is not a map");
601 }
602 if (isc->empty()) {
603 changed = true;
604 mutable_user_context->remove("ISC");
605 if (mutable_user_context->empty()) {
606 lease->setContext(ConstElementPtr());
607 }
608 return (changed);
609 }
610
611 verifying = "relay-agent-info";
612 extended_info = isc->get("relay-agent-info");
613 if (!extended_info) {
614 return (changed);
615 }
616 mutable_isc = boost::const_pointer_cast<Element>(isc);
617 if (!mutable_isc) {
618 // Should not happen...
619 mutable_isc = copy(isc, 0);
620 mutable_user_context->set("ISC", mutable_isc);
621 }
622
623 if (extended_info->getType() == Element::string) {
624 // Upgrade
625 changed = true;
626 ElementPtr upgraded = Element::createMap();
627 upgraded->set("sub-options", extended_info);
628 mutable_isc->set("relay-agent-info", upgraded);
629
630 // Try to decode sub-options.
631 verifying = "rai";
632 string rai_hex = extended_info->stringValue();
633 vector<uint8_t> rai_data;
634 str::decodeFormattedHexString(rai_hex, rai_data);
635 OptionCustomPtr rai(new OptionCustom(*rai_def, Option::V4, rai_data));
636 if (!rai) {
637 isc_throw(BadValue, "can't create RAI option");
638 }
639
640 OptionPtr remote_id = rai->getOption(RAI_OPTION_REMOTE_ID);
641 if (remote_id) {
642 vector<uint8_t> bytes = remote_id->toBinary();
643 if (bytes.size() > 0) {
644 upgraded->set("remote-id",
646 }
647 }
648
649 OptionPtr relay_id = rai->getOption(RAI_OPTION_RELAY_ID);
650 if (relay_id) {
651 vector<uint8_t> bytes = relay_id->toBinary(false);
652 if (bytes.size() > 0) {
653 upgraded->set("relay-id",
655 }
656 }
657
660 .arg(lease->addr_.toText());
661 return (changed);
662 } else if (extended_info->getType() != Element::map) {
663 mutable_isc->remove("relay-agent-info");
664 removed_extended_info = true;
665 isc_throw(BadValue, "relay-agent-info is not a map or a string");
666 }
667
669 return (changed);
670 }
671
672 // Try to decode sub-options.
673 ConstElementPtr sub_options = extended_info->get("sub-options");
674 if (sub_options) {
675 verifying = "sub-options";
676 if (sub_options->getType() != Element::string) {
677 mutable_isc->remove("relay-agent-info");
678 removed_extended_info = true;
679 isc_throw(BadValue, "sub-options is not a string");
680 }
681 string rai_hex = sub_options->stringValue();
682 vector<uint8_t> rai_data;
683 str::decodeFormattedHexString(rai_hex, rai_data);
684 }
685
686 ConstElementPtr remote_id = extended_info->get("remote-id");
687 if (remote_id) {
688 verifying = "remote-id";
689 if (remote_id->getType() != Element::string) {
690 mutable_isc->remove("relay-agent-info");
691 removed_extended_info = true;
692 isc_throw(BadValue, "remote-id is not a string");
693 }
694 string remote_id_hex = remote_id->stringValue();
695 vector<uint8_t> remote_id_data;
696 encode::decodeHex(remote_id_hex, remote_id_data);
697 if (remote_id_data.empty()) {
698 mutable_isc->remove("relay-agent-info");
699 removed_extended_info = true;
700 isc_throw(BadValue, "remote-id is empty");
701 }
702 }
703
704 ConstElementPtr relay_id = extended_info->get("relay-id");
705 if (relay_id) {
706 verifying = "relay-id";
707 if (relay_id->getType() != Element::string) {
708 mutable_isc->remove("relay-agent-info");
709 removed_extended_info = true;
710 isc_throw(BadValue, "relay-id is not a string");
711 }
712 string relay_id_hex = relay_id->stringValue();
713 vector<uint8_t> relay_id_data;
714 encode::decodeHex(relay_id_hex, relay_id_data);
715 if (relay_id_data.empty()) {
716 mutable_isc->remove("relay-agent-info");
717 removed_extended_info = true;
718 isc_throw(BadValue, "relay-id is empty");
719 }
720 }
721
723 return (changed);
724 }
725
726 verifying = "relay-agent-info";
727 for (auto elem : extended_info->mapValue()) {
728 if ((elem.first != "sub-options") &&
729 (elem.first != "remote-id") &&
730 (elem.first != "relay-id") &&
731 (elem.first != "comment")) {
732 mutable_isc->remove("relay-agent-info");
733 removed_extended_info = true;
734 isc_throw(BadValue, "spurious '" << elem.first <<
735 "' entry in relay-agent-info");
736 }
737 }
738
739 return (changed);
740 } catch (const exception& ex) {
741 ostringstream err;
742 err << "in " << verifying << " a problem was found: " << ex.what();
744 .arg(lease->addr_.toText())
745 .arg(err.str());
746
747 changed = true;
748 if (verifying == "user context") {
749 lease->setContext(ConstElementPtr());
750 } else if (verifying == "isc") {
751 mutable_user_context->remove("ISC");
752 if (mutable_user_context->empty()) {
753 lease->setContext(ConstElementPtr());
754 }
755 } else {
756 if (!removed_extended_info) {
757 mutable_isc->remove("relay-agent-info");
758 }
759 if (mutable_isc->empty()) {
760 mutable_user_context->remove("ISC");
761 if (mutable_user_context->empty()) {
762 lease->setContext(ConstElementPtr());
763 }
764 }
765 }
766 return (changed);
767 }
768}
769
770bool
773 bool changed = false;
774 if (!lease) {
775 return (changed);
776 }
777
779 return (changed);
780 }
781
782 ConstElementPtr user_context = lease->getContext();
783 if (!user_context) {
784 return (changed);
785 }
786
788 ConstElementPtr relay_info;
789 ElementPtr mutable_user_context;
790 ElementPtr mutable_isc;
791 string verifying = "";
792 bool removed_relay_info = false;
793 bool upgraded = false;
794 bool have_both = false;
795 int i = -1;
796
797 try {
798 verifying = "user context";
799 if (user_context->getType() != Element::map) {
800 isc_throw(BadValue, "user context is not a map");
801 }
802 if (user_context->empty()) {
803 changed = true;
804 lease->setContext(ConstElementPtr());
805 return (changed);
806 }
807
808 verifying = "isc";
809 isc = user_context->get("ISC");
810 if (!isc) {
811 return (changed);
812 }
813 mutable_user_context =
814 boost::const_pointer_cast<Element>(user_context);
815 if (!mutable_user_context) {
816 // Should not happen...
817 mutable_user_context = copy(user_context, 0);
818 lease->setContext(mutable_user_context);
819 }
820
821 if (isc->getType() != Element::map) {
822 isc_throw(BadValue, "ISC entry is not a map");
823 }
824 if (isc->empty()) {
825 changed = true;
826 mutable_user_context->remove("ISC");
827 if (mutable_user_context->empty()) {
828 lease->setContext(ConstElementPtr());
829 }
830 return (changed);
831 }
832 mutable_isc = boost::const_pointer_cast<Element>(isc);
833 if (!mutable_isc) {
834 // Should not happen...
835 mutable_isc = copy(isc, 0);
836 mutable_user_context->set("ISC", mutable_isc);
837 }
838
839 relay_info = mutable_isc->get("relays");
840 if (relay_info && isc->contains("relay-info")) {
841 changed = true;
842 mutable_isc->remove("relays");
843 have_both = true;
844 relay_info.reset();
845 }
846 if (relay_info) {
847 // Upgrade
848 changed = true;
849 upgraded = true;
850 verifying = "relays";
851 mutable_isc->set("relay-info", relay_info);
852 mutable_isc->remove("relays");
853
854 if (relay_info->getType() != Element::list) {
855 mutable_isc->remove("relay-info");
856 removed_relay_info = true;
857 isc_throw(BadValue, "relays is not a list");
858 }
859 if (relay_info->empty()) {
860 mutable_isc->remove("relay-info");
861 removed_relay_info = true;
862 isc_throw(BadValue, "relays is empty");
863 }
864
865 verifying = "relay";
866 for (i = 0; i < relay_info->size(); ++i) {
867 ElementPtr relay = relay_info->getNonConst(i);
868 if (!relay) {
869 mutable_isc->remove("relay-info");
870 removed_relay_info = true;
871 isc_throw(BadValue, "null relay#" << i);
872 }
873 if (relay->getType() != Element::map) {
874 mutable_isc->remove("relay-info");
875 removed_relay_info = true;
876 isc_throw(BadValue, "relay#" << i << " is not a map");
877 }
878
879 // Try to decode options.
880 ConstElementPtr options = relay->get("options");
881 if (!options) {
882 continue;
883 }
884
885 verifying = "options";
886 if (options->getType() != Element::string) {
887 mutable_isc->remove("relay-info");
888 removed_relay_info = true;
889 isc_throw(BadValue, "options is not a string");
890 }
891 string options_hex = options->stringValue();
892 vector<uint8_t> options_data;
893 str::decodeFormattedHexString(options_hex, options_data);
894 OptionCollection opts;
895 LibDHCP::unpackOptions6(options_data, DHCP6_OPTION_SPACE, opts);
896
897 auto remote_id_it = opts.find(D6O_REMOTE_ID);
898 if (remote_id_it != opts.end()) {
899 OptionPtr remote_id = remote_id_it->second;
900 if (remote_id) {
901 vector<uint8_t> bytes = remote_id->toBinary();
902 if (bytes.size() > 0) {
903 relay->set("remote-id",
905 }
906 }
907 }
908
909 auto relay_id_it = opts.find(D6O_RELAY_ID);
910 if (relay_id_it != opts.end()) {
911 OptionPtr relay_id = relay_id_it->second;
912 if (relay_id) {
913 vector<uint8_t> bytes = relay_id->toBinary(false);
914 if (bytes.size() > 0) {
915 relay->set("relay-id",
917 }
918 }
919 }
920 }
921 }
922
923 verifying = (upgraded ? "relays" : "relay-info");
924 i = -1;
925 relay_info = mutable_isc->get("relay-info");
926 if (!relay_info) {
927 return (changed);
928 }
929 if (!upgraded && (relay_info->getType() != Element::list)) {
930 mutable_isc->remove("relay-info");
931 removed_relay_info = true;
932 isc_throw(BadValue, "relay-info is not a list");
933 }
934 if (!upgraded && relay_info->empty()) {
935 mutable_isc->remove("relay-info");
936 removed_relay_info = true;
937 isc_throw(BadValue, "relay-info is empty");
938 }
939
940 verifying = "relay";
941 for (i = 0; i < relay_info->size(); ++i) {
942 ElementPtr relay = relay_info->getNonConst(i);
943 if (!upgraded && !relay) {
944 mutable_isc->remove("relay-info");
945 removed_relay_info = true;
946 isc_throw(BadValue, "null relay#" << i);
947 }
948 if (!upgraded && (relay->getType() != Element::map)) {
949 mutable_isc->remove("relay-info");
950 removed_relay_info = true;
951 isc_throw(BadValue, "relay#" << i << " is not a map");
952 }
953
954 ConstElementPtr options = relay->get("options");
955 if (!upgraded && options) {
956 // Try to decode options.
957 verifying = "options";
958 if (options->getType() != Element::string) {
959 mutable_isc->remove("relay-info");
960 removed_relay_info = true;
961 isc_throw(BadValue, "options is not a string");
962 }
963 string options_hex = options->stringValue();
964 vector<uint8_t> options_data;
965 str::decodeFormattedHexString(options_hex, options_data);
966 OptionCollection opts;
967 LibDHCP::unpackOptions6(options_data, DHCP6_OPTION_SPACE, opts);
968 }
970 continue;
971 }
972
973 verifying = "link";
974 ConstElementPtr link_addr = relay->get("link");
975 if (!link_addr) {
976 mutable_isc->remove("relay-info");
977 removed_relay_info = true;
978 isc_throw(BadValue, "no link");
979 }
980 if (link_addr->getType() != Element::string) {
981 mutable_isc->remove("relay-info");
982 removed_relay_info = true;
983 isc_throw(BadValue, "link is not a string");
984 }
985 IOAddress laddr(link_addr->stringValue());
986 if (!laddr.isV6()) {
987 mutable_isc->remove("relay-info");
988 removed_relay_info = true;
989 isc_throw(BadValue, "link is not an IPv6 address");
990 }
991
992 ConstElementPtr remote_id = relay->get("remote-id");
993 if (!upgraded && remote_id) {
994 verifying = "remote-id";
995 if (remote_id->getType() != Element::string) {
996 mutable_isc->remove("relay-info");
997 removed_relay_info = true;
998 isc_throw(BadValue, "remote-id is not a string");
999 }
1000 string remote_id_hex = remote_id->stringValue();
1001 vector<uint8_t> remote_id_data;
1002 encode::decodeHex(remote_id_hex, remote_id_data);
1003 if (remote_id_data.empty()) {
1004 mutable_isc->remove("relay-info");
1005 removed_relay_info = true;
1006 isc_throw(BadValue, "remote-id is empty");
1007 }
1008 }
1009
1010 ConstElementPtr relay_id = relay->get("relay-id");
1011 if (!upgraded && relay_id) {
1012 verifying = "relay-id";
1013 if (relay_id->getType() != Element::string) {
1014 mutable_isc->remove("relay-info");
1015 removed_relay_info = true;
1016 isc_throw(BadValue, "relay-id is not a string");
1017 }
1018 string relay_id_hex = relay_id->stringValue();
1019 vector<uint8_t> relay_id_data;
1020 encode::decodeHex(relay_id_hex, relay_id_data);
1021 if (relay_id_data.empty()) {
1022 mutable_isc->remove("relay-info");
1023 removed_relay_info = true;
1024 isc_throw(BadValue, "relay-id is empty");
1025 }
1026 }
1027
1029 continue;
1030 }
1031
1032 verifying = "peer";
1033 ConstElementPtr peer_addr = relay->get("peer");
1034 if (!peer_addr) {
1035 mutable_isc->remove("relay-info");
1036 removed_relay_info = true;
1037 isc_throw(BadValue, "no peer");
1038 }
1039 if (peer_addr->getType() != Element::string) {
1040 mutable_isc->remove("relay-info");
1041 removed_relay_info = true;
1042 isc_throw(BadValue, "peer is not a string");
1043 }
1044 IOAddress paddr(peer_addr->stringValue());
1045 if (!paddr.isV6()) {
1046 mutable_isc->remove("relay-info");
1047 removed_relay_info = true;
1048 isc_throw(BadValue, "peer is not an IPv6 address");
1049 }
1050
1051 verifying = "hop";
1052 ConstElementPtr hop = relay->get("hop");
1053 if (!hop) {
1054 mutable_isc->remove("relay-info");
1055 removed_relay_info = true;
1056 isc_throw(BadValue, "no hop");
1057 }
1058 if (hop->getType() != Element::integer) {
1059 mutable_isc->remove("relay-info");
1060 removed_relay_info = true;
1061 isc_throw(BadValue, "hop is not an integer");
1062 }
1063
1064 verifying = (upgraded ? "relays" : "relay-info");
1065 for (auto elem : relay->mapValue()) {
1066 if ((elem.first != "hop") &&
1067 (elem.first != "link") &&
1068 (elem.first != "peer") &&
1069 (elem.first != "options") &&
1070 (elem.first != "remote-id") &&
1071 (elem.first != "relay-id") &&
1072 (elem.first != "comment")) {
1073 mutable_isc->remove("relay-info");
1074 removed_relay_info = true;
1075 isc_throw(BadValue, "spurious '" << elem.first << "' entry");
1076 }
1077 }
1078 }
1079
1080 if (upgraded) {
1083 .arg(lease->addr_.toText());
1084 }
1085
1086 return (changed);
1087 } catch (const exception& ex) {
1088 ostringstream err;
1089 err << "in " << verifying;
1090 if (i >= 0) {
1091 err << " [relay#" << i << "]";
1092 }
1093 err << " a problem was found: " << ex.what();
1095 .arg(lease->addr_.toText())
1096 .arg(err.str());
1097
1098 changed = true;
1099 have_both = !have_both;
1100 if (verifying == "user context") {
1101 lease->setContext(ConstElementPtr());
1102 } else if (verifying == "isc") {
1103 mutable_user_context->remove("ISC");
1104 if (mutable_user_context->empty()) {
1105 lease->setContext(ConstElementPtr());
1106 }
1107 } else {
1108 if (!removed_relay_info) {
1109 mutable_isc->remove("relay-info");
1110 }
1111 if (mutable_isc->empty()) {
1112 mutable_user_context->remove("ISC");
1113 if (mutable_user_context->empty()) {
1114 lease->setContext(ConstElementPtr());
1115 }
1116 }
1117 }
1118 return (changed);
1119 }
1120}
1121
1122void
1124 bool ignore_errors) {
1125 if (!lease) {
1126 return;
1127 }
1128
1129 ConstElementPtr user_context = lease->getContext();
1130 if (!user_context) {
1131 return;
1132 }
1133 if (user_context->getType() != Element::map) {
1134 if (ignore_errors) {
1135 return;
1136 }
1137 isc_throw(BadValue, "user context is not a map");
1138 }
1139 if (user_context->empty()) {
1140 return;
1141 }
1142
1143 ConstElementPtr isc = user_context->get("ISC");
1144 if (!isc) {
1145 return;
1146 }
1147 if (isc->getType() != Element::map) {
1148 if (ignore_errors) {
1149 return;
1150 }
1151 isc_throw(BadValue, "ISC entry is not a map");
1152 }
1153 if (isc->empty()) {
1154 return;
1155 }
1156
1157 ConstElementPtr extended_info = isc->get("relay-agent-info");
1158 if (!extended_info) {
1159 return;
1160 }
1161 if (extended_info->getType() != Element::map) {
1162 if (ignore_errors) {
1163 return;
1164 }
1165 isc_throw(BadValue, "relay-agent-info is not a map");
1166 }
1167 if (extended_info->empty()) {
1168 return;
1169 }
1170
1171 ConstElementPtr relay_id = extended_info->get("relay-id");
1172 if (relay_id) {
1173 if (relay_id->getType() == Element::string) {
1174 vector<uint8_t> bytes;
1175 try {
1176 encode::decodeHex(relay_id->stringValue(), bytes);
1177 } catch (...) {
1178 // Decode failed
1179 if (!ignore_errors) {
1180 throw;
1181 }
1182 }
1183 lease->relay_id_ = bytes;
1184 } else if (!ignore_errors) {
1185 isc_throw(BadValue, "relay-id entry is not a string");
1186 }
1187 }
1188
1189 ConstElementPtr remote_id = extended_info->get("remote-id");
1190 if (remote_id) {
1191 if (remote_id->getType() == Element::string) {
1192 vector<uint8_t> bytes;
1193 try {
1194 encode::decodeHex(remote_id->stringValue(), bytes);
1195 } catch (...) {
1196 // Decode failed
1197 if (!ignore_errors) {
1198 throw;
1199 }
1200 }
1201 lease->remote_id_ = bytes;
1202 } else if (!ignore_errors) {
1203 isc_throw(BadValue, "remote-id entry is not a string");
1204 }
1205 }
1206}
1207
1208bool
1210
1211 bool added = false;
1212 if (!lease) {
1213 return (added);
1214 }
1215
1216 ConstElementPtr user_context = lease->getContext();
1217 if (!user_context || (user_context->getType() != Element::map) ||
1218 user_context->empty()) {
1219 return (added);
1220 }
1221
1222 ConstElementPtr isc = user_context->get("ISC");
1223 if (!isc || (isc->getType() != Element::map) || isc->empty()) {
1224 return (added);
1225 }
1226
1227 ConstElementPtr relay_info = isc->get("relay-info");
1228 if (!relay_info || (relay_info->getType() != Element::list) ||
1229 relay_info->empty()) {
1230 return (added);
1231 }
1232
1233 for (int i = 0; i < relay_info->size(); ++i) {
1234 ConstElementPtr relay = relay_info->get(i);
1235 if (!relay || (relay->getType() != Element::map) || relay->empty()) {
1236 continue;
1237 }
1238 try {
1239 ConstElementPtr relay_id = relay->get("relay-id");
1240 if (relay_id) {
1241 string relay_id_hex = relay_id->stringValue();
1242 vector<uint8_t> relay_id_data;
1243 encode::decodeHex(relay_id_hex, relay_id_data);
1244 if (relay_id_data.empty()) {
1245 continue;
1246 }
1247 addRelayId6(lease->addr_, relay_id_data);
1248 added = true;
1249 }
1250
1251 ConstElementPtr remote_id = relay->get("remote-id");
1252 if (remote_id) {
1253 string remote_id_hex = remote_id->stringValue();
1254 vector<uint8_t> remote_id_data;
1255 encode::decodeHex(remote_id_hex, remote_id_data);
1256 if (remote_id_data.empty()) {
1257 continue;
1258 }
1259 addRemoteId6(lease->addr_, remote_id_data);
1260 added = true;
1261 }
1262 } catch (const exception&) {
1263 continue;
1264 }
1265 }
1266 return (added);
1267}
1268
1269size_t
1271 return (0);
1272}
1273
1274size_t
1276 return (0);
1277}
1278
1279} // namespace isc::dhcp
1280} // 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.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:304
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Multiple lease records found where one expected.
Definition: db_exceptions.h:16
ExtendedInfoSanity
Values for extended info sanity checks done for leases.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:138
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition: duid.h:84
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
Definition: lease_mgr.cc:509
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery6()
Creates and runs the IPv6 lease stats query for all subnets and pools.
Definition: lease_mgr.cc:504
virtual Lease6Collection getLeases6() const =0
Returns all IPv6 leases.
void recountLeaseStats6()
Recalculates per-subnet and global stats for IPv6 leases.
Definition: lease_mgr.cc:285
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition: lease_mgr.h:1039
virtual size_t byRelayId6size() const
Return the by-relay-id table size.
Definition: lease_mgr.cc:1270
static bool upgradeLease6ExtendedInfo(const Lease6Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
Upgrade a V6 lease user context to the new extended info entry.
Definition: lease_mgr.cc:771
virtual size_t byRemoteId6size() const
Return the by-remote-id table size.
Definition: lease_mgr.cc:1275
virtual void addRelayId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &relay_id)=0
Add lease6 extended info into by-relay-id table.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
Definition: lease_mgr.cc:274
void recountLeaseStats4()
Recalculates per-subnet and global stats for IPv4 leases.
Definition: lease_mgr.cc:74
static std::string getDBVersion()
Class method to return extended version info This class method must be redeclared and redefined in de...
Definition: lease_mgr.cc:520
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
Definition: lease_mgr.cc:514
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
Definition: lease_mgr.cc:269
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4()
Creates and runs the IPv4 lease stats query for all subnets.
Definition: lease_mgr.cc:259
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
Definition: lease_mgr.cc:1123
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition: lease_mgr.cc:539
virtual void addRemoteId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &remote_id)=0
Add lease6 extended info into by-remote-id table.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery4()
Creates and runs the IPv4 lease stats query for all subnets and pools.
Definition: lease_mgr.cc:264
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
Definition: lease_mgr.cc:1209
virtual LeaseStatsQueryPtr startLeaseStatsQuery6()
Creates and runs the IPv6 lease stats query for all subnets.
Definition: lease_mgr.cc:499
const size_t page_size_
Holds page size.
Definition: lease_mgr.h:56
LeasePageSize(const size_t page_size)
Constructor.
Definition: lease_mgr.cc:43
LeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor to query statistics for all subnets.
Definition: lease_mgr.cc:223
SubnetID first_subnet_id_
First (or only) subnet_id in the selection criteria.
Definition: lease_mgr.h:222
SubnetID last_subnet_id_
Last subnet_id in the selection criteria when a range is given.
Definition: lease_mgr.h:225
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row of data.
Definition: lease_mgr.cc:280
SelectMode
Defines the types of selection criteria supported.
Definition: lease_mgr.h:152
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Definition: libdhcp++.cc:124
static size_t unpackOptions6(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, size_t *relay_msg_offset=0, size_t *relay_msg_len=0)
Parses provided buffer as DHCPv6 options and creates Option objects.
Definition: libdhcp++.cc:309
Option with defined data fields represented as buffers that can be accessed using data field index.
Definition: option_custom.h:32
@ D6O_REMOTE_ID
Definition: dhcp6.h:57
@ D6O_RELAY_ID
Definition: dhcp6.h:73
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
An abstract API for lease database.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1414
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:29
boost::shared_ptr< Element > ElementPtr
Definition: data.h:28
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
@ DHO_DHCP_AGENT_OPTIONS
Definition: dhcp4.h:151
const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:505
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:670
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition: lease_mgr.h:233
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:974
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
Definition: option.h:40
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet4Collection
A collection of Subnet4 objects.
Definition: subnet.h:903
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
@ RAI_OPTION_RELAY_ID
Definition: dhcp4.h:277
@ RAI_OPTION_REMOTE_ID
Definition: dhcp4.h:267
const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL
const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:292
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:483
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
Definition: base_n.cc:488
void decodeFormattedHexString(const std::string &hex_string, std::vector< uint8_t > &binary)
Converts a formatted string of hexadecimal digits into a vector.
Definition: strutil.cc:273
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.
#define DHCP4_OPTION_SPACE
global std option spaces
#define DHCP6_OPTION_SPACE
Contains a single row of lease statistical data.
Definition: lease_mgr.h:64
uint32_t pool_id_
The pool ID to which this data applies.
Definition: lease_mgr.h:132
int64_t state_count_
state_count The count of leases in the lease state
Definition: lease_mgr.h:141
uint32_t lease_state_
The lease_state to which the count applies.
Definition: lease_mgr.h:138
SubnetID subnet_id_
The subnet ID to which this data applies.
Definition: lease_mgr.h:129
Lease::Type lease_type_
The lease_type to which the count applies.
Definition: lease_mgr.h:135
static const uint32_t STATE_DEFAULT
A lease in the default state.
Definition: lease.h:69
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:72
Type
Type of lease or pool.
Definition: lease.h:46
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
@ TYPE_V4
IPv4 lease.
Definition: lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition: lease.h:47