Kea 3.3.3
lease_cmds.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2026 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
11#include <cc/data.h>
12#include <config/cmds_impl.h>
13#include <config/command_mgr.h>
15#include <dhcp/duid.h>
16#include <dhcpsrv/cfgmgr.h>
18#include <dhcpsrv/lease_mgr.h>
23#include <dhcpsrv/subnet_id.h>
25#include <hooks/hooks.h>
27#include <stats/stats_mgr.h>
28#include <util/encode/encode.h>
29#include <util/filesystem.h>
31
32#include <cstdint>
33#include <limits>
34#include <sstream>
35#include <string>
36
37#include <boost/algorithm/string.hpp>
38#include <boost/scoped_ptr.hpp>
39
41#include <lease_cmds_log.h>
42#include <lease_parser.h>
43
44using namespace isc::dhcp;
45using namespace isc::data;
46using namespace isc::dhcp_ddns;
47using namespace isc::config;
48using namespace isc::asiolink;
49using namespace isc::hooks;
50using namespace isc::stats;
51using namespace isc::util;
52using namespace isc::util::file;
53using namespace isc::log;
54using namespace std;
55
56namespace isc {
57namespace lease_cmds {
58
59namespace {
60
61const int128_t uint32_min = numeric_limits<uint32_t>::min();
62const int128_t uint32_max = numeric_limits<uint32_t>::max();
63
64}
65
67class LeaseCmdsImpl : private CmdsImpl {
68public:
69
71 class Parameters {
72 public:
73
81
84
87
90
93
96
106 static Type txtToType(const std::string& txt) {
107 if (txt == "hw-address") {
109 } else if (txt == "duid") {
110 return (Parameters::TYPE_DUID);
111 } else if (txt == "client-id") {
113 } else {
114 isc_throw(BadValue, "Incorrect identifier type: "
115 << txt << ", the only supported values are: "
116 "hw-address, duid, client-id");
117 }
118 }
119
122
125
127 uint32_t iaid;
128
131
134 : subnet_id(0), addr("::"), query_type(TYPE_ADDR),
135 lease_type(Lease::TYPE_NA), iaid(0), updateDDNS(false) {
136 }
137 };
138
139public:
140
149 int
151
161 int
163
172 int
174
186 int
188
204 int
206
216 int
218
228 int
230
240 int
242
252 int
254
265 int
267
276 int
278
287 int
289
298 int
300
309 int
311
320 int
322
331 int
333
343
353
362 int
364
376 Parameters getParameters(bool v6, const ConstElementPtr& args);
377
395 Lease6Ptr getIPv6LeaseForDelete(const Parameters& parameters) const;
396
412 const IOAddress& lease_address,
413 const DuidPtr& duid,
414 const int control_result,
415 const std::string& error_message) const;
416
427 IOAddress getAddressParam(ConstElementPtr params, const std::string name,
428 short family = AF_INET) const;
437 static bool addOrUpdate4(Lease4Ptr lease, bool force_create);
438
447 static bool addOrUpdate6(Lease6Ptr lease, bool force_create);
448
453 inline static ConstElementPtr getExtendedInfo6(const Lease6Ptr& lease) {
454 ConstElementPtr user_context = lease->getContext();
455 if (!user_context || (user_context->getType() != Element::map)) {
456 return (ConstElementPtr());
457 }
458 ConstElementPtr isc = user_context->get("ISC");
459 if (!isc || (isc->getType() != Element::map)) {
460 return (ConstElementPtr());
461 }
462 return (isc->get("relay-info"));
463 }
464
478 static void lease4Offer(CalloutHandle& callout_handle,
480
492 static void leases4Committed(CalloutHandle& callout_handle,
494
506 static void leases6Committed(CalloutHandle& callout_handle,
508};
509
510bool
511LeaseCmdsImpl::addOrUpdate4(Lease4Ptr lease, bool force_create) {
512 if (lease->stateRegistered()) {
513 isc_throw(BadValue, "DHCPv4 leases do not support registered state");
514 }
515
516 Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease->addr_);
517 if (force_create && !existing) {
518 // lease does not exist
519 if (!LeaseMgrFactory::instance().addLease(lease)) {
521 "lost race between calls to get and add");
522 }
524 return (true);
525 }
526 if (existing) {
527 // Update lease current expiration time with value received from the
528 // database. Some database backends reject operations on the lease if
529 // the current expiration time value does not match what is stored.
530 Lease::syncCurrentExpirationTime(*existing, *lease);
531 }
532 try {
534 } catch (const NoSuchLease&) {
535 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
536 << lease->addr_ << " either because the lease has been "
537 "deleted or it has changed in the database, in both cases a "
538 "retry might succeed");
539 }
540
541 LeaseMgr::updateStatsOnUpdate(existing, lease);
542 return (false);
543}
544
545bool
546LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) {
547 Lease6Ptr existing =
548 LeaseMgrFactory::instance().getLease6(lease->type_, lease->addr_);
549 if (force_create && !existing) {
550 // lease does not exist
551 if (!LeaseMgrFactory::instance().addLease(lease)) {
553 "lost race between calls to get and add");
554 }
556 return (true);
557 }
558 if (existing) {
559 // Refuse used <-> registered transitions.
560 if (existing->stateRegistered() && !lease->stateRegistered()) {
561 isc_throw(BadValue, "illegal reuse of registered address "
562 << lease->addr_);
563 } else if (!existing->stateRegistered() && lease->stateRegistered()) {
564 isc_throw(BadValue, "address in use: " << lease->addr_
565 << " can't be registered");
566 }
567
568 // Update lease current expiration time with value received from the
569 // database. Some database backends reject operations on the lease if
570 // the current expiration time value does not match what is stored.
571 Lease::syncCurrentExpirationTime(*existing, *lease);
572
573 // Check what is the action about extended info.
574 ConstElementPtr old_extended_info = getExtendedInfo6(existing);
575 ConstElementPtr extended_info = getExtendedInfo6(lease);
576 if ((!old_extended_info && !extended_info) ||
577 (old_extended_info && extended_info &&
578 (*old_extended_info == *extended_info))) {
579 // Leave the default Lease6::ACTION_IGNORE.
580 } else {
581 lease->extended_info_action_ = Lease6::ACTION_UPDATE;
582 }
583 }
584 try {
586 } catch (const NoSuchLease&) {
587 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
588 << lease->addr_ << " either because the lease has been "
589 "deleted or it has changed in the database, in both cases a "
590 "retry might succeed");
591 }
592
593 LeaseMgr::updateStatsOnUpdate(existing, lease);
594 return (false);
595}
596
597int
599 // Arbitrary defaulting to DHCPv4 or with other words extractCommand
600 // below is not expected to throw...
601 bool v4 = true;
602 stringstream resp;
603 string lease_address = "unknown";
604 try {
605 extractCommand(handle);
606 v4 = (cmd_name_ == "lease4-add");
607 if (!cmd_args_) {
608 isc_throw(isc::BadValue, "no parameters specified for the command");
609 }
610
612
613 // This parameter is ignored for the commands adding the lease.
614 bool force_create = false;
615 Lease4Ptr lease4;
616 Lease6Ptr lease6;
617 if (v4) {
618 Lease4Parser parser;
619 lease4 = parser.parse(config, cmd_args_, force_create);
620 if (lease4) {
621 lease_address = lease4->addr_.toText();
622 bool success;
623 if (!MultiThreadingMgr::instance().getMode()) {
624 // Not multi-threading.
625 success = LeaseMgrFactory::instance().addLease(lease4);
626 } else {
627 // Multi-threading, try to lock first to avoid a race.
628 ResourceHandler4 resource_handler;
629 if (resource_handler.tryLock4(lease4->addr_)) {
630 success = LeaseMgrFactory::instance().addLease(lease4);
631 } else {
633 "ResourceBusy: IP address:" << lease4->addr_
634 << " could not be added.");
635 }
636 }
637
638 if (!success) {
639 isc_throw(LeaseCmdsConflict, "IPv4 lease already exists.");
640 }
641
643 resp << "Lease for address " << lease4->addr_.toText()
644 << ", subnet-id " << lease4->subnet_id_ << " added.";
645 }
646 } else {
647 Lease6Parser parser;
648 lease6 = parser.parse(config, cmd_args_, force_create);
649 if (lease6) {
650 lease_address = lease6->addr_.toText();
651 bool success;
652 if (!MultiThreadingMgr::instance().getMode()) {
653 // Not multi-threading.
654 success = LeaseMgrFactory::instance().addLease(lease6);
655 } else {
656 // Multi-threading, try to lock first to avoid a race.
657 ResourceHandler resource_handler;
658 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
659 success = LeaseMgrFactory::instance().addLease(lease6);
660 } else {
662 "ResourceBusy: IP address:" << lease6->addr_
663 << " could not be added.");
664 }
665 }
666
667 if (!success) {
668 isc_throw(LeaseCmdsConflict, "IPv6 lease already exists.");
669 }
670
672 if (lease6->type_ == Lease::TYPE_NA) {
673 resp << "Lease for address " << lease6->addr_.toText()
674 << ", subnet-id " << lease6->subnet_id_ << " added.";
675 } else {
676 resp << "Lease for prefix " << lease6->addr_.toText()
677 << "/" << static_cast<int>(lease6->prefixlen_)
678 << ", subnet-id " << lease6->subnet_id_ << " added.";
679 }
680 }
681 }
682 } catch (const LeaseCmdsConflict& ex) {
684 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
685 .arg(ex.what());
687 return (0);
688
689 } catch (const std::exception& ex) {
691 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
692 .arg(ex.what());
693 setErrorResponse(handle, ex.what());
694 return (1);
695 }
696
699 .arg(lease_address);
700 setSuccessResponse(handle, resp.str());
701 return (0);
702}
703
706 Parameters x;
707
708 if (!params || params->getType() != Element::map) {
709 isc_throw(BadValue, "Parameters missing or are not a map.");
710 }
711
712 if (params->contains("update-ddns")) {
713 ConstElementPtr tmp = params->get("update-ddns");
714 if (tmp->getType() != Element::boolean) {
715 isc_throw(BadValue, "'update-ddns' is not a boolean");
716 } else {
717 x.updateDDNS = tmp->boolValue();
718 }
719 }
720
721 // We support several sets of parameters for leaseX-get/lease-del:
722 // lease-get(type, address)
723 // lease-get(type, subnet-id, identifier-type, identifier)
724
725 if (params->contains("type")) {
726 string t = params->get("type")->stringValue();
727 if (t == "IA_NA" || t == "0") {
729 } else if (t == "IA_PD" || t == "2") {
731 } else if (t == "V4" || t == "3") {
733 } else {
734 isc_throw(BadValue, "Invalid lease type specified: " << t
735 << ", only supported values are: IA_NA, IA_PD and V4");
736 }
737 }
738
739 ConstElementPtr tmp = params->get("ip-address");
740 if (tmp) {
741 if (tmp->getType() != Element::string) {
742 isc_throw(BadValue, "'ip-address' is not a string.");
743 }
744
745 x.addr = IOAddress(tmp->stringValue());
746
747 if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
748 stringstream txt;
749 txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
750 << " address specified: " << tmp->stringValue();
751 isc_throw(BadValue, txt.str());
752 }
753
755 return (x);
756 }
757
758 tmp = params->get("subnet-id");
759 if (!tmp) {
760 isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
761 }
762 if (tmp->getType() != Element::integer) {
763 isc_throw(BadValue, "'subnet-id' parameter is not integer.");
764 }
765 int128_t tmp128 = tmp->intValue();
766 if ((tmp128 < uint32_min) || (tmp128 > uint32_max)) {
767 isc_throw(BadValue, "'subnet-id' parameter is not a 32 bit unsigned integer.");
768 }
769 x.subnet_id = static_cast<SubnetID>(tmp128);
770
771 tmp = params->get("iaid");
772 if (tmp) {
773 if (!v6) {
774 isc_throw(BadValue, "'iaid' parameter is specific to DHCPv6.");
775 }
776 if (tmp->getType() != Element::integer) {
777 isc_throw(BadValue, "'iaid' parameter is not integer.");
778 }
779 tmp128 = tmp->intValue();
780 if ((tmp128 < uint32_min) || (tmp128 > uint32_max)) {
781 isc_throw(BadValue, "'iaid' parameter is not a 32 bit unsigned integer.");
782 }
783 x.iaid = static_cast<uint32_t>(tmp128);
784 }
785
786 // No address specified. Ok, so it must be identifier based query.
787 // "identifier-type": "duid",
788 // "identifier": "aa:bb:cc:dd:ee:..."
789
790 ConstElementPtr type = params->get("identifier-type");
791 ConstElementPtr ident = params->get("identifier");
792 if (!type || type->getType() != Element::string) {
793 isc_throw(BadValue, "No 'ip-address' provided"
794 " and 'identifier-type' is either missing or not a string.");
795 }
796 if (!ident || ident->getType() != Element::string) {
797 isc_throw(BadValue, "No 'ip-address' provided"
798 " and 'identifier' is either missing or not a string.");
799 }
800
801 // Got the parameters. Let's see if their values make sense.
802 // Try to convert identifier-type
803 x.query_type = Parameters::txtToType(type->stringValue());
804
805 switch (x.query_type) {
807 try {
808 HWAddr hw = HWAddr::fromText(ident->stringValue());
809 x.hwaddr = HWAddrPtr(new HWAddr(hw));
810 } catch (const std::exception& ex) {
811 isc_throw(BadValue, "Bad 'hw-address' identifier: " << ex.what());
812 }
813 break;
815 try {
816 x.client_id = ClientId::fromText(ident->stringValue());
817 } catch (const std::exception& ex) {
818 isc_throw(BadValue, "Bad 'client-id' identifier: " << ex.what());
819 }
820 break;
822 try {
823 DUID duid = DUID::fromText(ident->stringValue());
824 x.duid = DuidPtr(new DUID(duid));
825 } catch (const std::exception& ex) {
826 isc_throw(BadValue, "Bad 'duid' identifier: " << ex.what());
827 }
828 break;
829 default:
830 isc_throw(BadValue, "Identifier type " << type->stringValue() <<
831 " is not supported.");
832 }
833
834 return (x);
835}
836
837int
839 Parameters p;
840 Lease4Ptr lease4;
841 Lease6Ptr lease6;
842 bool v4 = true;
843 try {
844 extractCommand(handle);
845 v4 = (cmd_name_ == "lease4-get");
846 p = getParameters(!v4, cmd_args_);
847 switch (p.query_type) {
849 // Query by address
850 if (v4) {
852 } else {
854 }
855 break;
856 }
858 if (v4) {
859 if (!p.hwaddr) {
860 isc_throw(InvalidParameter, "Program error: Query by hw-address "
861 "requires hwaddr to be specified");
862 }
863
865 } else {
866 isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
867 }
868 break;
869
871 if (!v4) {
872 if (!p.duid) {
873 isc_throw(InvalidParameter, "Program error: Query by duid "
874 "requires duid to be specified");
875 }
876
878 p.iaid, p.subnet_id);
879 } else {
880 isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
881 }
882 break;
883
885 if (v4) {
886 if (!p.client_id) {
887 isc_throw(InvalidParameter, "Program error: Query by client-id "
888 "requires client-id to be specified");
889 }
890
892 } else {
893 isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
894 }
895 break;
896
897 default: {
898 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
899 break;
900 }
901 }
902 } catch (const std::exception& ex) {
904 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
905 .arg(ex.what());
906 setErrorResponse(handle, ex.what());
907 return (1);
908 }
909
910 ElementPtr lease_json;
911 if (v4 && lease4) {
912 lease_json = lease4->toElement();
914 "IPv4 lease found.", lease_json);
915 setResponse(handle, response);
916 } else if (!v4 && lease6) {
917 lease_json = lease6->toElement();
919 "IPv6 lease found.", lease_json);
920 setResponse(handle, response);
921 } else {
922 // If we got here, the lease has not been found.
923 setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
924 }
925
926 return (0);
927}
928
929int
931 bool v4 = true;
932 try {
933 extractCommand(handle);
934 v4 = (cmd_name_ == "lease4-get-all");
935
936 ElementPtr leases_json = Element::createList();
937
938 // The argument may contain a list of subnets for which leases should
939 // be returned.
940 if (cmd_args_) {
941 ConstElementPtr subnets = cmd_args_->get("subnets");
942 if (!subnets) {
943 isc_throw(BadValue, "'subnets' parameter not specified");
944 }
945 if (subnets->getType() != Element::list) {
946 isc_throw(BadValue, "'subnets' parameter must be a list");
947 }
948
949 const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
950 for (auto const& subnet_id : subnet_ids) {
951 if (subnet_id->getType() != Element::integer) {
952 isc_throw(BadValue, "listed subnet identifiers must be numbers");
953 }
954 auto subnet_id_ = subnet_id->intValue();
955 if ((subnet_id_ < uint32_min) || (subnet_id_ > uint32_max)) {
956 isc_throw(BadValue, "out of range subnet identifier "
957 << subnet_id_);
958 }
959
960 if (v4) {
961 Lease4Collection leases =
963 for (auto const& lease : leases) {
964 ElementPtr lease_json = lease->toElement();
965 leases_json->add(lease_json);
966 }
967 } else {
968 Lease6Collection leases =
970 for (auto const& lease : leases) {
971 ElementPtr lease_json = lease->toElement();
972 leases_json->add(lease_json);
973 }
974 }
975 }
976
977 } else {
978 // There is no 'subnets' argument so let's return all leases.
979 if (v4) {
981 for (auto const& lease : leases) {
982 ElementPtr lease_json = lease->toElement();
983 leases_json->add(lease_json);
984 }
985 } else {
987 for (auto const& lease : leases) {
988 ElementPtr lease_json = lease->toElement();
989 leases_json->add(lease_json);
990 }
991 }
992 }
993
994 std::ostringstream s;
995 s << leases_json->size()
996 << " IPv" << (v4 ? "4" : "6")
997 << " lease(s) found.";
999 args->set("leases", leases_json);
1000 ConstElementPtr response =
1001 createAnswer(leases_json->size() > 0 ?
1004 s.str(), args);
1005 setResponse(handle, response);
1006
1007 } catch (const std::exception& ex) {
1008 setErrorResponse(handle, ex.what());
1009 return (CONTROL_RESULT_ERROR);
1010 }
1011
1012 return (0);
1013}
1014
1015int
1017 bool v4 = true;
1018 try {
1019 extractCommand(handle);
1020 v4 = (cmd_name_ == "lease4-get-page");
1021
1022 // arguments must always be present
1023 if (!cmd_args_) {
1024 isc_throw(BadValue, "no parameters specified for the " << cmd_name_
1025 << " command");
1026 }
1027
1028 // The 'from' argument denotes from which lease we should start the
1029 // results page. The results page excludes this lease.
1030 ConstElementPtr from = cmd_args_->get("from");
1031 if (!from) {
1032 isc_throw(BadValue, "'from' parameter not specified");
1033 }
1034
1035 // The 'from' argument is a string. It may contain a 'start' keyword or
1036 // an IP address.
1037 if (from->getType() != Element::string) {
1038 isc_throw(BadValue, "'from' parameter must be a string");
1039 }
1040
1041 boost::scoped_ptr<IOAddress> from_address;
1042 try {
1043 if (from->stringValue() == "start") {
1044 from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1045
1046 } else {
1047 // Conversion of a string to an IP address may throw.
1048 from_address.reset(new IOAddress(from->stringValue()));
1049 }
1050
1051 } catch (...) {
1052 isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1053 "a valid IPv" << (v4 ? "4" : "6") << " address");
1054 }
1055
1056 // It must be either IPv4 address for lease4-get-page or IPv6 address for
1057 // lease6-get-page.
1058 if (v4 && (!from_address->isV4())) {
1059 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1060 << " is not an IPv4 address");
1061
1062 } else if (!v4 && from_address->isV4()) {
1063 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1064 << " is not an IPv6 address");
1065 }
1066
1067 // The 'limit' is a desired page size. It must always be present.
1068 ConstElementPtr page_limit = cmd_args_->get("limit");
1069 if (!page_limit) {
1070 isc_throw(BadValue, "'limit' parameter not specified");
1071 }
1072
1073 // The 'limit' must be a number.
1074 if (page_limit->getType() != Element::integer) {
1075 isc_throw(BadValue, "'limit' parameter must be a number");
1076 }
1077
1078 auto tmp128 = page_limit->intValue();
1079 if ((tmp128 < uint32_min) || (tmp128 > uint32_max)) {
1080 isc_throw(BadValue, "'limit' parameter is not a 32 bit unsigned integer.");
1081 }
1082
1083 if (tmp128 == 0) {
1084 isc_throw(BadValue, "'limit' parameter must not be 0.");
1085 }
1086
1087 // Retrieve the desired page size.
1088 size_t page_limit_value = static_cast<size_t>(tmp128);
1089
1090 ElementPtr leases_json = Element::createList();
1091
1092 if (v4) {
1093 // Get page of IPv4 leases.
1094 Lease4Collection leases =
1095 LeaseMgrFactory::instance().getLeases4(*from_address,
1096 LeasePageSize(page_limit_value));
1097
1098 // Convert leases into JSON list.
1099 for (auto const& lease : leases) {
1100 ElementPtr lease_json = lease->toElement();
1101 leases_json->add(lease_json);
1102 }
1103
1104 } else {
1105 // Get page of IPv6 leases.
1106 Lease6Collection leases =
1107 LeaseMgrFactory::instance().getLeases6(*from_address,
1108 LeasePageSize(page_limit_value));
1109 // Convert leases into JSON list.
1110 for (auto const& lease : leases) {
1111 ElementPtr lease_json = lease->toElement();
1112 leases_json->add(lease_json);
1113 }
1114 }
1115
1116 // Prepare textual status.
1117 std::ostringstream s;
1118 s << leases_json->size()
1119 << " IPv" << (v4 ? "4" : "6")
1120 << " lease(s) found.";
1122
1123 // Put gathered data into arguments map.
1124 args->set("leases", leases_json);
1125 args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1126
1127 // Create the response.
1128 ConstElementPtr response =
1129 createAnswer(leases_json->size() > 0 ?
1132 s.str(), args);
1133 setResponse(handle, response);
1134
1135 } catch (const std::exception& ex) {
1136 setErrorResponse(handle, ex.what());
1137 return (CONTROL_RESULT_ERROR);
1138 }
1139
1140 return (CONTROL_RESULT_SUCCESS);
1141}
1142
1143int
1145 bool v4 = true;
1146 try {
1147 extractCommand(handle);
1148 v4 = (cmd_name_ == "lease4-get-by-hw-address");
1149
1150 // arguments must always be present
1151 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1152 isc_throw(BadValue, "Command arguments missing or a not a map.");
1153 }
1154
1155 // the hw-address parameter is mandatory.
1156 ConstElementPtr hw_address = cmd_args_->get("hw-address");
1157 if (!hw_address) {
1158 isc_throw(BadValue, "'hw-address' parameter not specified");
1159 }
1160
1161 // The 'hw-address' argument is a string.
1162 if (hw_address->getType() != Element::string) {
1163 isc_throw(BadValue, "'hw-address' parameter must be a string");
1164 }
1165
1166 if (hw_address->stringValue().empty()) {
1167 isc_throw(BadValue, "'hw-address' parameter must not be empty");
1168 }
1169
1170 HWAddr hwaddr;
1171 try {
1172 hwaddr = HWAddr::fromText(hw_address->stringValue());
1173 } catch (const std::exception& ex) {
1174 isc_throw(BadValue, "bad 'hw-address' parameter: " << ex.what());
1175 }
1176
1177 ElementPtr leases_json = Element::createList();
1178 if (v4) {
1179 Lease4Collection leases =
1181 for (auto const& lease : leases) {
1182 ElementPtr lease_json = lease->toElement();
1183 leases_json->add(lease_json);
1184 }
1185 } else {
1186 Lease6Collection leases =
1188 for (auto const& lease : leases) {
1189 ElementPtr lease_json = lease->toElement();
1190 leases_json->add(lease_json);
1191 }
1192 }
1193
1194 std::ostringstream s;
1195 s << leases_json->size()
1196 << " IPv" << (v4 ? "4" : "6")
1197 << " lease(s) found.";
1199 args->set("leases", leases_json);
1200 ConstElementPtr response =
1201 createAnswer(leases_json->size() > 0 ?
1204 s.str(), args);
1205 setResponse(handle, response);
1206
1207 } catch (const std::exception& ex) {
1208 setErrorResponse(handle, ex.what());
1209 return (CONTROL_RESULT_ERROR);
1210 }
1211
1212 return (0);
1213}
1214
1215int
1217 try {
1218 extractCommand(handle);
1219
1220 // arguments must always be present
1221 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1222 isc_throw(BadValue, "Command arguments missing or a not a map.");
1223 }
1224
1225 // the client-id parameter is mandatory.
1226 ConstElementPtr client_id = cmd_args_->get("client-id");
1227 if (!client_id) {
1228 isc_throw(BadValue, "'client-id' parameter not specified");
1229 }
1230
1231 // The 'client-id' argument is a string.
1232 if (client_id->getType() != Element::string) {
1233 isc_throw(BadValue, "'client-id' parameter must be a string");
1234 }
1235
1236 ClientIdPtr clientid;
1237 try {
1238 clientid = ClientId::fromText(client_id->stringValue());
1239 } catch (const std::exception& ex) {
1240 isc_throw(BadValue, "bad 'client-id' parameter: " << ex.what());
1241 }
1242
1243 Lease4Collection leases =
1245 ElementPtr leases_json = Element::createList();
1246 for (auto const& lease : leases) {
1247 ElementPtr lease_json = lease->toElement();
1248 leases_json->add(lease_json);
1249 }
1250
1251 std::ostringstream s;
1252 s << leases_json->size() << " IPv4 lease(s) found.";
1254 args->set("leases", leases_json);
1255 ConstElementPtr response =
1256 createAnswer(leases_json->size() > 0 ?
1259 s.str(), args);
1260 setResponse(handle, response);
1261
1262 } catch (const std::exception& ex) {
1263 setErrorResponse(handle, ex.what());
1264 return (CONTROL_RESULT_ERROR);
1265 }
1266
1267 return (0);
1268}
1269
1270int
1272 try {
1273 extractCommand(handle);
1274
1275 // arguments must always be present
1276 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1277 isc_throw(BadValue, "Command arguments missing or a not a map.");
1278 }
1279
1280 // the duid parameter is mandatory.
1281 ConstElementPtr duid = cmd_args_->get("duid");
1282 if (!duid) {
1283 isc_throw(BadValue, "'duid' parameter not specified");
1284 }
1285
1286 // The 'duid' argument is a string.
1287 if (duid->getType() != Element::string) {
1288 isc_throw(BadValue, "'duid' parameter must be a string");
1289 }
1290
1291 DUID duid_ = DUID::EMPTY();
1292 try {
1293 duid_ = DUID::fromText(duid->stringValue());
1294 } catch (const std::exception& ex) {
1295 isc_throw(BadValue, "bad 'duid' parameter: " << ex.what());
1296 }
1297
1298 Lease6Collection leases =
1300 ElementPtr leases_json = Element::createList();
1301 for (auto const& lease : leases) {
1302 ElementPtr lease_json = lease->toElement();
1303 leases_json->add(lease_json);
1304 }
1305
1306 std::ostringstream s;
1307 s << leases_json->size() << " IPv6 lease(s) found.";
1309 args->set("leases", leases_json);
1310 ConstElementPtr response =
1311 createAnswer(leases_json->size() > 0 ?
1314 s.str(), args);
1315 setResponse(handle, response);
1316
1317 } catch (const std::exception& ex) {
1318 setErrorResponse(handle, ex.what());
1319 return (CONTROL_RESULT_ERROR);
1320 }
1321
1322 return (0);
1323}
1324
1325int
1327 bool v4 = true;
1328 try {
1329 extractCommand(handle);
1330 v4 = (cmd_name_ == "lease4-get-by-state");
1331
1332 // arguments must always be present
1333 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1334 isc_throw(BadValue, "Command arguments missing or a not a map.");
1335 }
1336
1337 // the state parameter is mandatory.
1338 ConstElementPtr state = cmd_args_->get("state");
1339 if (!state) {
1340 isc_throw(BadValue, "'state' parameter not specified");
1341 }
1342
1343 uint32_t state_ = 0;
1344 // We accept string (nicknames) and integer values.
1345 if (state->getType() == Element::string) {
1346 std::string state_str = state->stringValue();
1347 if (state_str.empty()) {
1348 isc_throw(BadValue, "'state' parameter is empty");
1349 } else if ((state_str == "default") || (state_str == "assigned")) {
1350 state_ = Lease::STATE_DEFAULT;;
1351 } else if (state_str == "declined") {
1352 state_ = Lease::STATE_DECLINED;
1353 } else if (state_str == "expired-reclaimed") {
1355 } else if (state_str == "released") {
1356 state_ = Lease::STATE_RELEASED;
1357 } else if (state_str == "registered") {
1358 state_ = Lease::STATE_REGISTERED;
1359 } else {
1360 isc_throw(BadValue, "'state' parameter value (" << state_str
1361 << ") is not recognized");
1362 }
1363 } else if (state->getType() == Element::integer) {
1364 state_ = state->intValue();
1365 } else {
1366 isc_throw(BadValue, "'state' parameter must be a number or a string");
1367 }
1368
1369 SubnetID subnet_id_ = 0;
1370 ConstElementPtr subnet = cmd_args_->get("subnet-id");
1371 if (subnet) {
1372 if (subnet->getType() != Element::integer) {
1373 isc_throw(BadValue, "'subnet-id' parameter must be a number");
1374 }
1375 auto id128 = subnet->intValue();
1376 if ((id128 < uint32_min) || (id128 > uint32_max)) {
1377 isc_throw(BadValue, "'subnet-id' parameter must be a 32 bit unsigned integer");
1378 }
1379 subnet_id_ = static_cast<SubnetID>(id128);
1380 }
1381
1382 ElementPtr leases_json = Element::createList();
1383 if (v4) {
1384 Lease4Collection leases =
1385 LeaseMgrFactory::instance().getLeases4(state_, subnet_id_);
1386
1387 for (auto const& lease : leases) {
1388 ElementPtr lease_json = lease->toElement();
1389 leases_json->add(lease_json);
1390 }
1391 } else {
1392 Lease6Collection leases =
1393 LeaseMgrFactory::instance().getLeases6(state_, subnet_id_);
1394
1395 for (auto const& lease : leases) {
1396 ElementPtr lease_json = lease->toElement();
1397 leases_json->add(lease_json);
1398 }
1399 }
1400
1401 std::ostringstream s;
1402 s << leases_json->size()
1403 << " IPv" << (v4 ? "4" : "6")
1404 << " lease(s) found with state ";
1405 if (state_ <= Lease::STATE_REGISTERED) {
1406 s << Lease::basicStatesToText(state_) << " (" << state_ << ")";
1407 } else {
1408 s << state_;
1409 }
1410 if (subnet_id_ != 0) {
1411 s << " in subnet " << subnet_id_;
1412 }
1413 s << ".";
1415 args->set("leases", leases_json);
1416 ConstElementPtr response =
1417 createAnswer(leases_json->size() > 0 ?
1420 s.str(), args);
1421 setResponse(handle, response);
1422
1423 } catch (const std::exception& ex) {
1424 setErrorResponse(handle, ex.what());
1425 return (CONTROL_RESULT_ERROR);
1426 }
1427
1428 return (0);
1429}
1430
1431int
1433 bool v4 = true;
1434 try {
1435 extractCommand(handle);
1436 v4 = (cmd_name_ == "lease4-get-by-hostname");
1437
1438 // arguments must always be present
1439 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1440 isc_throw(BadValue, "Command arguments missing or a not a map.");
1441 }
1442
1443 // the hostname parameter is mandatory.
1444 ConstElementPtr hostname = cmd_args_->get("hostname");
1445 if (!hostname) {
1446 isc_throw(BadValue, "'hostname' parameter not specified");
1447 }
1448
1449 // The 'hostname' argument is a string.
1450 if (hostname->getType() != Element::string) {
1451 isc_throw(BadValue, "'hostname' parameter must be a string");
1452 }
1453
1454 std::string hostname_ = hostname->stringValue();
1456 if (hostname_.empty()) {
1457 isc_throw(BadValue, "'hostname' parameter is empty");
1458 }
1459 boost::algorithm::to_lower(hostname_);
1460
1461 ElementPtr leases_json = Element::createList();
1462 if (v4) {
1463 Lease4Collection leases =
1465
1466 for (auto const& lease : leases) {
1467 ElementPtr lease_json = lease->toElement();
1468 leases_json->add(lease_json);
1469 }
1470 } else {
1471 Lease6Collection leases =
1473
1474 for (auto const& lease : leases) {
1475 ElementPtr lease_json = lease->toElement();
1476 leases_json->add(lease_json);
1477 }
1478 }
1479
1480 std::ostringstream s;
1481 s << leases_json->size()
1482 << " IPv" << (v4 ? "4" : "6")
1483 << " lease(s) found.";
1485 args->set("leases", leases_json);
1486 ConstElementPtr response =
1487 createAnswer(leases_json->size() > 0 ?
1490 s.str(), args);
1491 setResponse(handle, response);
1492
1493 } catch (const std::exception& ex) {
1494 setErrorResponse(handle, ex.what());
1495 return (CONTROL_RESULT_ERROR);
1496 }
1497
1498 return (0);
1499}
1500
1501int
1503 Parameters p;
1504 Lease4Ptr lease4;
1505 try {
1506 extractCommand(handle);
1507 p = getParameters(false, cmd_args_);
1508 switch (p.query_type) {
1509 case Parameters::TYPE_ADDR: {
1510 // If address was specified explicitly, let's use it as is.
1512 if (!lease4) {
1513 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1514 return (0);
1515 }
1516 break;
1517 }
1519 if (!p.hwaddr) {
1520 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1521 "requires hwaddr to be specified");
1522 }
1523
1524 // Let's see if there's such a lease at all.
1526 if (!lease4) {
1527 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1528 return (0);
1529 }
1530 break;
1531 }
1533 if (!p.client_id) {
1534 isc_throw(InvalidParameter, "Program error: Query by client-id "
1535 "requires client-id to be specified");
1536 }
1537
1538 // Let's see if there's such a lease at all.
1540 if (!lease4) {
1541 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1542 return (0);
1543 }
1544 break;
1545 }
1546 case Parameters::TYPE_DUID: {
1547 isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
1548 break;
1549 }
1550 default: {
1551 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1552 break;
1553 }
1554 }
1555
1556 if (LeaseMgrFactory::instance().deleteLease(lease4)) {
1557 setSuccessResponse(handle, "IPv4 lease deleted.");
1559 } else {
1560 setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1561 }
1562
1563 // Queue an NCR to remove DNS if configured and the lease has it.
1564 if (p.updateDDNS) {
1565 queueNCR(CHG_REMOVE, lease4);
1566 }
1567
1568 } catch (const std::exception& ex) {
1570 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1571 .arg(ex.what());
1572 setErrorResponse(handle, ex.what());
1573 return (1);
1574 }
1576 .arg(lease4->addr_.toText());
1577 return (0);
1578}
1579
1580int
1582 try {
1583 extractCommand(handle);
1584
1585 // Arguments are mandatory.
1586 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1587 isc_throw(BadValue, "Command arguments missing or a not a map.");
1588 }
1589
1590 // At least one of the 'deleted-leases' or 'leases' must be present.
1591 auto deleted_leases = cmd_args_->get("deleted-leases");
1592 auto leases = cmd_args_->get("leases");
1593
1594 if (!deleted_leases && !leases) {
1595 isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1596 " specified");
1597 }
1598
1599 // Make sure that 'deleted-leases' is a list, if present.
1600 if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1601 isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1602 }
1603
1604 // Make sure that 'leases' is a list, if present.
1605 if (leases && (leases->getType() != Element::list)) {
1606 isc_throw(BadValue, "the 'leases' parameter must be a list");
1607 }
1608
1609 // Parse deleted leases without deleting them from the database
1610 // yet. If any of the deleted leases or new leases appears to be
1611 // malformed we can easily rollback.
1612 std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1613 if (deleted_leases) {
1614 auto leases_list = deleted_leases->listValue();
1615
1616 // Iterate over leases to be deleted.
1617 for (auto const& lease_params : leases_list) {
1618 // Parsing the lease may throw and it means that the lease
1619 // information is malformed.
1620 Parameters p = getParameters(true, lease_params);
1621 auto lease = getIPv6LeaseForDelete(p);
1622 parsed_deleted_list.push_back(std::make_pair(p, lease));
1623 }
1624 }
1625
1626 // Parse new/updated leases without affecting the database to detect
1627 // any errors that should cause an error response.
1628 std::list<Lease6Ptr> parsed_leases_list;
1629 if (leases) {
1631
1632 // Iterate over all leases.
1633 auto leases_list = leases->listValue();
1634 for (auto const& lease_params : leases_list) {
1635
1636 Lease6Parser parser;
1637 bool force_update;
1638
1639 // If parsing the lease fails we throw, as it indicates that the
1640 // command is malformed.
1641 Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1642 parsed_leases_list.push_back(lease6);
1643 }
1644 }
1645
1646 // Count successful deletions and updates.
1647 size_t success_count = 0;
1648
1649 ElementPtr failed_deleted_list;
1650 if (!parsed_deleted_list.empty()) {
1651
1652 // Iterate over leases to be deleted.
1653 for (auto const& lease_params_pair : parsed_deleted_list) {
1654
1655 // This part is outside of the try-catch because an exception
1656 // indicates that the command is malformed.
1657 Parameters p = lease_params_pair.first;
1658 auto lease = lease_params_pair.second;
1659
1660 try {
1661 if (lease) {
1662 // This may throw if the lease couldn't be deleted for
1663 // any reason, but we still want to proceed with other
1664 // leases.
1665 if (LeaseMgrFactory::instance().deleteLease(lease)) {
1666 ++success_count;
1668
1669 } else {
1670 // Lazy creation of the list of leases which failed to delete.
1671 if (!failed_deleted_list) {
1672 failed_deleted_list = Element::createList();
1673 }
1674
1675 // If the lease doesn't exist we also want to put it
1676 // on the list of leases which failed to delete. That
1677 // corresponds to the lease6-del command which returns
1678 // an error when the lease doesn't exist.
1679 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1680 p.addr, p.duid,
1682 "lease not found"));
1683 }
1684 }
1685
1686 } catch (const std::exception& ex) {
1687 // Lazy creation of the list of leases which failed to delete.
1688 if (!failed_deleted_list) {
1689 failed_deleted_list = Element::createList();
1690 }
1691 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1692 p.addr, p.duid,
1694 ex.what()));
1695 }
1696 }
1697 }
1698
1699 // Process leases to be added or/and updated.
1700 ElementPtr failed_leases_list;
1701 if (!parsed_leases_list.empty()) {
1703
1704 // Iterate over all leases.
1705 for (auto const& lease : parsed_leases_list) {
1706
1707 auto result = CONTROL_RESULT_SUCCESS;
1708 std::ostringstream text;
1709 try {
1710 if (!MultiThreadingMgr::instance().getMode()) {
1711 // Not multi-threading.
1712 addOrUpdate6(lease, true);
1713 } else {
1714 // Multi-threading, try to lock first to avoid a race.
1715 ResourceHandler resource_handler;
1716 if (resource_handler.tryLock(lease->type_, lease->addr_)) {
1717 addOrUpdate6(lease, true);
1718 } else {
1720 "ResourceBusy: IP address:" << lease->addr_
1721 << " could not be updated.");
1722 }
1723 }
1724
1725 ++success_count;
1726 } catch (const LeaseCmdsConflict& ex) {
1727 result = CONTROL_RESULT_CONFLICT;
1728 text << ex.what();
1729
1730 } catch (const std::exception& ex) {
1731 result = CONTROL_RESULT_ERROR;
1732 text << ex.what();
1733 }
1734 // Handle an error.
1735 if (result != CONTROL_RESULT_SUCCESS) {
1736 // Lazy creation of the list of leases which failed to add/update.
1737 if (!failed_leases_list) {
1738 failed_leases_list = Element::createList();
1739 }
1740 failed_leases_list->add(createFailedLeaseMap(lease->type_,
1741 lease->addr_,
1742 lease->duid_,
1743 result,
1744 text.str()));
1745 }
1746 }
1747 }
1748
1749 // Start preparing the response.
1750 ElementPtr args;
1751
1752 if (failed_deleted_list || failed_leases_list) {
1753 // If there are any failed leases, let's include them in the response.
1754 args = Element::createMap();
1755
1756 // failed-deleted-leases
1757 if (failed_deleted_list) {
1758 args->set("failed-deleted-leases", failed_deleted_list);
1759 }
1760
1761 // failed-leases
1762 if (failed_leases_list) {
1763 args->set("failed-leases", failed_leases_list);
1764 }
1765 }
1766
1767 // Send the success response and include failed leases.
1768 std::ostringstream resp_text;
1769 resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
1770 auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
1771 CONTROL_RESULT_EMPTY, resp_text.str(), args);
1772 setResponse(handle, answer);
1773
1776 .arg(success_count);
1777
1778 } catch (const std::exception& ex) {
1779 // Unable to parse the command and similar issues.
1781 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1782 .arg(ex.what());
1783 setErrorResponse(handle, ex.what());
1784 return (CONTROL_RESULT_ERROR);
1785 }
1786
1787 return (0);
1788}
1789
1790int
1792 Parameters p;
1793 Lease6Ptr lease6;
1795 try {
1796 extractCommand(handle);
1797 p = getParameters(true, cmd_args_);
1798
1799 switch (p.query_type) {
1800 case Parameters::TYPE_ADDR: {
1801 // If address was specified explicitly, let's use it as is.
1802
1803 // Let's see if there's such a lease at all.
1805 if (!lease6) {
1806 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1807 return (0);
1808 }
1809 break;
1810 }
1812 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
1813 break;
1814 }
1815 case Parameters::TYPE_DUID: {
1816 if (!p.duid) {
1817 isc_throw(InvalidParameter, "Program error: Query by duid "
1818 "requires duid to be specified");
1819 }
1820
1821 // Let's see if there's such a lease at all.
1823 p.iaid, p.subnet_id);
1824 if (!lease6) {
1825 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1826 return (0);
1827 }
1828 break;
1829 }
1830 default: {
1831 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1832 break;
1833 }
1834 }
1835
1836 if (LeaseMgrFactory::instance().deleteLease(lease6)) {
1837 setSuccessResponse(handle, "IPv6 lease deleted.");
1839 } else {
1840 setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1841 }
1842
1843 // Queue an NCR to remove DNS if configured and the lease has it.
1844 if (p.updateDDNS) {
1845 queueNCR(CHG_REMOVE, lease6);
1846 }
1847
1848 } catch (const std::exception& ex) {
1850 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1851 .arg(ex.what());
1852 setErrorResponse(handle, ex.what());
1853 return (1);
1854 }
1855
1857 .arg(lease6->addr_.toText());
1858 return (0);
1859}
1860
1861int
1863 try {
1864 extractCommand(handle);
1865
1866 // We need the lease to be specified.
1867 if (!cmd_args_) {
1868 isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
1869 }
1870
1871 // Get the parameters specified by the user first.
1873 Lease4Ptr lease4;
1874 Lease4Parser parser;
1875 bool force_create = false;
1876
1877 // The parser does sanity checks (if the address is in scope, if
1878 // subnet-id is valid, etc)
1879 lease4 = parser.parse(config, cmd_args_, force_create);
1880 bool added = false;
1881 if (!MultiThreadingMgr::instance().getMode()) {
1882 // Not multi-threading.
1883 added = addOrUpdate4(lease4, force_create);
1884 } else {
1885 // Multi-threading, try to lock first to avoid a race.
1886 ResourceHandler4 resource_handler;
1887 if (resource_handler.tryLock4(lease4->addr_)) {
1888 added = addOrUpdate4(lease4, force_create);
1889 } else {
1891 "ResourceBusy: IP address:" << lease4->addr_
1892 << " could not be updated.");
1893 }
1894 }
1895
1896 if (added) {
1897 setSuccessResponse(handle, "IPv4 lease added.");
1898 } else {
1899 setSuccessResponse(handle, "IPv4 lease updated.");
1900 }
1903 .arg(lease4->addr_.toText());
1904
1905 } catch (const LeaseCmdsConflict& ex) {
1907 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1908 .arg(ex.what());
1910 return (0);
1911
1912 } catch (const std::exception& ex) {
1914 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1915 .arg(ex.what());
1916 setErrorResponse(handle, ex.what());
1917 return (1);
1918 }
1919
1920 return (0);
1921}
1922
1923int
1925 try {
1926 extractCommand(handle);
1927
1928 // We need the lease to be specified.
1929 if (!cmd_args_) {
1930 isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
1931 }
1932
1933 // Get the parameters specified by the user first.
1935 Lease6Ptr lease6;
1936 Lease6Parser parser;
1937 bool force_create = false;
1938
1939 // The parser does sanity checks (if the address is in scope, if
1940 // subnet-id is valid, etc)
1941 lease6 = parser.parse(config, cmd_args_, force_create);
1942 bool added = false;
1943 if (!MultiThreadingMgr::instance().getMode()) {
1944 // Not multi-threading.
1945 added = addOrUpdate6(lease6, force_create);
1946 } else {
1947 // Multi-threading, try to lock first to avoid a race.
1948 ResourceHandler resource_handler;
1949 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
1950 added = addOrUpdate6(lease6, force_create);
1951 } else {
1953 "ResourceBusy: IP address:" << lease6->addr_
1954 << " could not be updated.");
1955 }
1956 }
1957
1958 if (added) {
1959 setSuccessResponse(handle, "IPv6 lease added.");
1960 } else {
1961 setSuccessResponse(handle, "IPv6 lease updated.");
1962 }
1965 .arg(lease6->addr_.toText());
1966
1967 } catch (const LeaseCmdsConflict& ex) {
1969 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1970 .arg(ex.what());
1972 return (0);
1973
1974 } catch (const std::exception& ex) {
1976 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1977 .arg(ex.what());
1978 setErrorResponse(handle, ex.what());
1979 return (1);
1980 }
1981
1982 return (0);
1983}
1984
1985int
1987 try {
1988 extractCommand(handle);
1989
1990 SimpleParser parser;
1991 SubnetID id = 0;
1992
1993 size_t num = 0; // number of leases deleted
1994 stringstream ids; // a text with subnet-ids being wiped
1995
1996 // The subnet-id parameter is now optional.
1997 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
1998 id = parser.getUint32(cmd_args_, "subnet-id");
1999 }
2000
2001 if (id) {
2002 // Wipe a single subnet.
2004 ids << " " << id;
2005
2006 auto assigned_observation = StatsMgr::instance().getObservation(
2007 StatsMgr::generateName("subnet", id, "assigned-addresses"));
2008
2009 int64_t previous_assigned = 0;
2010
2011 if (assigned_observation) {
2012 previous_assigned = assigned_observation->getInteger().first;
2013 }
2014
2015 auto declined_observation = StatsMgr::instance().getObservation(
2016 StatsMgr::generateName("subnet", id, "declined-addresses"));
2017
2018 int64_t previous_declined = 0;
2019
2020 if (declined_observation) {
2021 previous_declined = declined_observation->getInteger().first;
2022 }
2023
2025 StatsMgr::generateName("subnet", id, "assigned-addresses"),
2026 static_cast<int64_t>(0));
2027
2029 StatsMgr::generateName("subnet", id, "declined-addresses"),
2030 static_cast<int64_t>(0));
2031
2032 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(id);
2033 if (sub) {
2034 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2035 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2036 StatsMgr::generateName("pool", pool->getID(),
2037 "assigned-addresses")));
2038 if (!StatsMgr::instance().getObservation(name_aa)) {
2039 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2040 }
2041
2042 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2043 StatsMgr::generateName("pool", pool->getID(),
2044 "declined-addresses")));
2045 if (!StatsMgr::instance().getObservation(name_da)) {
2046 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2047 }
2048 }
2049 }
2050
2051 StatsMgr::instance().addValue("assigned-addresses", -previous_assigned);
2052
2053 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2054 } else {
2055 // Wipe them all!
2057 ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
2058 const Subnet4Collection* subs = subnets->getAll();
2059
2060 // Go over all subnets and wipe leases in each of them.
2061 for (auto const& sub : *subs) {
2062 num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
2063 ids << " " << sub->getID();
2065 StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
2066 static_cast<int64_t>(0));
2067
2069 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2070 static_cast<int64_t>(0));
2071
2072 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2073 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2074 StatsMgr::generateName("pool", pool->getID(),
2075 "assigned-addresses")));
2076 if (!StatsMgr::instance().getObservation(name_aa)) {
2077 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2078 }
2079
2080 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2081 StatsMgr::generateName("pool", pool->getID(),
2082 "declined-addresses")));
2083 if (!StatsMgr::instance().getObservation(name_da)) {
2084 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2085 }
2086 }
2087 }
2088
2089 StatsMgr::instance().setValue("assigned-addresses", static_cast<int64_t>(0));
2090
2091 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2092 }
2093
2094 stringstream tmp;
2095 tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
2097 : CONTROL_RESULT_EMPTY, tmp.str());
2098 setResponse(handle, response);
2099 } catch (const std::exception& ex) {
2101 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2102 .arg(ex.what());
2103 setErrorResponse(handle, ex.what());
2104 return (1);
2105 }
2106
2108 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2109 return (0);
2110}
2111
2112int
2114 try {
2115 extractCommand(handle);
2116
2117 SimpleParser parser;
2118 SubnetID id = 0;
2119
2120 size_t num = 0; // number of leases deleted
2121 stringstream ids; // a text with subnet-ids being wiped
2122
2127
2128 // The subnet-id parameter is now optional.
2129 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2130 id = parser.getUint32(cmd_args_, "subnet-id");
2131 }
2132
2133 if (id) {
2134 // Wipe a single subnet.
2136 ids << " " << id;
2137
2138 auto assigned_na_observation = StatsMgr::instance().getObservation(
2139 StatsMgr::generateName("subnet", id, "assigned-nas"));
2140
2141 int64_t previous_assigned_na = 0;
2142
2143 if (assigned_na_observation) {
2144 previous_assigned_na = assigned_na_observation->getInteger().first;
2145 }
2146
2147 auto assigned_pd_observation = StatsMgr::instance().getObservation(
2148 StatsMgr::generateName("subnet", id, "assigned-pds"));
2149
2150 int64_t previous_assigned_pd = 0;
2151
2152 if (assigned_pd_observation) {
2153 previous_assigned_pd = assigned_pd_observation->getInteger().first;
2154 }
2155
2156 auto declined_observation = StatsMgr::instance().getObservation(
2157 StatsMgr::generateName("subnet", id, "declined-addresses"));
2158
2159 int64_t previous_declined = 0;
2160
2161 if (declined_observation) {
2162 previous_declined = declined_observation->getInteger().first;
2163 }
2164
2166 StatsMgr::generateName("subnet", id, "assigned-nas" ),
2167 static_cast<int64_t>(0));
2168
2170 StatsMgr::generateName("subnet", id, "assigned-pds"),
2171 static_cast<int64_t>(0));
2172
2174 StatsMgr::generateName("subnet", id, "declined-addresses"),
2175 static_cast<int64_t>(0));
2176
2178 StatsMgr::generateName("subnet", id, "registered-nas"),
2179 static_cast<int64_t>(0));
2180
2181 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(id);
2182 if (sub) {
2183 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2184 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2185 StatsMgr::generateName("pool", pool->getID(),
2186 "assigned-nas")));
2187 if (!StatsMgr::instance().getObservation(name_anas)) {
2188 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2189 }
2190
2191 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2192 StatsMgr::generateName("pool", pool->getID(),
2193 "declined-addresses")));
2194 if (!StatsMgr::instance().getObservation(name_da)) {
2195 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2196 }
2197 }
2198
2199 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2200 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2201 StatsMgr::generateName("pd-pool", pool->getID(),
2202 "assigned-pds")));
2203 if (!StatsMgr::instance().getObservation(name_apds)) {
2204 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2205 }
2206 }
2207 }
2208
2209 StatsMgr::instance().addValue("assigned-nas", -previous_assigned_na);
2210
2211 StatsMgr::instance().addValue("assigned-pds", -previous_assigned_pd);
2212
2213 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2214 } else {
2215 // Wipe them all!
2217 ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2218 const Subnet6Collection* subs = subnets->getAll();
2219
2220 // Go over all subnets and wipe leases in each of them.
2221 for (auto const& sub : *subs) {
2222 num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2223 ids << " " << sub->getID();
2225 StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2226 static_cast<int64_t>(0));
2227
2229 StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2230 static_cast<int64_t>(0));
2231
2233 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2234 static_cast<int64_t>(0));
2235
2237 StatsMgr::generateName("subnet", sub->getID(), "registered-nas"),
2238 static_cast<int64_t>(0));
2239
2240 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2241 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2242 StatsMgr::generateName("pool", pool->getID(),
2243 "assigned-nas")));
2244 if (!StatsMgr::instance().getObservation(name_anas)) {
2245 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2246 }
2247
2248 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2249 StatsMgr::generateName("pool", pool->getID(),
2250 "declined-addresses")));
2251 if (!StatsMgr::instance().getObservation(name_da)) {
2252 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2253 }
2254 }
2255
2256 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2257 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2258 StatsMgr::generateName("pd-pool", pool->getID(),
2259 "assigned-pds")));
2260 if (!StatsMgr::instance().getObservation(name_apds)) {
2261 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2262 }
2263 }
2264 }
2265
2266 StatsMgr::instance().setValue("assigned-nas", static_cast<int64_t>(0));
2267
2268 StatsMgr::instance().setValue("assigned-pds", static_cast<int64_t>(0));
2269
2270 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2271 }
2272
2273 stringstream tmp;
2274 tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2276 : CONTROL_RESULT_EMPTY, tmp.str());
2277 setResponse(handle, response);
2278 } catch (const std::exception& ex) {
2280 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2281 .arg(ex.what());
2282 setErrorResponse(handle, ex.what());
2283 return (1);
2284 }
2285
2287 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2288 return (0);
2289}
2290
2293 Lease6Ptr lease6;
2294
2295 switch (parameters.query_type) {
2296 case Parameters::TYPE_ADDR: {
2297 // If address was specified explicitly, let's use it as is.
2298
2299 // Let's see if there's such a lease at all.
2300 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2301 parameters.addr);
2302 if (!lease6) {
2303 lease6.reset(new Lease6());
2304 lease6->addr_ = parameters.addr;
2305 }
2306 break;
2307 }
2309 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2310 break;
2311 }
2312 case Parameters::TYPE_DUID: {
2313 if (!parameters.duid) {
2314 isc_throw(InvalidParameter, "Program error: Query by duid "
2315 "requires duid to be specified");
2316 }
2317
2318 // Let's see if there's such a lease at all.
2319 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2320 *parameters.duid,
2321 parameters.iaid,
2322 parameters.subnet_id);
2323 break;
2324 }
2325 default:
2326 isc_throw(InvalidOperation, "Unknown query type: "
2327 << static_cast<int>(parameters.query_type));
2328 }
2329
2330 return (lease6);
2331}
2332
2335 short family) const {
2336 ConstElementPtr param = params->get(name);
2337 if (!param) {
2338 isc_throw(BadValue, "'" << name << "' parameter is missing.");
2339 }
2340
2341 if (param->getType() != Element::string) {
2342 isc_throw(BadValue, "'" << name << "' is not a string.");
2343 }
2344
2345 IOAddress addr(0);
2346 try {
2347 addr = IOAddress(param->stringValue());
2348 } catch (const std::exception& ex) {
2349 isc_throw(BadValue, "'" << param->stringValue()
2350 << "' is not a valid IP address.");
2351 }
2352
2353 if (addr.getFamily() != family) {
2354 isc_throw(BadValue, "Invalid "
2355 << (family == AF_INET6 ? "IPv6" : "IPv4")
2356 << " address specified: " << param->stringValue());
2357 }
2358
2359 return (addr);
2360}
2361
2362int
2364 std::stringstream ss;
2365 int resp_code = CONTROL_RESULT_ERROR;
2366
2367 try {
2368 extractCommand(handle);
2369
2370 // Get the target lease address. Invalid value will throw.
2371 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2372
2373 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2374 ss << "DDNS updating is not enabled";
2375 resp_code = CONTROL_RESULT_CONFLICT;
2376 } else {
2377 // Find the lease.
2379 if (!lease) {
2380 ss << "No lease found for: " << addr.toText();
2381 resp_code = CONTROL_RESULT_EMPTY;
2382 } else if (lease->hostname_.empty()) {
2383 ss << "Lease for: " << addr.toText()
2384 << ", has no hostname, nothing to update";
2385 resp_code = CONTROL_RESULT_CONFLICT;
2386 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2387 ss << "Neither forward nor reverse updates enabled for lease for: "
2388 << addr.toText();
2389 resp_code = CONTROL_RESULT_CONFLICT;
2390 } else {
2391 // We have a lease with a hostname and updates in at least
2392 // one direction enabled. Queue an NCR for it.
2393 queueNCR(CHG_ADD, lease);
2394 ss << "NCR generated for: " << addr.toText()
2395 << ", hostname: " << lease->hostname_;
2396 setSuccessResponse(handle, ss.str());
2398 return (0);
2399 }
2400 }
2401 } catch (const std::exception& ex) {
2402 ss << ex.what();
2403 }
2404
2406 setErrorResponse(handle, ss.str(), resp_code);
2407 return (resp_code == CONTROL_RESULT_EMPTY || resp_code == CONTROL_RESULT_CONFLICT ? 0 : 1);
2408}
2409
2410int
2412 std::stringstream ss;
2413 int resp_code = CONTROL_RESULT_ERROR;
2414
2415 try {
2416 extractCommand(handle);
2417
2418 // Get the target lease address. Invalid value will throw.
2419 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2420
2421 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2422 ss << "DDNS updating is not enabled";
2423 resp_code = CONTROL_RESULT_CONFLICT;
2424 } else {
2425 // Find the lease.
2427 if (!lease) {
2428 ss << "No lease found for: " << addr.toText();
2429 resp_code = CONTROL_RESULT_EMPTY;
2430 } else if (lease->hostname_.empty()) {
2431 ss << "Lease for: " << addr.toText()
2432 << ", has no hostname, nothing to update";
2433 resp_code = CONTROL_RESULT_CONFLICT;
2434 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2435 ss << "Neither forward nor reverse updates enabled for lease for: "
2436 << addr.toText();
2437 resp_code = CONTROL_RESULT_CONFLICT;
2438 } else {
2439 // We have a lease with a hostname and updates in at least
2440 // one direction enabled. Queue an NCR for it.
2441 queueNCR(CHG_ADD, lease);
2442 ss << "NCR generated for: " << addr.toText()
2443 << ", hostname: " << lease->hostname_;
2444 setSuccessResponse(handle, ss.str());
2446 return (0);
2447 }
2448 }
2449 } catch (const std::exception& ex) {
2450 ss << ex.what();
2451 }
2452
2454 setErrorResponse(handle, ss.str(), resp_code);
2455 return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2456}
2457
2460 const IOAddress& lease_address,
2461 const DuidPtr& duid,
2462 const int control_result,
2463 const std::string& error_message) const {
2464 auto failed_lease_map = Element::createMap();
2465 failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2466
2467 if (!lease_address.isV6Zero()) {
2468 failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2469
2470 } else if (duid) {
2471 failed_lease_map->set("duid", Element::create(duid->toText()));
2472 }
2473
2474 // Associate the result with the lease.
2475 failed_lease_map->set("result", Element::create(control_result));
2476 failed_lease_map->set("error-message", Element::create(error_message));
2477
2478 return (failed_lease_map);
2479}
2480
2481int
2483 bool v4 = true;
2484 try {
2485 extractCommand(handle);
2486 v4 = (cmd_name_ == "lease4-write");
2487
2488 if (!cmd_args_) {
2489 isc_throw(isc::BadValue, "no parameters specified for the command");
2490 }
2491
2492 ConstElementPtr file = cmd_args_->get("filename");
2493 if (!file) {
2494 isc_throw(BadValue, "'filename' parameter not specified");
2495 }
2496 if (file->getType() != Element::string) {
2497 isc_throw(BadValue, "'filename' parameter must be a string");
2498 }
2499
2500 std::string filename;
2501 try {
2502 filename = CfgMgr::instance().validatePath(file->stringValue());
2503 } catch (const SecurityWarn& ex) {
2505 .arg(ex.what());
2506 filename = file->stringValue();
2507 } catch (const std::exception& ex) {
2508 isc_throw(BadValue, "'filename' parameter is invalid: " << ex.what());
2509 }
2510
2511 if (v4) {
2513 } else {
2515 }
2516
2517 ostringstream s;
2518 s << (v4 ? "IPv4" : "IPv6")
2519 << " lease database into '"
2520 << filename << "'.";
2522 setResponse(handle, response);
2523 } catch (const FatalException& ex) {
2524 if (v4) {
2526 .arg(ex.what());
2527 } else {
2529 .arg(ex.what());
2530 }
2533 } catch (const std::exception& ex) {
2534 setErrorResponse(handle, ex.what());
2535 return (CONTROL_RESULT_ERROR);
2536 }
2537
2538 return (0);
2539}
2540
2541void
2544 uint32_t offer_lifetime;
2545 callout_handle.getArgument("offer_lifetime", offer_lifetime);
2546 if (!offer_lifetime) {
2547 // Offers leases are not being persisted, nothing to do.
2548 return;
2549 }
2550
2551 // Get the remaining arguments we need.
2552 Pkt4Ptr query;
2553 Pkt4Ptr response;
2554 Lease4CollectionPtr leases;
2555
2556 callout_handle.getArgument("query4", query);
2557 callout_handle.getArgument("response4", response);
2558 callout_handle.getArgument("leases4", leases);
2559
2560 if (!leases || leases->empty() || !((*leases)[0])) {
2561 isc_throw(Unexpected, "lease4Offer - no lease!");
2562 }
2563
2564 Lease4Ptr lease = (*leases)[0];
2565 try {
2566 if (mgr->evaluateVariables(query, response, lease)) {
2568 }
2569 } catch (const NoSuchLease&) {
2570 isc_throw(LeaseCmdsConflict, "failed to update"
2571 " the lease with address " << lease->addr_ <<
2572 " either because the lease has been"
2573 " deleted or it has changed in the database");
2574 } catch (const std::exception& ex) {
2575 isc_throw(Unexpected, "evaluating binding variables failed for: "
2576 << query->getLabel() << ", :" << ex.what());
2577 }
2578}
2579
2580void
2583 Pkt4Ptr query;
2584 Pkt4Ptr response;
2585 Lease4CollectionPtr leases;
2586
2587 // Get the necessary arguments.
2588 callout_handle.getArgument("query4", query);
2589 callout_handle.getArgument("response4", response);
2590 callout_handle.getArgument("leases4", leases);
2591
2592 if (!leases) {
2593 isc_throw(Unexpected, "leases4Committed - leases is null");
2594 }
2595
2596 // In some cases we may have no lease, e.g. DHCPNAK,
2597 // or no response e.g. DHCPRELEASE.
2598 if (leases->empty() || !response || (response->getType() != DHCPACK)) {
2599 return;
2600 }
2601
2602 Lease4Ptr lease = (*leases)[0];
2603 if (!lease) {
2604 isc_throw(Unexpected, "leases4Committed - lease is null");
2605 }
2606
2607 try {
2608 if (mgr->evaluateVariables(query, response, lease)) {
2610 }
2611 } catch (const NoSuchLease&) {
2612 isc_throw(LeaseCmdsConflict, "failed to update"
2613 " the lease with address " << lease->addr_ <<
2614 " either because the lease has been"
2615 " deleted or it has changed in the database");
2616 } catch (const std::exception& ex) {
2617 isc_throw(Unexpected, "evaluating binding variables failed for: "
2618 << query->getLabel() << ", :" << ex.what());
2619 }
2620}
2621
2622void
2625 Pkt6Ptr query;
2626 Pkt6Ptr response;
2627 Lease6CollectionPtr leases;
2628
2629 // Get the necessary arguments.
2630 callout_handle.getArgument("query6", query);
2631 callout_handle.getArgument("response6", response);
2632 callout_handle.getArgument("leases6", leases);
2633
2634 if (!leases) {
2635 isc_throw(Unexpected, "leases6Committed - leases is null");
2636 }
2637
2638 // In some cases we may have no active leases or no response.
2639 if (leases->empty() || !response) {
2640 return;
2641 }
2642
2643 int attempted = 0;
2644 int failed = 0;
2645 for (auto lease : *leases) {
2646 try {
2647 if (!lease) {
2648 isc_throw(Unexpected, "leases6Committed - lease is null");
2649 }
2650
2656 // Only update a lease if its active.
2657 if (lease->valid_lft_) {
2658 ++attempted;
2659 if (mgr->evaluateVariables(query, response, lease)) {
2661 }
2662 }
2663 } catch (const NoSuchLease&) {
2664 ++failed;
2666 .arg(lease->addr_.toText())
2667 .arg(query->getLabel());
2668 } catch (const std::exception& ex) {
2669 ++failed;
2671 .arg(query->getLabel())
2672 .arg(lease->addr_.toText())
2673 .arg(ex.what());
2674 }
2675 }
2676
2677 if (failed) {
2678 isc_throw(Unexpected, failed << " out of " << attempted
2679 << " leases failed to update for "
2680 << query->getLabel());
2681 }
2682}
2683
2684int
2686 return (impl_->leaseAddHandler(handle));
2687}
2688
2689int
2691 return (impl_->lease6BulkApplyHandler(handle));
2692}
2693
2694int
2696 return (impl_->leaseGetHandler(handle));
2697}
2698
2699int
2701 return (impl_->leaseGetAllHandler(handle));
2702}
2703
2704int
2706 return (impl_->leaseGetPageHandler(handle));
2707}
2708
2709int
2711 return (impl_->leaseGetByHwAddressHandler(handle));
2712}
2713
2714int
2716 return (impl_->leaseGetByClientIdHandler(handle));
2717}
2718
2719int
2721 return (impl_->leaseGetByDuidHandler(handle));
2722}
2723
2724int
2726 return (impl_->leaseGetByStateHandler(handle));
2727}
2728
2729int
2731 return (impl_->leaseGetByHostnameHandler(handle));
2732}
2733
2734int
2736 return (impl_->lease4DelHandler(handle));
2737}
2738
2739int
2741 return (impl_->lease6DelHandler(handle));
2742}
2743
2744int
2746 return (impl_->lease4UpdateHandler(handle));
2747}
2748
2749int
2751 return (impl_->lease6UpdateHandler(handle));
2752}
2753
2754int
2757 return (impl_->lease4WipeHandler(handle));
2758}
2759
2760int
2763 return (impl_->lease6WipeHandler(handle));
2764}
2765
2766int
2768 return (impl_->lease4ResendDdnsHandler(handle));
2769}
2770
2771int
2773 return (impl_->lease6ResendDdnsHandler(handle));
2774}
2775
2776int
2778 return (impl_->leaseWriteHandler(handle));
2779}
2780
2782}
2783
2784
2785void
2788 impl_->lease4Offer(callout_handle, mgr);
2789}
2790
2791void
2794 impl_->leases4Committed(callout_handle, mgr);
2795}
2796
2797void
2800 impl_->leases6Committed(callout_handle, mgr);
2801}
2802
2803} // end of namespace lease_cmds
2804} // end of namespace isc
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition duid.cc:50
static const DUID & EMPTY()
Defines the constant "empty" DUID.
Definition duid.cc:55
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:300
@ map
Definition data.h:160
@ integer
Definition data.h:153
@ boolean
Definition data.h:155
@ list
Definition data.h:159
@ string
Definition data.h:157
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:355
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:350
Exception thrown when a command failed due to a conflict.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if an unrecoverable error occurs.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown when an unexpected error condition occurs.
Base class that command handler implementers may use for common tasks.
Definition cmds_impl.h:21
std::string cmd_name_
Stores the command name extracted by a call to extractCommand.
Definition cmds_impl.h:69
void setErrorResponse(hooks::CalloutHandle &handle, const std::string &text, int status=CONTROL_RESULT_ERROR)
Set the callout argument "response" to indicate an error.
Definition cmds_impl.h:54
data::ConstElementPtr cmd_args_
Stores the command arguments extracted by a call to extractCommand.
Definition cmds_impl.h:72
void extractCommand(hooks::CalloutHandle &handle)
Extracts the command name and arguments from a Callout handle.
Definition cmds_impl.h:29
void setSuccessResponse(hooks::CalloutHandle &handle, const std::string &text)
Set the callout argument "response" to indicate success.
Definition cmds_impl.h:43
void setResponse(hooks::CalloutHandle &handle, data::ConstElementPtr &response)
Set the callout argument "response" to the given response.
Definition cmds_impl.h:64
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
std::string validatePath(const std::string data_path) const
Validates a file path against the supported directory for DHCP data.
Definition cfgmgr.cc:40
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Definition duid.cc:73
Holds DUID (DHCPv6 Unique Identifier).
Definition duid.h:142
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual size_t wipeLeases6(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
static void updateStatsOnAdd(const Lease4Ptr &lease)
Update in-memory stats when adding a v4 lease.
virtual Lease4Collection getLeases4(SubnetID subnet_id) const =0
Returns all IPv4 leases for the particular subnet identifier.
virtual void writeLeases6(const std::string &filename)=0
Write V6 leases to a file.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
static void updateStatsOnUpdate(const Lease4Ptr &existing, const Lease4Ptr &lease)
Update in-memory stats when updating a v4 lease.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual size_t wipeLeases4(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual void writeLeases4(const std::string &filename)=0
Write V4 leases to a file.
static void updateStatsOnDelete(const Lease4Ptr &lease)
Update in-memory stats when deleting a v4 lease.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
Wraps value holding size of the page with leases.
Definition lease_mgr.h:47
Attempt to update lease that was not there.
Resource race avoidance RAII handler for DHCPv4.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
Resource race avoidance RAII handler.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
Per-packet callout handle.
void getArgument(const std::string &name, T &value) const
Get argument.
Parser for Lease4 structure.
virtual isc::dhcp::Lease4Ptr parse(isc::dhcp::ConstSrvConfigPtr &cfg, const isc::data::ConstElementPtr &lease_info, bool &force_create)
Parses Element tree and tries to convert to Lease4.
Parser for Lease6 structure.
virtual isc::dhcp::Lease6Ptr parse(isc::dhcp::ConstSrvConfigPtr &cfg, const isc::data::ConstElementPtr &lease_info, bool &force_create)
Parses Element tree and tries to convert to Lease4.
Parameters specified for lease commands.
Definition lease_cmds.cc:71
uint32_t iaid
IAID identifier used for v6 leases.
HWAddrPtr hwaddr
Specifies hardware address (used when query_type is TYPE_HWADDR).
Definition lease_cmds.cc:89
Lease::Type lease_type
Lease type (NA,TA or PD) used for v6 leases.
Type query_type
specifies parameter types
Type
specifies type of query (by IP addr, by hwaddr, by DUID)
Definition lease_cmds.cc:75
@ TYPE_CLIENT_ID
query by client identifier (v4 only).
Definition lease_cmds.cc:79
@ TYPE_HWADDR
query by hardware address (v4 only)
Definition lease_cmds.cc:77
@ TYPE_ADDR
query by IP address (either v4 or v6)
Definition lease_cmds.cc:76
isc::dhcp::ClientIdPtr client_id
Specifies identifier value (used when query_type is TYPE_CLIENT_ID).
Definition lease_cmds.cc:95
static Type txtToType(const std::string &txt)
Attempts to covert text to one of specified types.
bool updateDDNS
Indicates whether or not DNS should be updated.
IOAddress addr
Specifies IPv4/v6 address (used when query_type is TYPE_ADDR).
Definition lease_cmds.cc:86
SubnetID subnet_id
Specifies subnet-id (always used).
Definition lease_cmds.cc:83
isc::dhcp::DuidPtr duid
Specifies identifier value (used when query_type is TYPE_DUID).
Definition lease_cmds.cc:92
Wrapper class around reservation command handlers.
Definition lease_cmds.cc:67
int lease4DelHandler(CalloutHandle &handle)
lease4-del command handler
IOAddress getAddressParam(ConstElementPtr params, const std::string name, short family=AF_INET) const
static void lease4Offer(CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
lease4_offer hookpoint handler.
ElementPtr createFailedLeaseMap(const Lease::Type &lease_type, const IOAddress &lease_address, const DuidPtr &duid, const int control_result, const std::string &error_message) const
Returns a map holding brief information about a lease which failed to be deleted, updated or added.
int leaseGetByStateHandler(hooks::CalloutHandle &handle)
lease4-get-by-state and lease6-get-by-state commands handler
static bool addOrUpdate6(Lease6Ptr lease, bool force_create)
Add or update lease.
int lease6BulkApplyHandler(CalloutHandle &handle)
lease6-bulk-apply command handler
int leaseGetByDuidHandler(hooks::CalloutHandle &handle)
lease6-get-by-duid command handler
int lease6UpdateHandler(CalloutHandle &handle)
lease6-update handler
int leaseGetPageHandler(hooks::CalloutHandle &handle)
lease4-get-page, lease6-get-page commands handler
Lease6Ptr getIPv6LeaseForDelete(const Parameters &parameters) const
Convenience function fetching IPv6 address to be used to delete a lease.
int leaseGetByHostnameHandler(hooks::CalloutHandle &handle)
lease4-get-by-hostname and lease6-get-by-hostname commands handler
int lease6DelHandler(CalloutHandle &handle)
lease6-del command handler
int leaseGetByHwAddressHandler(hooks::CalloutHandle &handle)
lease4-get-by-hw-address, lease6-get-by-hw-address command handler
static ConstElementPtr getExtendedInfo6(const Lease6Ptr &lease)
Get DHCPv6 extended info.
int leaseGetHandler(CalloutHandle &handle)
lease4-get, lease6-get command handler
static bool addOrUpdate4(Lease4Ptr lease, bool force_create)
Add or update lease.
static void leases4Committed(CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases4_committed hookpoint handler.
int lease6WipeHandler(CalloutHandle &handle)
lease6-wipe handler
int leaseGetByClientIdHandler(hooks::CalloutHandle &handle)
lease4-get-by-client-id command handler
int lease6ResendDdnsHandler(CalloutHandle &handle)
lease6-resend-ddns handler
int leaseAddHandler(CalloutHandle &handle)
lease4-add, lease6-add command handler
int lease4ResendDdnsHandler(CalloutHandle &handle)
lease4-resend-ddns handler
Parameters getParameters(bool v6, const ConstElementPtr &args)
Extracts parameters required for reservation-get and reservation-del.
static void leases6Committed(CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases6_committed hookpoint handler.
int lease4UpdateHandler(CalloutHandle &handle)
lease4-update handler
int lease4WipeHandler(CalloutHandle &handle)
lease4-wipe handler
int leaseGetAllHandler(CalloutHandle &handle)
lease4-get-all, lease6-get-all commands handler
int leaseWriteHandler(CalloutHandle &handle)
lease4-write handler, lease6-write handler
int lease4ResendDdnsHandler(hooks::CalloutHandle &handle)
lease4-resend-ddns command handler
int leaseGetByStateHandler(hooks::CalloutHandle &handle)
lease4-get-by-state and lease6-get-by-state commands handler
int lease6WipeHandler(hooks::CalloutHandle &handle)
lease6-wipe handler
int leaseGetPageHandler(hooks::CalloutHandle &handle)
lease4-get-page, lease6-get-page commands handler
int lease6DelHandler(hooks::CalloutHandle &handle)
lease6-del command handler
int leaseGetAllHandler(hooks::CalloutHandle &handle)
lease4-get-all, lease6-get-all commands handler
int leaseGetByHostnameHandler(hooks::CalloutHandle &handle)
lease4-get-by-hostname and lease6-get-by-hostname commands handler
void leases4Committed(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases4_committed hookpoint handler.
int lease4DelHandler(hooks::CalloutHandle &handle)
lease4-del command handler
int leaseWriteHandler(hooks::CalloutHandle &handle)
lease4-write handler, lease6-write handler
int leaseAddHandler(hooks::CalloutHandle &handle)
lease4-add, lease6-add command handler
int leaseGetByClientIdHandler(hooks::CalloutHandle &handle)
lease4-get-by-client-id command handler
void lease4Offer(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
lease4_offer hookpoint handler.
int lease4UpdateHandler(hooks::CalloutHandle &handle)
lease4-update handler
int leaseGetHandler(hooks::CalloutHandle &handle)
lease4-get, lease6-get command handler
int leaseGetByHwAddressHandler(hooks::CalloutHandle &handle)
lease4-get-by-hw-address, lease6-get-by-hw-address command handler
int lease6UpdateHandler(hooks::CalloutHandle &handle)
lease6-update handler
void leases6Committed(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases6_committed hookpoint handler.
int leaseGetByDuidHandler(hooks::CalloutHandle &handle)
lease6-get-by-duid command handler
int lease6BulkApplyHandler(hooks::CalloutHandle &handle)
lease6-bulk-apply command handler
int lease4WipeHandler(hooks::CalloutHandle &handle)
lease4-wipe handler
int lease6ResendDdnsHandler(hooks::CalloutHandle &handle)
lease6-resend-ddns command handler
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
A generic exception that is thrown if a parameter given violates security check but enforcement is la...
Definition filesystem.h:22
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
const isc::log::MessageID LEASE_CMDS_DEL4
const isc::log::MessageID LEASE_CMDS_WIPE4_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE4_FAILED
const isc::log::MessageID LEASE_CMDS_WIPE6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6_CONFLICT
const isc::log::MessageID LEASE_CMDS_UPDATE4_CONFLICT
const isc::log::MessageID LEASE_CMDS_FATAL_WRITE_LEASES4
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED
const isc::log::MessageID LEASE_CMDS_DEL6
const isc::log::MessageID LEASE_CMDS_ADD4_FAILED
const isc::log::MessageID LEASE_CMDS_LEASES6_COMMITTED_LEASE_ERROR
const isc::log::MessageID LEASE_CMDS_PATH_SECURITY_WARNING
const isc::log::MessageID LEASE_CMDS_ADD6
const isc::log::MessageID LEASE_CMDS_ADD4
const isc::log::MessageID LEASE_CMDS_WIPE6
const isc::log::MessageID LEASE_CMDS_ADD6_CONFLICT
const isc::log::MessageID LEASE_CMDS_BULK_APPLY6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4
const isc::log::MessageID LEASE_CMDS_GET6_FAILED
const isc::log::MessageID LEASE_CMDS_WIPE4
const isc::log::MessageID LEASE_CMDS_BULK_APPLY6
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6_FAILED
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6
const isc::log::MessageID LEASE_CMDS_GET4_FAILED
const isc::log::MessageID LEASE_CMDS_ADD4_CONFLICT
const isc::log::MessageID LEASE_CMDS_LEASES6_COMMITTED_CONFLICT
const isc::log::MessageID LEASE_CMDS_DEL4_FAILED
const isc::log::MessageID LEASE_CMDS_ADD6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE4
const isc::log::MessageID LEASE_CMDS_FATAL_WRITE_LEASES6
const isc::log::MessageID LEASE_CMDS_DEL6_FAILED
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_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
#define LOG_FATAL(LOGGER, MESSAGE)
Macro to conveniently test fatal output and log it.
Definition macros.h:38
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_CONFLICT
Status code indicating that the command was unsuccessful due to a conflict between the command argume...
const int CONTROL_RESULT_FATAL_ERROR
Status code indicating that the command was unsuccessful and the configuration could not be reverted ...
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
Definition lease.h:525
boost::shared_ptr< const SrvConfig > ConstSrvConfigPtr
Const pointer to the SrvConfig.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates NameChangeRequest from the DHCPv4 lease and queues it to be sent to D2.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:556
boost::shared_ptr< DUID > DuidPtr
Definition duid.h:136
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:530
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition lease.h:695
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:934
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:166
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:863
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition duid.h:216
boost::shared_ptr< const CfgSubnets4 > ConstCfgSubnets4Ptr
Const pointer.
boost::shared_ptr< const CfgSubnets6 > ConstCfgSubnets6Ptr
Const pointer.
@ DHCPACK
Definition dhcp4.h:239
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition lease.h:698
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition lease.h:522
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:317
const int LEASE_CMDS_DBG_COMMAND_DATA
Logging level used to log successful commands.
isc::log::Logger lease_cmds_logger("lease-cmds-hooks")
boost::shared_ptr< BindingVariableMgr > BindingVariableMgrPtr
Defines a shared pointer to a BindingVariableMgr.
boost::multiprecision::checked_int128_t int128_t
Definition bigints.h:19
Defines the logger used by the top-level component of kea-lfc.
Hardware type that represents information from DHCPv4 packet.
Definition hwaddr.h:20
static HWAddr fromText(const std::string &text, const uint16_t htype=HTYPE_ETHER)
Creates instance of the hardware address from textual format.
Definition hwaddr.cc:62
Structure that holds a lease for IPv6 address and/or prefix.
Definition lease.h:538
@ ACTION_UPDATE
update extended info tables.
Definition lease.h:578
a common structure for IPv4 and IPv6 leases
Definition lease.h:33
static constexpr uint32_t STATE_DEFAULT
A lease in the default state.
Definition lease.h:71
static constexpr uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Definition lease.h:77
static constexpr uint32_t STATE_DECLINED
Declined lease.
Definition lease.h:74
static constexpr uint32_t STATE_REGISTERED
Registered self-generated lease.
Definition lease.h:83
static std::string basicStatesToText(const uint32_t state)
Returns name(s) of the basic lease state(s).
Definition lease.cc:89
static constexpr uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
Definition lease.h:80
static void syncCurrentExpirationTime(const Lease &from, Lease &to)
Sync lease current expiration time with new value from another lease, so that additional operations c...
Definition lease.cc:316
Type
Type of lease or pool.
Definition lease.h:48
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:51
@ TYPE_V4
IPv4 lease.
Definition lease.h:52
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition lease.h:49
static std::string typeToText(Type type)
returns text representation of a lease type
Definition lease.cc:56