Kea 3.0.0
lease_cmds.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2025 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>
9#include <config/cmds_impl.h>
11#include <cc/data.h>
12#include <asiolink/io_address.h>
14#include <dhcpsrv/cfgmgr.h>
16#include <dhcpsrv/lease_mgr.h>
20#include <dhcpsrv/subnet_id.h>
22#include <dhcp/duid.h>
23#include <hooks/hooks.h>
25#include <lease_cmds.h>
27#include <lease_parser.h>
28#include <lease_cmds_log.h>
29#include <stats/stats_mgr.h>
30#include <util/encode/encode.h>
32
33#include <boost/scoped_ptr.hpp>
34#include <boost/algorithm/string.hpp>
35#include <string>
36#include <sstream>
37
38using namespace isc::dhcp;
39using namespace isc::data;
40using namespace isc::dhcp_ddns;
41using namespace isc::config;
42using namespace isc::asiolink;
43using namespace isc::hooks;
44using namespace isc::stats;
45using namespace isc::util;
46using namespace isc::log;
47using namespace std;
48
49namespace isc {
50namespace lease_cmds {
51
53class LeaseCmdsImpl : private CmdsImpl {
54public:
55
57 class Parameters {
58 public:
59
67
70
73
76
79
82
92 static Type txtToType(const std::string& txt) {
93 if (txt == "address") {
94 return (Parameters::TYPE_ADDR);
95 } else if (txt == "hw-address") {
97 } else if (txt == "duid") {
98 return (Parameters::TYPE_DUID);
99 } else if (txt == "client-id") {
101 } else {
102 isc_throw(BadValue, "Incorrect identifier type: "
103 << txt << ", the only supported values are: "
104 "address, hw-address, duid");
105 }
106 }
107
110
113
115 uint32_t iaid;
116
119
122 : subnet_id(0), addr("::"), query_type(TYPE_ADDR),
123 lease_type(Lease::TYPE_NA), iaid(0), updateDDNS(false) {
124 }
125 };
126
127public:
128
137 int
139
149 int
151
160 int
162
174 int
176
192 int
194
204 int
206
216 int
218
228 int
230
241 int
243
252 int
254
263 int
265
274 int
276
285 int
287
296 int
298
307 int
309
319
329
338 int
340
352 Parameters getParameters(bool v6, const ConstElementPtr& args);
353
371 Lease6Ptr getIPv6LeaseForDelete(const Parameters& parameters) const;
372
388 const IOAddress& lease_address,
389 const DuidPtr& duid,
390 const int control_result,
391 const std::string& error_message) const;
392
403 IOAddress getAddressParam(ConstElementPtr params, const std::string name,
404 short family = AF_INET) const;
405
409 static void updateStatsOnAdd(const Lease4Ptr& lease);
410
414 static void updateStatsOnAdd(const Lease6Ptr& lease);
415
420 static void updateStatsOnUpdate(const Lease4Ptr& existing,
421 const Lease4Ptr& lease);
422
427 static void updateStatsOnUpdate(const Lease6Ptr& existing,
428 const Lease6Ptr& lease);
429
433 static void updateStatsOnDelete(const Lease4Ptr& lease);
434
438 static void updateStatsOnDelete(const Lease6Ptr& lease);
439
448 static bool addOrUpdate4(Lease4Ptr lease, bool force_create);
449
458 static bool addOrUpdate6(Lease6Ptr lease, bool force_create);
459
464 inline static ConstElementPtr getExtendedInfo6(const Lease6Ptr& lease) {
465 ConstElementPtr user_context = lease->getContext();
466 if (!user_context || (user_context->getType() != Element::map)) {
467 return (ConstElementPtr());
468 }
469 ConstElementPtr isc = user_context->get("ISC");
470 if (!isc || (isc->getType() != Element::map)) {
471 return (ConstElementPtr());
472 }
473 return (isc->get("relay-info"));
474 }
475
489 static void lease4Offer(CalloutHandle& callout_handle,
491
503 static void leases4Committed(CalloutHandle& callout_handle,
505
517 static void leases6Committed(CalloutHandle& callout_handle,
519};
520
521void
523 if (!lease->stateExpiredReclaimed()) {
525 StatsMgr::generateName("subnet", lease->subnet_id_,
526 "assigned-addresses"),
527 static_cast<int64_t>(1));
528
529 PoolPtr pool;
530 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
531 if (subnet) {
532 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
533 if (pool) {
535 StatsMgr::generateName("subnet", subnet->getID(),
536 StatsMgr::generateName("pool", pool->getID(),
537 "assigned-addresses")),
538 static_cast<int64_t>(1));
539 }
540 }
541
542 if (lease->stateDeclined()) {
543 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
544
546 StatsMgr::generateName("subnet", lease->subnet_id_,
547 "declined-addresses"),
548 static_cast<int64_t>(1));
549
550 if (pool) {
552 StatsMgr::generateName("subnet", subnet->getID(),
553 StatsMgr::generateName("pool", pool->getID(),
554 "declined-addresses")),
555 static_cast<int64_t>(1));
556 }
557 }
558 }
559}
560
561void
563 if (lease->stateRegistered()) {
565 StatsMgr::generateName("subnet", lease->subnet_id_, "registered-nas"),
566 static_cast<int64_t>(1));
567 } else if (!lease->stateExpiredReclaimed()) {
569 StatsMgr::generateName("subnet", lease->subnet_id_,
570 lease->type_ == Lease::TYPE_NA ?
571 "assigned-nas" : "assigned-pds"),
572 static_cast<int64_t>(1));
573
574 PoolPtr pool;
575 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
576 if (subnet) {
577 pool = subnet->getPool(lease->type_, lease->addr_, false);
578 if (pool) {
580 StatsMgr::generateName("subnet", subnet->getID(),
581 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
582 "pool" : "pd-pool", pool->getID(),
583 lease->type_ == Lease::TYPE_NA ?
584 "assigned-nas" : "assigned-pds")),
585 static_cast<int64_t>(1));
586 }
587 }
588
589 if (lease->stateDeclined()) {
590 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
591
593 StatsMgr::generateName("subnet", lease->subnet_id_,
594 "declined-addresses"),
595 static_cast<int64_t>(1));
596
597 if (pool) {
599 StatsMgr::generateName("subnet", subnet->getID(),
600 StatsMgr::generateName("pool", pool->getID(),
601 "declined-addresses")),
602 static_cast<int64_t>(1));
603 }
604 }
605 }
606}
607
608void
610 const Lease4Ptr& lease) {
611 if (!existing->stateExpiredReclaimed()) {
612 ConstSubnet4Ptr subnet;
613 PoolPtr pool;
614
615 // old lease is non expired-reclaimed
616 if (existing->subnet_id_ != lease->subnet_id_) {
618 StatsMgr::generateName("subnet", existing->subnet_id_,
619 "assigned-addresses"),
620 static_cast<int64_t>(-1));
621
622 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(existing->subnet_id_);
623 if (subnet) {
624 pool = subnet->getPool(Lease::TYPE_V4, existing->addr_, false);
625 if (pool) {
627 StatsMgr::generateName("subnet", subnet->getID(),
628 StatsMgr::generateName("pool", pool->getID(),
629 "assigned-addresses")),
630 static_cast<int64_t>(-1));
631 }
632 }
633 }
634
635 if (existing->stateDeclined()) {
636 // old lease is declined
637 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
638
640 StatsMgr::generateName("subnet", existing->subnet_id_,
641 "declined-addresses"),
642 static_cast<int64_t>(-1));
643
644 if (pool) {
646 StatsMgr::generateName("subnet", subnet->getID(),
647 StatsMgr::generateName("pool", pool->getID(),
648 "declined-addresses")),
649 static_cast<int64_t>(-1));
650 }
651 }
652
653 pool.reset();
654
655 if (!lease->stateExpiredReclaimed()) {
656 // new lease is non expired-reclaimed
657 if (existing->subnet_id_ != lease->subnet_id_) {
659 StatsMgr::generateName("subnet", lease->subnet_id_,
660 "assigned-addresses"),
661 static_cast<int64_t>(1));
662
663 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
664 if (subnet) {
665 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
666 if (pool) {
668 StatsMgr::generateName("subnet", subnet->getID(),
669 StatsMgr::generateName("pool", pool->getID(),
670 "assigned-addresses")),
671 static_cast<int64_t>(1));
672 }
673 }
674 }
675
676 if (lease->stateDeclined()) {
677 // new lease is declined
678 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
679
681 StatsMgr::generateName("subnet", lease->subnet_id_,
682 "declined-addresses"),
683 static_cast<int64_t>(1));
684
685 if (pool) {
687 StatsMgr::generateName("subnet", subnet->getID(),
688 StatsMgr::generateName("pool", pool->getID(),
689 "declined-addresses")),
690 static_cast<int64_t>(1));
691 }
692 }
693 }
694 } else {
695 // old lease is expired-reclaimed
696 if (!lease->stateExpiredReclaimed()) {
697 // new lease is non expired-reclaimed
699 StatsMgr::generateName("subnet", lease->subnet_id_,
700 "assigned-addresses"),
701 static_cast<int64_t>(1));
702
703 PoolPtr pool;
704 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
705 if (subnet) {
706 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
707 if (pool) {
709 StatsMgr::generateName("subnet", subnet->getID(),
710 StatsMgr::generateName("pool", pool->getID(),
711 "assigned-addresses")),
712 static_cast<int64_t>(1));
713 }
714 }
715
716 if (lease->stateDeclined()) {
717 // new lease is declined
718 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
719
721 StatsMgr::generateName("subnet", lease->subnet_id_,
722 "declined-addresses"),
723 static_cast<int64_t>(1));
724
725 if (pool) {
727 StatsMgr::generateName("subnet", subnet->getID(),
728 StatsMgr::generateName("pool", pool->getID(),
729 "declined-addresses")),
730 static_cast<int64_t>(1));
731 }
732 }
733 }
734 }
735}
736
737void
739 const Lease6Ptr& lease) {
740 // Does not cover registered <-> not registered transition.
741 if (existing->stateRegistered()) {
742 if (existing->subnet_id_ != lease->subnet_id_) {
744 StatsMgr::generateName("subnet", existing->subnet_id_,
745 "registered-nas"),
746 static_cast<int64_t>(-1));
748 StatsMgr::generateName("subnet", lease->subnet_id_,
749 "registered-nas"),
750 static_cast<int64_t>(1));
751 }
752 } else if (!existing->stateExpiredReclaimed()) {
753 ConstSubnet6Ptr subnet;
754 PoolPtr pool;
755
756 // old lease is non expired-reclaimed
757 if (existing->subnet_id_ != lease->subnet_id_) {
759 StatsMgr::generateName("subnet", existing->subnet_id_,
760 lease->type_ == Lease::TYPE_NA ?
761 "assigned-nas" : "assigned-pds"),
762 static_cast<int64_t>(-1));
763
764 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(existing->subnet_id_);
765 if (subnet) {
766 pool = subnet->getPool(existing->type_, existing->addr_, false);
767 if (pool) {
769 StatsMgr::generateName("subnet", subnet->getID(),
770 StatsMgr::generateName(existing->type_ == Lease::TYPE_NA ?
771 "pool" : "pd-pool", pool->getID(),
772 existing->type_ == Lease::TYPE_NA ?
773 "assigned-nas" : "assigned-pds")),
774 static_cast<int64_t>(-1));
775 }
776 }
777 }
778
779 if (existing->stateDeclined()) {
780 // old lease is declined
781 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
782
784 StatsMgr::generateName("subnet", existing->subnet_id_,
785 "declined-addresses"),
786 static_cast<int64_t>(-1));
787
788 if (pool) {
790 StatsMgr::generateName("subnet", subnet->getID(),
791 StatsMgr::generateName("pool", pool->getID(),
792 "declined-addresses")),
793 static_cast<int64_t>(-1));
794 }
795 }
796
797 pool.reset();
798
799 if (!lease->stateExpiredReclaimed()) {
800 // new lease is non expired-reclaimed
801 if (existing->subnet_id_ != lease->subnet_id_) {
803 StatsMgr::generateName("subnet", lease->subnet_id_,
804 lease->type_ == Lease::TYPE_NA ?
805 "assigned-nas" : "assigned-pds"),
806 static_cast<int64_t>(1));
807
808 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
809 if (subnet) {
810 pool = subnet->getPool(lease->type_, lease->addr_, false);
811 if (pool) {
813 StatsMgr::generateName("subnet", subnet->getID(),
814 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
815 "pool" : "pd-pool", pool->getID(),
816 lease->type_ == Lease::TYPE_NA ?
817 "assigned-nas" : "assigned-pds")),
818 static_cast<int64_t>(1));
819 }
820 }
821 }
822
823 if (lease->stateDeclined()) {
824 // new lease is declined
825 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
826
828 StatsMgr::generateName("subnet", lease->subnet_id_,
829 "declined-addresses"),
830 static_cast<int64_t>(1));
831
832 if (pool) {
834 StatsMgr::generateName("subnet", subnet->getID(),
835 StatsMgr::generateName("pool", pool->getID(),
836 "declined-addresses")),
837 static_cast<int64_t>(1));
838 }
839 }
840 }
841 } else {
842 // old lease is expired-reclaimed
843 if (!lease->stateExpiredReclaimed()) {
844 // new lease is non expired-reclaimed
846 StatsMgr::generateName("subnet", lease->subnet_id_,
847 lease->type_ == Lease::TYPE_NA ?
848 "assigned-nas" : "assigned-pds"),
849 static_cast<int64_t>(1));
850
851 PoolPtr pool;
852 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
853 if (subnet) {
854 pool = subnet->getPool(lease->type_, lease->addr_, false);
855 if (pool) {
857 StatsMgr::generateName("subnet", subnet->getID(),
858 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
859 "pool" : "pd-pool", pool->getID(),
860 lease->type_ == Lease::TYPE_NA ?
861 "assigned-nas" : "assigned-pds")),
862 static_cast<int64_t>(1));
863 }
864 }
865
866 if (lease->stateDeclined()) {
867 // new lease is declined
868 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
869
871 StatsMgr::generateName("subnet", lease->subnet_id_,
872 "declined-addresses"),
873 static_cast<int64_t>(1));
874
875 if (pool) {
877 StatsMgr::generateName("subnet", subnet->getID(),
878 StatsMgr::generateName("pool", pool->getID(),
879 "declined-addresses")),
880 static_cast<int64_t>(1));
881 }
882 }
883 }
884 }
885}
886
887void
889 if (!lease->stateExpiredReclaimed()) {
891 StatsMgr::generateName("subnet", lease->subnet_id_,
892 "assigned-addresses"),
893 static_cast<int64_t>(-1));
894
895 PoolPtr pool;
896 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
897 if (subnet) {
898 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
899 if (pool) {
901 StatsMgr::generateName("subnet", subnet->getID(),
902 StatsMgr::generateName("pool", pool->getID(),
903 "assigned-addresses")),
904 static_cast<int64_t>(-1));
905 }
906 }
907
908 if (lease->stateDeclined()) {
909 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
910
912 StatsMgr::generateName("subnet", lease->subnet_id_,
913 "declined-addresses"),
914 static_cast<int64_t>(-1));
915
916 if (pool) {
918 StatsMgr::generateName("subnet", subnet->getID(),
919 StatsMgr::generateName("pool", pool->getID(),
920 "declined-addresses")),
921 static_cast<int64_t>(-1));
922 }
923 }
924 }
925}
926
927void
929 if (lease->stateRegistered()) {
931 StatsMgr::generateName("subnet", lease->subnet_id_,
932 "registered-nas"),
933 static_cast<int64_t>(-1));
934 } else if (!lease->stateExpiredReclaimed()) {
936 StatsMgr::generateName("subnet", lease->subnet_id_,
937 lease->type_ == Lease::TYPE_NA ?
938 "assigned-nas" : "assigned-pds"),
939 static_cast<int64_t>(-1));
940
941 PoolPtr pool;
942 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
943 if (subnet) {
944 pool = subnet->getPool(lease->type_, lease->addr_, false);
945 if (pool) {
947 StatsMgr::generateName("subnet", subnet->getID(),
948 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
949 "pool" : "pd-pool", pool->getID(),
950 lease->type_ == Lease::TYPE_NA ?
951 "assigned-nas" : "assigned-pds")),
952 static_cast<int64_t>(-1));
953 }
954 }
955
956 if (lease->stateDeclined()) {
957 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
958
960 StatsMgr::generateName("subnet", lease->subnet_id_,
961 "declined-addresses"),
962 static_cast<int64_t>(-1));
963
964 if (pool) {
966 StatsMgr::generateName("subnet", subnet->getID(),
967 StatsMgr::generateName("pool", pool->getID(),
968 "declined-addresses")),
969 static_cast<int64_t>(-1));
970 }
971 }
972 }
973}
974
975bool
976LeaseCmdsImpl::addOrUpdate4(Lease4Ptr lease, bool force_create) {
977 Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease->addr_);
978 if (force_create && !existing) {
979 // lease does not exist
980 if (!LeaseMgrFactory::instance().addLease(lease)) {
982 "lost race between calls to get and add");
983 }
985 return (true);
986 }
987 if (existing) {
988 // Update lease current expiration time with value received from the
989 // database. Some database backends reject operations on the lease if
990 // the current expiration time value does not match what is stored.
991 Lease::syncCurrentExpirationTime(*existing, *lease);
992 }
993 try {
995 } catch (const NoSuchLease&) {
996 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
997 << lease->addr_ << " either because the lease has been "
998 "deleted or it has changed in the database, in both cases a "
999 "retry might succeed");
1000 }
1001
1002 LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
1003 return (false);
1004}
1005
1006bool
1007LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) {
1008 Lease6Ptr existing =
1009 LeaseMgrFactory::instance().getLease6(lease->type_, lease->addr_);
1010 if (force_create && !existing) {
1011 // lease does not exist
1012 if (!LeaseMgrFactory::instance().addLease(lease)) {
1014 "lost race between calls to get and add");
1015 }
1017 return (true);
1018 }
1019 if (existing) {
1020 // Refuse used <-> registered transitions.
1021 if (existing->stateRegistered() && !lease->stateRegistered()) {
1022 isc_throw(BadValue, "illegal reuse of registered address "
1023 << lease->addr_);
1024 } else if (!existing->stateRegistered() && lease->stateRegistered()) {
1025 isc_throw(BadValue, "address in use: " << lease->addr_
1026 << " can't be registered");
1027 }
1028
1029 // Update lease current expiration time with value received from the
1030 // database. Some database backends reject operations on the lease if
1031 // the current expiration time value does not match what is stored.
1032 Lease::syncCurrentExpirationTime(*existing, *lease);
1033
1034 // Check what is the action about extended info.
1035 ConstElementPtr old_extended_info = getExtendedInfo6(existing);
1036 ConstElementPtr extended_info = getExtendedInfo6(lease);
1037 if ((!old_extended_info && !extended_info) ||
1038 (old_extended_info && extended_info &&
1039 (*old_extended_info == *extended_info))) {
1040 // Leave the default Lease6::ACTION_IGNORE.
1041 } else {
1042 lease->extended_info_action_ = Lease6::ACTION_UPDATE;
1043 }
1044 }
1045 try {
1047 } catch (const NoSuchLease&) {
1048 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
1049 << lease->addr_ << " either because the lease has been "
1050 "deleted or it has changed in the database, in both cases a "
1051 "retry might succeed");
1052 }
1053
1054 LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
1055 return (false);
1056}
1057
1058int
1060 // Arbitrary defaulting to DHCPv4 or with other words extractCommand
1061 // below is not expected to throw...
1062 bool v4 = true;
1063 stringstream resp;
1064 string lease_address = "unknown";
1065 try {
1066 extractCommand(handle);
1067 v4 = (cmd_name_ == "lease4-add");
1068 if (!cmd_args_) {
1069 isc_throw(isc::BadValue, "no parameters specified for the command");
1070 }
1071
1073
1074 // This parameter is ignored for the commands adding the lease.
1075 bool force_create = false;
1076 Lease4Ptr lease4;
1077 Lease6Ptr lease6;
1078 if (v4) {
1079 Lease4Parser parser;
1080 lease4 = parser.parse(config, cmd_args_, force_create);
1081 if (lease4) {
1082 lease_address = lease4->addr_.toText();
1083 bool success;
1084 if (!MultiThreadingMgr::instance().getMode()) {
1085 // Not multi-threading.
1086 success = LeaseMgrFactory::instance().addLease(lease4);
1087 } else {
1088 // Multi-threading, try to lock first to avoid a race.
1089 ResourceHandler4 resource_handler;
1090 if (resource_handler.tryLock4(lease4->addr_)) {
1091 success = LeaseMgrFactory::instance().addLease(lease4);
1092 } else {
1094 "ResourceBusy: IP address:" << lease4->addr_
1095 << " could not be added.");
1096 }
1097 }
1098
1099 if (!success) {
1100 isc_throw(LeaseCmdsConflict, "IPv4 lease already exists.");
1101 }
1102
1104 resp << "Lease for address " << lease4->addr_.toText()
1105 << ", subnet-id " << lease4->subnet_id_ << " added.";
1106 }
1107 } else {
1108 Lease6Parser parser;
1109 lease6 = parser.parse(config, cmd_args_, force_create);
1110 if (lease6) {
1111 lease_address = lease6->addr_.toText();
1112 bool success;
1113 if (!MultiThreadingMgr::instance().getMode()) {
1114 // Not multi-threading.
1115 success = LeaseMgrFactory::instance().addLease(lease6);
1116 } else {
1117 // Multi-threading, try to lock first to avoid a race.
1118 ResourceHandler resource_handler;
1119 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
1120 success = LeaseMgrFactory::instance().addLease(lease6);
1121 } else {
1123 "ResourceBusy: IP address:" << lease6->addr_
1124 << " could not be added.");
1125 }
1126 }
1127
1128 if (!success) {
1129 isc_throw(LeaseCmdsConflict, "IPv6 lease already exists.");
1130 }
1131
1133 if (lease6->type_ == Lease::TYPE_NA) {
1134 resp << "Lease for address " << lease6->addr_.toText()
1135 << ", subnet-id " << lease6->subnet_id_ << " added.";
1136 } else {
1137 resp << "Lease for prefix " << lease6->addr_.toText()
1138 << "/" << static_cast<int>(lease6->prefixlen_)
1139 << ", subnet-id " << lease6->subnet_id_ << " added.";
1140 }
1141 }
1142 }
1143 } catch (const LeaseCmdsConflict& ex) {
1145 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1146 .arg(ex.what());
1148 return (0);
1149
1150 } catch (const std::exception& ex) {
1152 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1153 .arg(ex.what());
1154 setErrorResponse(handle, ex.what());
1155 return (1);
1156 }
1157
1160 .arg(lease_address);
1161 setSuccessResponse(handle, resp.str());
1162 return (0);
1163}
1164
1167 Parameters x;
1168
1169 if (!params || params->getType() != Element::map) {
1170 isc_throw(BadValue, "Parameters missing or are not a map.");
1171 }
1172
1173 if (params->contains("update-ddns")) {
1174 ConstElementPtr tmp = params->get("update-ddns");
1175 if (tmp->getType() != Element::boolean) {
1176 isc_throw(BadValue, "'update-ddns' is not a boolean");
1177 } else {
1178 x.updateDDNS = tmp->boolValue();
1179 }
1180 }
1181
1182 // We support several sets of parameters for leaseX-get/lease-del:
1183 // lease-get(type, address)
1184 // lease-get(type, subnet-id, identifier-type, identifier)
1185
1186 if (params->contains("type")) {
1187 string t = params->get("type")->stringValue();
1188 if (t == "IA_NA" || t == "0") {
1190 } else if (t == "IA_TA" || t == "1") {
1192 } else if (t == "IA_PD" || t == "2") {
1194 } else if (t == "V4" || t == "3") {
1196 } else {
1197 isc_throw(BadValue, "Invalid lease type specified: "
1198 << t << ", only supported values are: IA_NA, IA_TA,"
1199 << " IA_PD and V4");
1200 }
1201 }
1202
1203 ConstElementPtr tmp = params->get("ip-address");
1204 if (tmp) {
1205 if (tmp->getType() != Element::string) {
1206 isc_throw(BadValue, "'ip-address' is not a string.");
1207 }
1208
1209 x.addr = IOAddress(tmp->stringValue());
1210
1211 if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
1212 stringstream txt;
1213 txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
1214 << " address specified: " << tmp->stringValue();
1215 isc_throw(BadValue, txt.str());
1216 }
1217
1219 return (x);
1220 }
1221
1222 tmp = params->get("subnet-id");
1223 if (!tmp) {
1224 isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
1225 }
1226 if (tmp->getType() != Element::integer) {
1227 isc_throw(BadValue, "'subnet-id' parameter is not integer.");
1228 }
1229 x.subnet_id = tmp->intValue();
1230
1231 if (params->contains("iaid")) {
1232 x.iaid = params->get("iaid")->intValue();
1233 }
1234
1235 // No address specified. Ok, so it must be identifier based query.
1236 // "identifier-type": "duid",
1237 // "identifier": "aa:bb:cc:dd:ee:..."
1238
1239 ConstElementPtr type = params->get("identifier-type");
1240 ConstElementPtr ident = params->get("identifier");
1241 if (!type || type->getType() != Element::string) {
1242 isc_throw(BadValue, "No 'ip-address' provided"
1243 " and 'identifier-type' is either missing or not a string.");
1244 }
1245 if (!ident || ident->getType() != Element::string) {
1246 isc_throw(BadValue, "No 'ip-address' provided"
1247 " and 'identifier' is either missing or not a string.");
1248 }
1249
1250 // Got the parameters. Let's see if their values make sense.
1251 // Try to convert identifier-type
1252 x.query_type = Parameters::txtToType(type->stringValue());
1253
1254 switch (x.query_type) {
1256 HWAddr hw = HWAddr::fromText(ident->stringValue());
1257 x.hwaddr = HWAddrPtr(new HWAddr(hw));
1258 break;
1259 }
1261 x.client_id = ClientId::fromText(ident->stringValue());
1262 break;
1263 }
1264 case Parameters::TYPE_DUID: {
1265 DUID duid = DUID::fromText(ident->stringValue());
1266 x.duid = DuidPtr(new DUID(duid));
1267 break;
1268 }
1269 case Parameters::TYPE_ADDR: {
1270 // We should never get here. The address clause should have been caught
1271 // earlier.
1272 return (x);
1273 }
1274 default: {
1275 isc_throw(BadValue, "Identifier type " << type->stringValue() <<
1276 " is not supported.");
1277 }
1278 }
1279
1280 return (x);
1281}
1282
1283int
1285 Parameters p;
1286 Lease4Ptr lease4;
1287 Lease6Ptr lease6;
1288 bool v4 = true;
1289 try {
1290 extractCommand(handle);
1291 v4 = (cmd_name_ == "lease4-get");
1292 p = getParameters(!v4, cmd_args_);
1293 switch (p.query_type) {
1294 case Parameters::TYPE_ADDR: {
1295 // Query by address
1296 if (v4) {
1298 } else {
1300 }
1301 break;
1302 }
1304 if (v4) {
1305 if (!p.hwaddr) {
1306 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1307 "requires hwaddr to be specified");
1308 }
1309
1311 } else {
1312 isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
1313 }
1314 break;
1315
1317 if (!v4) {
1318 if (!p.duid) {
1319 isc_throw(InvalidParameter, "Program error: Query by duid "
1320 "requires duid to be specified");
1321 }
1322
1324 p.iaid, p.subnet_id);
1325 } else {
1326 isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
1327 }
1328 break;
1329
1331 if (v4) {
1332 if (!p.client_id) {
1333 isc_throw(InvalidParameter, "Program error: Query by client-id "
1334 "requires client-id to be specified");
1335 }
1336
1338 } else {
1339 isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
1340 }
1341 break;
1342
1343 default: {
1344 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1345 break;
1346 }
1347 }
1348 } catch (const std::exception& ex) {
1350 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1351 .arg(ex.what());
1352 setErrorResponse(handle, ex.what());
1353 return (1);
1354 }
1355
1356 ElementPtr lease_json;
1357 if (v4 && lease4) {
1358 lease_json = lease4->toElement();
1360 "IPv4 lease found.", lease_json);
1361 setResponse(handle, response);
1362 } else if (!v4 && lease6) {
1363 lease_json = lease6->toElement();
1365 "IPv6 lease found.", lease_json);
1366 setResponse(handle, response);
1367 } else {
1368 // If we got here, the lease has not been found.
1369 setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
1370 }
1371
1372 return (0);
1373}
1374
1375int
1377 bool v4 = true;
1378 try {
1379 extractCommand(handle);
1380 v4 = (cmd_name_ == "lease4-get-all");
1381
1382 ElementPtr leases_json = Element::createList();
1383
1384 // The argument may contain a list of subnets for which leases should
1385 // be returned.
1386 if (cmd_args_) {
1387 ConstElementPtr subnets = cmd_args_->get("subnets");
1388 if (!subnets) {
1389 isc_throw(BadValue, "'subnets' parameter not specified");
1390 }
1391 if (subnets->getType() != Element::list) {
1392 isc_throw(BadValue, "'subnets' parameter must be a list");
1393 }
1394
1395 const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
1396 for (auto const& subnet_id : subnet_ids) {
1397 if (subnet_id->getType() != Element::integer) {
1398 isc_throw(BadValue, "listed subnet identifiers must be numbers");
1399 }
1400
1401 if (v4) {
1402 Lease4Collection leases =
1403 LeaseMgrFactory::instance().getLeases4(subnet_id->intValue());
1404 for (auto const& lease : leases) {
1405 ElementPtr lease_json = lease->toElement();
1406 leases_json->add(lease_json);
1407 }
1408 } else {
1409 Lease6Collection leases =
1410 LeaseMgrFactory::instance().getLeases6(subnet_id->intValue());
1411 for (auto const& lease : leases) {
1412 ElementPtr lease_json = lease->toElement();
1413 leases_json->add(lease_json);
1414 }
1415 }
1416 }
1417
1418 } else {
1419 // There is no 'subnets' argument so let's return all leases.
1420 if (v4) {
1422 for (auto const& lease : leases) {
1423 ElementPtr lease_json = lease->toElement();
1424 leases_json->add(lease_json);
1425 }
1426 } else {
1428 for (auto const& lease : leases) {
1429 ElementPtr lease_json = lease->toElement();
1430 leases_json->add(lease_json);
1431 }
1432 }
1433 }
1434
1435 std::ostringstream s;
1436 s << leases_json->size()
1437 << " IPv" << (v4 ? "4" : "6")
1438 << " lease(s) found.";
1440 args->set("leases", leases_json);
1441 ConstElementPtr response =
1442 createAnswer(leases_json->size() > 0 ?
1445 s.str(), args);
1446 setResponse(handle, response);
1447
1448 } catch (const std::exception& ex) {
1449 setErrorResponse(handle, ex.what());
1450 return (CONTROL_RESULT_ERROR);
1451 }
1452
1453 return (0);
1454}
1455
1456int
1458 bool v4 = true;
1459 try {
1460 extractCommand(handle);
1461 v4 = (cmd_name_ == "lease4-get-page");
1462
1463 // arguments must always be present
1464 if (!cmd_args_) {
1465 isc_throw(BadValue, "no parameters specified for the " << cmd_name_
1466 << " command");
1467 }
1468
1469 // The 'from' argument denotes from which lease we should start the
1470 // results page. The results page excludes this lease.
1471 ConstElementPtr from = cmd_args_->get("from");
1472 if (!from) {
1473 isc_throw(BadValue, "'from' parameter not specified");
1474 }
1475
1476 // The 'from' argument is a string. It may contain a 'start' keyword or
1477 // an IP address.
1478 if (from->getType() != Element::string) {
1479 isc_throw(BadValue, "'from' parameter must be a string");
1480 }
1481
1482 boost::scoped_ptr<IOAddress> from_address;
1483 try {
1484 if (from->stringValue() == "start") {
1485 from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1486
1487 } else {
1488 // Conversion of a string to an IP address may throw.
1489 from_address.reset(new IOAddress(from->stringValue()));
1490 }
1491
1492 } catch (...) {
1493 isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1494 "a valid IPv" << (v4 ? "4" : "6") << " address");
1495 }
1496
1497 // It must be either IPv4 address for lease4-get-page or IPv6 address for
1498 // lease6-get-page.
1499 if (v4 && (!from_address->isV4())) {
1500 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1501 << " is not an IPv4 address");
1502
1503 } else if (!v4 && from_address->isV4()) {
1504 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1505 << " is not an IPv6 address");
1506 }
1507
1508 // The 'limit' is a desired page size. It must always be present.
1509 ConstElementPtr page_limit = cmd_args_->get("limit");
1510 if (!page_limit) {
1511 isc_throw(BadValue, "'limit' parameter not specified");
1512 }
1513
1514 // The 'limit' must be a number.
1515 if (page_limit->getType() != Element::integer) {
1516 isc_throw(BadValue, "'limit' parameter must be a number");
1517 }
1518
1519 // Retrieve the desired page size.
1520 size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
1521
1522 ElementPtr leases_json = Element::createList();
1523
1524 if (v4) {
1525 // Get page of IPv4 leases.
1526 Lease4Collection leases =
1527 LeaseMgrFactory::instance().getLeases4(*from_address,
1528 LeasePageSize(page_limit_value));
1529
1530 // Convert leases into JSON list.
1531 for (auto const& lease : leases) {
1532 ElementPtr lease_json = lease->toElement();
1533 leases_json->add(lease_json);
1534 }
1535
1536 } else {
1537 // Get page of IPv6 leases.
1538 Lease6Collection leases =
1539 LeaseMgrFactory::instance().getLeases6(*from_address,
1540 LeasePageSize(page_limit_value));
1541 // Convert leases into JSON list.
1542 for (auto const& lease : leases) {
1543 ElementPtr lease_json = lease->toElement();
1544 leases_json->add(lease_json);
1545 }
1546 }
1547
1548 // Prepare textual status.
1549 std::ostringstream s;
1550 s << leases_json->size()
1551 << " IPv" << (v4 ? "4" : "6")
1552 << " lease(s) found.";
1554
1555 // Put gathered data into arguments map.
1556 args->set("leases", leases_json);
1557 args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1558
1559 // Create the response.
1560 ConstElementPtr response =
1561 createAnswer(leases_json->size() > 0 ?
1564 s.str(), args);
1565 setResponse(handle, response);
1566
1567 } catch (const std::exception& ex) {
1568 setErrorResponse(handle, ex.what());
1569 return (CONTROL_RESULT_ERROR);
1570 }
1571
1572 return (CONTROL_RESULT_SUCCESS);
1573}
1574
1575int
1577 try {
1578 extractCommand(handle);
1579
1580 // arguments must always be present
1581 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1582 isc_throw(BadValue, "Command arguments missing or a not a map.");
1583 }
1584
1585 // the hw-address parameter is mandatory.
1586 ConstElementPtr hw_address = cmd_args_->get("hw-address");
1587 if (!hw_address) {
1588 isc_throw(BadValue, "'hw-address' parameter not specified");
1589 }
1590
1591 // The 'hw-address' argument is a string.
1592 if (hw_address->getType() != Element::string) {
1593 isc_throw(BadValue, "'hw-address' parameter must be a string");
1594 }
1595
1596 HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
1597
1598 Lease4Collection leases =
1600 ElementPtr leases_json = Element::createList();
1601 for (auto const& lease : leases) {
1602 ElementPtr lease_json = lease->toElement();
1603 leases_json->add(lease_json);
1604 }
1605
1606 std::ostringstream s;
1607 s << leases_json->size() << " IPv4 lease(s) found.";
1609 args->set("leases", leases_json);
1610 ConstElementPtr response =
1611 createAnswer(leases_json->size() > 0 ?
1614 s.str(), args);
1615 setResponse(handle, response);
1616
1617 } catch (const std::exception& ex) {
1618 setErrorResponse(handle, ex.what());
1619 return (CONTROL_RESULT_ERROR);
1620 }
1621
1622 return (0);
1623}
1624
1625int
1627 try {
1628 extractCommand(handle);
1629
1630 // arguments must always be present
1631 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1632 isc_throw(BadValue, "Command arguments missing or a not a map.");
1633 }
1634
1635 // the client-id parameter is mandatory.
1636 ConstElementPtr client_id = cmd_args_->get("client-id");
1637 if (!client_id) {
1638 isc_throw(BadValue, "'client-id' parameter not specified");
1639 }
1640
1641 // The 'client-id' argument is a string.
1642 if (client_id->getType() != Element::string) {
1643 isc_throw(BadValue, "'client-id' parameter must be a string");
1644 }
1645
1646 ClientIdPtr clientid = ClientId::fromText(client_id->stringValue());
1647
1648 Lease4Collection leases =
1650 ElementPtr leases_json = Element::createList();
1651 for (auto const& lease : leases) {
1652 ElementPtr lease_json = lease->toElement();
1653 leases_json->add(lease_json);
1654 }
1655
1656 std::ostringstream s;
1657 s << leases_json->size() << " IPv4 lease(s) found.";
1659 args->set("leases", leases_json);
1660 ConstElementPtr response =
1661 createAnswer(leases_json->size() > 0 ?
1664 s.str(), args);
1665 setResponse(handle, response);
1666
1667 } catch (const std::exception& ex) {
1668 setErrorResponse(handle, ex.what());
1669 return (CONTROL_RESULT_ERROR);
1670 }
1671
1672 return (0);
1673}
1674
1675int
1677 try {
1678 extractCommand(handle);
1679
1680 // arguments must always be present
1681 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1682 isc_throw(BadValue, "Command arguments missing or a not a map.");
1683 }
1684
1685 // the duid parameter is mandatory.
1686 ConstElementPtr duid = cmd_args_->get("duid");
1687 if (!duid) {
1688 isc_throw(BadValue, "'duid' parameter not specified");
1689 }
1690
1691 // The 'duid' argument is a string.
1692 if (duid->getType() != Element::string) {
1693 isc_throw(BadValue, "'duid' parameter must be a string");
1694 }
1695
1696 DUID duid_ = DUID::fromText(duid->stringValue());
1697
1698 Lease6Collection leases =
1700 ElementPtr leases_json = Element::createList();
1701 for (auto const& lease : leases) {
1702 ElementPtr lease_json = lease->toElement();
1703 leases_json->add(lease_json);
1704 }
1705
1706 std::ostringstream s;
1707 s << leases_json->size() << " IPv6 lease(s) found.";
1709 args->set("leases", leases_json);
1710 ConstElementPtr response =
1711 createAnswer(leases_json->size() > 0 ?
1714 s.str(), args);
1715 setResponse(handle, response);
1716
1717 } catch (const std::exception& ex) {
1718 setErrorResponse(handle, ex.what());
1719 return (CONTROL_RESULT_ERROR);
1720 }
1721
1722 return (0);
1723}
1724
1725int
1727 bool v4 = true;
1728 try {
1729 extractCommand(handle);
1730 v4 = (cmd_name_ == "lease4-get-by-hostname");
1731
1732 // arguments must always be present
1733 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1734 isc_throw(BadValue, "Command arguments missing or a not a map.");
1735 }
1736
1737 // the hostname parameter is mandatory.
1738 ConstElementPtr hostname = cmd_args_->get("hostname");
1739 if (!hostname) {
1740 isc_throw(BadValue, "'hostname' parameter not specified");
1741 }
1742
1743 // The 'hostname' argument is a string.
1744 if (hostname->getType() != Element::string) {
1745 isc_throw(BadValue, "'hostname' parameter must be a string");
1746 }
1747
1748 std::string hostname_ = hostname->stringValue();
1750 if (hostname_.empty()) {
1751 isc_throw(BadValue, "'hostname' parameter is empty");
1752 }
1753 boost::algorithm::to_lower(hostname_);
1754
1755 ElementPtr leases_json = Element::createList();
1756 if (v4) {
1757 Lease4Collection leases =
1759
1760 for (auto const& lease : leases) {
1761 ElementPtr lease_json = lease->toElement();
1762 leases_json->add(lease_json);
1763 }
1764 } else {
1765 Lease6Collection leases =
1767
1768 for (auto const& lease : leases) {
1769 ElementPtr lease_json = lease->toElement();
1770 leases_json->add(lease_json);
1771 }
1772 }
1773
1774 std::ostringstream s;
1775 s << leases_json->size()
1776 << " IPv" << (v4 ? "4" : "6")
1777 << " lease(s) found.";
1779 args->set("leases", leases_json);
1780 ConstElementPtr response =
1781 createAnswer(leases_json->size() > 0 ?
1784 s.str(), args);
1785 setResponse(handle, response);
1786
1787 } catch (const std::exception& ex) {
1788 setErrorResponse(handle, ex.what());
1789 return (CONTROL_RESULT_ERROR);
1790 }
1791
1792 return (0);
1793}
1794
1795int
1797 Parameters p;
1798 Lease4Ptr lease4;
1799 try {
1800 extractCommand(handle);
1801 p = getParameters(false, cmd_args_);
1802 switch (p.query_type) {
1803 case Parameters::TYPE_ADDR: {
1804 // If address was specified explicitly, let's use it as is.
1806 if (!lease4) {
1807 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1808 return (0);
1809 }
1810 break;
1811 }
1813 if (!p.hwaddr) {
1814 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1815 "requires hwaddr to be specified");
1816 }
1817
1818 // Let's see if there's such a lease at all.
1820 if (!lease4) {
1821 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1822 return (0);
1823 }
1824 break;
1825 }
1827 if (!p.client_id) {
1828 isc_throw(InvalidParameter, "Program error: Query by client-id "
1829 "requires client-id to be specified");
1830 }
1831
1832 // Let's see if there's such a lease at all.
1834 if (!lease4) {
1835 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1836 return (0);
1837 }
1838 break;
1839 }
1840 case Parameters::TYPE_DUID: {
1841 isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
1842 break;
1843 }
1844 default: {
1845 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1846 break;
1847 }
1848 }
1849
1850 if (LeaseMgrFactory::instance().deleteLease(lease4)) {
1851 setSuccessResponse(handle, "IPv4 lease deleted.");
1853 } else {
1854 setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1855 }
1856
1857 // Queue an NCR to remove DNS if configured and the lease has it.
1858 if (p.updateDDNS) {
1859 queueNCR(CHG_REMOVE, lease4);
1860 }
1861
1862 } catch (const std::exception& ex) {
1864 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1865 .arg(ex.what());
1866 setErrorResponse(handle, ex.what());
1867 return (1);
1868 }
1870 .arg(lease4->addr_.toText());
1871 return (0);
1872}
1873
1874int
1876 try {
1877 extractCommand(handle);
1878
1879 // Arguments are mandatory.
1880 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1881 isc_throw(BadValue, "Command arguments missing or a not a map.");
1882 }
1883
1884 // At least one of the 'deleted-leases' or 'leases' must be present.
1885 auto deleted_leases = cmd_args_->get("deleted-leases");
1886 auto leases = cmd_args_->get("leases");
1887
1888 if (!deleted_leases && !leases) {
1889 isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1890 " specified");
1891 }
1892
1893 // Make sure that 'deleted-leases' is a list, if present.
1894 if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1895 isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1896 }
1897
1898 // Make sure that 'leases' is a list, if present.
1899 if (leases && (leases->getType() != Element::list)) {
1900 isc_throw(BadValue, "the 'leases' parameter must be a list");
1901 }
1902
1903 // Parse deleted leases without deleting them from the database
1904 // yet. If any of the deleted leases or new leases appears to be
1905 // malformed we can easily rollback.
1906 std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1907 if (deleted_leases) {
1908 auto leases_list = deleted_leases->listValue();
1909
1910 // Iterate over leases to be deleted.
1911 for (auto const& lease_params : leases_list) {
1912 // Parsing the lease may throw and it means that the lease
1913 // information is malformed.
1914 Parameters p = getParameters(true, lease_params);
1915 auto lease = getIPv6LeaseForDelete(p);
1916 parsed_deleted_list.push_back(std::make_pair(p, lease));
1917 }
1918 }
1919
1920 // Parse new/updated leases without affecting the database to detect
1921 // any errors that should cause an error response.
1922 std::list<Lease6Ptr> parsed_leases_list;
1923 if (leases) {
1925
1926 // Iterate over all leases.
1927 auto leases_list = leases->listValue();
1928 for (auto const& lease_params : leases_list) {
1929
1930 Lease6Parser parser;
1931 bool force_update;
1932
1933 // If parsing the lease fails we throw, as it indicates that the
1934 // command is malformed.
1935 Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1936 parsed_leases_list.push_back(lease6);
1937 }
1938 }
1939
1940 // Count successful deletions and updates.
1941 size_t success_count = 0;
1942
1943 ElementPtr failed_deleted_list;
1944 if (!parsed_deleted_list.empty()) {
1945
1946 // Iterate over leases to be deleted.
1947 for (auto const& lease_params_pair : parsed_deleted_list) {
1948
1949 // This part is outside of the try-catch because an exception
1950 // indicates that the command is malformed.
1951 Parameters p = lease_params_pair.first;
1952 auto lease = lease_params_pair.second;
1953
1954 try {
1955 if (lease) {
1956 // This may throw if the lease couldn't be deleted for
1957 // any reason, but we still want to proceed with other
1958 // leases.
1959 if (LeaseMgrFactory::instance().deleteLease(lease)) {
1960 ++success_count;
1962
1963 } else {
1964 // Lazy creation of the list of leases which failed to delete.
1965 if (!failed_deleted_list) {
1966 failed_deleted_list = Element::createList();
1967 }
1968
1969 // If the lease doesn't exist we also want to put it
1970 // on the list of leases which failed to delete. That
1971 // corresponds to the lease6-del command which returns
1972 // an error when the lease doesn't exist.
1973 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1974 p.addr, p.duid,
1976 "lease not found"));
1977 }
1978 }
1979
1980 } catch (const std::exception& ex) {
1981 // Lazy creation of the list of leases which failed to delete.
1982 if (!failed_deleted_list) {
1983 failed_deleted_list = Element::createList();
1984 }
1985 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1986 p.addr, p.duid,
1988 ex.what()));
1989 }
1990 }
1991 }
1992
1993 // Process leases to be added or/and updated.
1994 ElementPtr failed_leases_list;
1995 if (!parsed_leases_list.empty()) {
1997
1998 // Iterate over all leases.
1999 for (auto const& lease : parsed_leases_list) {
2000
2001 auto result = CONTROL_RESULT_SUCCESS;
2002 std::ostringstream text;
2003 try {
2004 if (!MultiThreadingMgr::instance().getMode()) {
2005 // Not multi-threading.
2006 addOrUpdate6(lease, true);
2007 } else {
2008 // Multi-threading, try to lock first to avoid a race.
2009 ResourceHandler resource_handler;
2010 if (resource_handler.tryLock(lease->type_, lease->addr_)) {
2011 addOrUpdate6(lease, true);
2012 } else {
2014 "ResourceBusy: IP address:" << lease->addr_
2015 << " could not be updated.");
2016 }
2017 }
2018
2019 ++success_count;
2020 } catch (const LeaseCmdsConflict& ex) {
2021 result = CONTROL_RESULT_CONFLICT;
2022 text << ex.what();
2023
2024 } catch (const std::exception& ex) {
2025 result = CONTROL_RESULT_ERROR;
2026 text << ex.what();
2027 }
2028 // Handle an error.
2029 if (result != CONTROL_RESULT_SUCCESS) {
2030 // Lazy creation of the list of leases which failed to add/update.
2031 if (!failed_leases_list) {
2032 failed_leases_list = Element::createList();
2033 }
2034 failed_leases_list->add(createFailedLeaseMap(lease->type_,
2035 lease->addr_,
2036 lease->duid_,
2037 result,
2038 text.str()));
2039 }
2040 }
2041 }
2042
2043 // Start preparing the response.
2044 ElementPtr args;
2045
2046 if (failed_deleted_list || failed_leases_list) {
2047 // If there are any failed leases, let's include them in the response.
2048 args = Element::createMap();
2049
2050 // failed-deleted-leases
2051 if (failed_deleted_list) {
2052 args->set("failed-deleted-leases", failed_deleted_list);
2053 }
2054
2055 // failed-leases
2056 if (failed_leases_list) {
2057 args->set("failed-leases", failed_leases_list);
2058 }
2059 }
2060
2061 // Send the success response and include failed leases.
2062 std::ostringstream resp_text;
2063 resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
2064 auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
2065 CONTROL_RESULT_EMPTY, resp_text.str(), args);
2066 setResponse(handle, answer);
2067
2070 .arg(success_count);
2071
2072 } catch (const std::exception& ex) {
2073 // Unable to parse the command and similar issues.
2075 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2076 .arg(ex.what());
2077 setErrorResponse(handle, ex.what());
2078 return (CONTROL_RESULT_ERROR);
2079 }
2080
2081 return (0);
2082}
2083
2084int
2086 Parameters p;
2087 Lease6Ptr lease6;
2089 try {
2090 extractCommand(handle);
2091 p = getParameters(true, cmd_args_);
2092
2093 switch (p.query_type) {
2094 case Parameters::TYPE_ADDR: {
2095 // If address was specified explicitly, let's use it as is.
2096
2097 // Let's see if there's such a lease at all.
2099 if (!lease6) {
2100 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2101 return (0);
2102 }
2103 break;
2104 }
2106 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2107 break;
2108 }
2109 case Parameters::TYPE_DUID: {
2110 if (!p.duid) {
2111 isc_throw(InvalidParameter, "Program error: Query by duid "
2112 "requires duid to be specified");
2113 }
2114
2115 // Let's see if there's such a lease at all.
2117 p.iaid, p.subnet_id);
2118 if (!lease6) {
2119 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2120 return (0);
2121 }
2122 break;
2123 }
2124 default: {
2125 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
2126 break;
2127 }
2128 }
2129
2130 if (LeaseMgrFactory::instance().deleteLease(lease6)) {
2131 setSuccessResponse(handle, "IPv6 lease deleted.");
2133 } else {
2134 setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2135 }
2136
2137 // Queue an NCR to remove DNS if configured and the lease has it.
2138 if (p.updateDDNS) {
2139 queueNCR(CHG_REMOVE, lease6);
2140 }
2141
2142 } catch (const std::exception& ex) {
2144 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2145 .arg(ex.what());
2146 setErrorResponse(handle, ex.what());
2147 return (1);
2148 }
2149
2151 .arg(lease6->addr_.toText());
2152 return (0);
2153}
2154
2155int
2157 try {
2158 extractCommand(handle);
2159
2160 // We need the lease to be specified.
2161 if (!cmd_args_) {
2162 isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
2163 }
2164
2165 // Get the parameters specified by the user first.
2167 Lease4Ptr lease4;
2168 Lease4Parser parser;
2169 bool force_create = false;
2170
2171 // The parser does sanity checks (if the address is in scope, if
2172 // subnet-id is valid, etc)
2173 lease4 = parser.parse(config, cmd_args_, force_create);
2174 bool added = false;
2175 if (!MultiThreadingMgr::instance().getMode()) {
2176 // Not multi-threading.
2177 added = addOrUpdate4(lease4, force_create);
2178 } else {
2179 // Multi-threading, try to lock first to avoid a race.
2180 ResourceHandler4 resource_handler;
2181 if (resource_handler.tryLock4(lease4->addr_)) {
2182 added = addOrUpdate4(lease4, force_create);
2183 } else {
2185 "ResourceBusy: IP address:" << lease4->addr_
2186 << " could not be updated.");
2187 }
2188 }
2189
2190 if (added) {
2191 setSuccessResponse(handle, "IPv4 lease added.");
2192 } else {
2193 setSuccessResponse(handle, "IPv4 lease updated.");
2194 }
2197 .arg(lease4->addr_.toText());
2198
2199 } catch (const LeaseCmdsConflict& ex) {
2201 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2202 .arg(ex.what());
2204 return (0);
2205
2206 } catch (const std::exception& ex) {
2208 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2209 .arg(ex.what());
2210 setErrorResponse(handle, ex.what());
2211 return (1);
2212 }
2213
2214 return (0);
2215}
2216
2217int
2219 try {
2220 extractCommand(handle);
2221
2222 // We need the lease to be specified.
2223 if (!cmd_args_) {
2224 isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
2225 }
2226
2227 // Get the parameters specified by the user first.
2229 Lease6Ptr lease6;
2230 Lease6Parser parser;
2231 bool force_create = false;
2232
2233 // The parser does sanity checks (if the address is in scope, if
2234 // subnet-id is valid, etc)
2235 lease6 = parser.parse(config, cmd_args_, force_create);
2236 bool added = false;
2237 if (!MultiThreadingMgr::instance().getMode()) {
2238 // Not multi-threading.
2239 added = addOrUpdate6(lease6, force_create);
2240 } else {
2241 // Multi-threading, try to lock first to avoid a race.
2242 ResourceHandler resource_handler;
2243 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
2244 added = addOrUpdate6(lease6, force_create);
2245 } else {
2247 "ResourceBusy: IP address:" << lease6->addr_
2248 << " could not be updated.");
2249 }
2250 }
2251
2252 if (added) {
2253 setSuccessResponse(handle, "IPv6 lease added.");
2254 } else {
2255 setSuccessResponse(handle, "IPv6 lease updated.");
2256 }
2259 .arg(lease6->addr_.toText());
2260
2261 } catch (const LeaseCmdsConflict& ex) {
2263 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2264 .arg(ex.what());
2266 return (0);
2267
2268 } catch (const std::exception& ex) {
2270 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2271 .arg(ex.what());
2272 setErrorResponse(handle, ex.what());
2273 return (1);
2274 }
2275
2276 return (0);
2277}
2278
2279int
2281 try {
2282 extractCommand(handle);
2283
2284 SimpleParser parser;
2285 SubnetID id = 0;
2286
2287 size_t num = 0; // number of leases deleted
2288 stringstream ids; // a text with subnet-ids being wiped
2289
2290 // The subnet-id parameter is now optional.
2291 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2292 id = parser.getUint32(cmd_args_, "subnet-id");
2293 }
2294
2295 if (id) {
2296 // Wipe a single subnet.
2298 ids << " " << id;
2299
2300 auto observation = StatsMgr::instance().getObservation(
2301 StatsMgr::generateName("subnet", id, "declined-addresses"));
2302
2303 int64_t previous_declined = 0;
2304
2305 if (observation) {
2306 previous_declined = observation->getInteger().first;
2307 }
2308
2310 StatsMgr::generateName("subnet", id, "assigned-addresses"),
2311 static_cast<int64_t>(0));
2312
2314 StatsMgr::generateName("subnet", id, "declined-addresses"),
2315 static_cast<int64_t>(0));
2316
2317 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(id);
2318 if (sub) {
2319 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2320 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2321 StatsMgr::generateName("pool", pool->getID(),
2322 "assigned-addresses")));
2323 if (!StatsMgr::instance().getObservation(name_aa)) {
2324 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2325 }
2326
2327 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2328 StatsMgr::generateName("pool", pool->getID(),
2329 "declined-addresses")));
2330 if (!StatsMgr::instance().getObservation(name_da)) {
2331 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2332 }
2333 }
2334 }
2335
2336 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2337 } else {
2338 // Wipe them all!
2340 ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
2341 const Subnet4Collection* subs = subnets->getAll();
2342
2343 // Go over all subnets and wipe leases in each of them.
2344 for (auto const& sub : *subs) {
2345 num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
2346 ids << " " << sub->getID();
2348 StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
2349 static_cast<int64_t>(0));
2350
2352 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2353 static_cast<int64_t>(0));
2354
2355 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2356 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2357 StatsMgr::generateName("pool", pool->getID(),
2358 "assigned-addresses")));
2359 if (!StatsMgr::instance().getObservation(name_aa)) {
2360 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2361 }
2362
2363 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2364 StatsMgr::generateName("pool", pool->getID(),
2365 "declined-addresses")));
2366 if (!StatsMgr::instance().getObservation(name_da)) {
2367 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2368 }
2369 }
2370 }
2371
2372 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2373 }
2374
2375 stringstream tmp;
2376 tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
2378 : CONTROL_RESULT_EMPTY, tmp.str());
2379 setResponse(handle, response);
2380 } catch (const std::exception& ex) {
2382 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2383 .arg(ex.what());
2384 setErrorResponse(handle, ex.what());
2385 return (1);
2386 }
2387
2389 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2390 return (0);
2391}
2392
2393int
2395 try {
2396 extractCommand(handle);
2397
2398 SimpleParser parser;
2399 SubnetID id = 0;
2400
2401 size_t num = 0; // number of leases deleted
2402 stringstream ids; // a text with subnet-ids being wiped
2403
2408
2409 // The subnet-id parameter is now optional.
2410 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2411 id = parser.getUint32(cmd_args_, "subnet-id");
2412 }
2413
2414 if (id) {
2415 // Wipe a single subnet.
2417 ids << " " << id;
2418
2419 auto observation = StatsMgr::instance().getObservation(
2420 StatsMgr::generateName("subnet", id, "declined-addresses"));
2421
2422 int64_t previous_declined = 0;
2423
2424 if (observation) {
2425 previous_declined = observation->getInteger().first;
2426 }
2427
2429 StatsMgr::generateName("subnet", id, "assigned-nas" ),
2430 static_cast<int64_t>(0));
2431
2433 StatsMgr::generateName("subnet", id, "assigned-pds"),
2434 static_cast<int64_t>(0));
2435
2437 StatsMgr::generateName("subnet", id, "declined-addresses"),
2438 static_cast<int64_t>(0));
2439
2441 StatsMgr::generateName("subnet", id, "registered-nas"),
2442 static_cast<int64_t>(0));
2443
2444 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(id);
2445 if (sub) {
2446 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2447 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2448 StatsMgr::generateName("pool", pool->getID(),
2449 "assigned-nas")));
2450 if (!StatsMgr::instance().getObservation(name_anas)) {
2451 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2452 }
2453
2454 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2455 StatsMgr::generateName("pool", pool->getID(),
2456 "declined-addresses")));
2457 if (!StatsMgr::instance().getObservation(name_da)) {
2458 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2459 }
2460 }
2461
2462 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2463 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2464 StatsMgr::generateName("pd-pool", pool->getID(),
2465 "assigned-pds")));
2466 if (!StatsMgr::instance().getObservation(name_apds)) {
2467 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2468 }
2469 }
2470 }
2471
2472 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2473 } else {
2474 // Wipe them all!
2476 ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2477 const Subnet6Collection* subs = subnets->getAll();
2478
2479 // Go over all subnets and wipe leases in each of them.
2480 for (auto const& sub : *subs) {
2481 num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2482 ids << " " << sub->getID();
2484 StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2485 static_cast<int64_t>(0));
2486
2488 StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2489 static_cast<int64_t>(0));
2490
2492 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2493 static_cast<int64_t>(0));
2494
2496 StatsMgr::generateName("subnet", sub->getID(), "registered-nas"),
2497 static_cast<int64_t>(0));
2498
2499 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2500 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2501 StatsMgr::generateName("pool", pool->getID(),
2502 "assigned-nas")));
2503 if (!StatsMgr::instance().getObservation(name_anas)) {
2504 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2505 }
2506
2507 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2508 StatsMgr::generateName("pool", pool->getID(),
2509 "declined-addresses")));
2510 if (!StatsMgr::instance().getObservation(name_da)) {
2511 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2512 }
2513 }
2514
2515 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2516 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2517 StatsMgr::generateName("pd-pool", pool->getID(),
2518 "assigned-pds")));
2519 if (!StatsMgr::instance().getObservation(name_apds)) {
2520 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2521 }
2522 }
2523 }
2524
2525 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2526 }
2527
2528 stringstream tmp;
2529 tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2531 : CONTROL_RESULT_EMPTY, tmp.str());
2532 setResponse(handle, response);
2533 } catch (const std::exception& ex) {
2535 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2536 .arg(ex.what());
2537 setErrorResponse(handle, ex.what());
2538 return (1);
2539 }
2540
2542 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2543 return (0);
2544}
2545
2548 Lease6Ptr lease6;
2549
2550 switch (parameters.query_type) {
2551 case Parameters::TYPE_ADDR: {
2552 // If address was specified explicitly, let's use it as is.
2553
2554 // Let's see if there's such a lease at all.
2555 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2556 parameters.addr);
2557 if (!lease6) {
2558 lease6.reset(new Lease6());
2559 lease6->addr_ = parameters.addr;
2560 }
2561 break;
2562 }
2564 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2565 break;
2566 }
2567 case Parameters::TYPE_DUID: {
2568 if (!parameters.duid) {
2569 isc_throw(InvalidParameter, "Program error: Query by duid "
2570 "requires duid to be specified");
2571 }
2572
2573 // Let's see if there's such a lease at all.
2574 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2575 *parameters.duid,
2576 parameters.iaid,
2577 parameters.subnet_id);
2578 break;
2579 }
2580 default:
2581 isc_throw(InvalidOperation, "Unknown query type: "
2582 << static_cast<int>(parameters.query_type));
2583 }
2584
2585 return (lease6);
2586}
2587
2590 short family) const {
2591 ConstElementPtr param = params->get(name);
2592 if (!param) {
2593 isc_throw(BadValue, "'" << name << "' parameter is missing.");
2594 }
2595
2596 if (param->getType() != Element::string) {
2597 isc_throw(BadValue, "'" << name << "' is not a string.");
2598 }
2599
2600 IOAddress addr(0);
2601 try {
2602 addr = IOAddress(param->stringValue());
2603 } catch (const std::exception& ex) {
2604 isc_throw(BadValue, "'" << param->stringValue()
2605 << "' is not a valid IP address.");
2606 }
2607
2608 if (addr.getFamily() != family) {
2609 isc_throw(BadValue, "Invalid "
2610 << (family == AF_INET6 ? "IPv6" : "IPv4")
2611 << " address specified: " << param->stringValue());
2612 }
2613
2614 return (addr);
2615}
2616
2617int
2619 std::stringstream ss;
2620 int resp_code = CONTROL_RESULT_ERROR;
2621
2622 try {
2623 extractCommand(handle);
2624
2625 // Get the target lease address. Invalid value will throw.
2626 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2627
2628 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2629 ss << "DDNS updating is not enabled";
2630 resp_code = CONTROL_RESULT_CONFLICT;
2631 } else {
2632 // Find the lease.
2634 if (!lease) {
2635 ss << "No lease found for: " << addr.toText();
2636 resp_code = CONTROL_RESULT_EMPTY;
2637 } else if (lease->hostname_.empty()) {
2638 ss << "Lease for: " << addr.toText()
2639 << ", has no hostname, nothing to update";
2640 resp_code = CONTROL_RESULT_CONFLICT;
2641 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2642 ss << "Neither forward nor reverse updates enabled for lease for: "
2643 << addr.toText();
2644 resp_code = CONTROL_RESULT_CONFLICT;
2645 } else {
2646 // We have a lease with a hostname and updates in at least
2647 // one direction enabled. Queue an NCR for it.
2648 queueNCR(CHG_ADD, lease);
2649 ss << "NCR generated for: " << addr.toText()
2650 << ", hostname: " << lease->hostname_;
2651 setSuccessResponse(handle, ss.str());
2653 return (0);
2654 }
2655 }
2656 } catch (const std::exception& ex) {
2657 ss << ex.what();
2658 }
2659
2661 setErrorResponse(handle, ss.str(), resp_code);
2662 return (resp_code == CONTROL_RESULT_EMPTY || resp_code == CONTROL_RESULT_CONFLICT ? 0 : 1);
2663}
2664
2665int
2667 std::stringstream ss;
2668 int resp_code = CONTROL_RESULT_ERROR;
2669
2670 try {
2671 extractCommand(handle);
2672
2673 // Get the target lease address. Invalid value will throw.
2674 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2675
2676 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2677 ss << "DDNS updating is not enabled";
2678 resp_code = CONTROL_RESULT_CONFLICT;
2679 } else {
2680 // Find the lease.
2682 if (!lease) {
2683 ss << "No lease found for: " << addr.toText();
2684 resp_code = CONTROL_RESULT_EMPTY;
2685 } else if (lease->hostname_.empty()) {
2686 ss << "Lease for: " << addr.toText()
2687 << ", has no hostname, nothing to update";
2688 resp_code = CONTROL_RESULT_CONFLICT;
2689 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2690 ss << "Neither forward nor reverse updates enabled for lease for: "
2691 << addr.toText();
2692 resp_code = CONTROL_RESULT_CONFLICT;
2693 } else {
2694 // We have a lease with a hostname and updates in at least
2695 // one direction enabled. Queue an NCR for it.
2696 queueNCR(CHG_ADD, lease);
2697 ss << "NCR generated for: " << addr.toText()
2698 << ", hostname: " << lease->hostname_;
2699 setSuccessResponse(handle, ss.str());
2701 return (0);
2702 }
2703 }
2704 } catch (const std::exception& ex) {
2705 ss << ex.what();
2706 }
2707
2709 setErrorResponse(handle, ss.str(), resp_code);
2710 return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2711}
2712
2715 const IOAddress& lease_address,
2716 const DuidPtr& duid,
2717 const int control_result,
2718 const std::string& error_message) const {
2719 auto failed_lease_map = Element::createMap();
2720 failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2721
2722 if (!lease_address.isV6Zero()) {
2723 failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2724
2725 } else if (duid) {
2726 failed_lease_map->set("duid", Element::create(duid->toText()));
2727 }
2728
2729 // Associate the result with the lease.
2730 failed_lease_map->set("result", Element::create(control_result));
2731 failed_lease_map->set("error-message", Element::create(error_message));
2732
2733 return (failed_lease_map);
2734}
2735
2736int
2738 bool v4 = true;
2739 try {
2740 extractCommand(handle);
2741 v4 = (cmd_name_ == "lease4-write");
2742
2743 if (!cmd_args_) {
2744 isc_throw(isc::BadValue, "no parameters specified for the command");
2745 }
2746
2747 ConstElementPtr file = cmd_args_->get("filename");
2748 if (!file) {
2749 isc_throw(BadValue, "'filename' parameter not specified");
2750 }
2751 if (file->getType() != Element::string) {
2752 isc_throw(BadValue, "'filename' parameter must be a string");
2753 }
2754
2755 std::string filename;
2756 try {
2757 filename = CfgMgr::instance().validatePath(file->stringValue());
2758 } catch (const std::exception& ex) {
2759 isc_throw(BadValue, "'filename' parameter is invalid: " << ex.what());
2760 }
2761
2762 if (v4) {
2764 } else {
2766 }
2767
2768 ostringstream s;
2769 s << (v4 ? "IPv4" : "IPv6")
2770 << " lease database into '"
2771 << filename << "'.";
2773 setResponse(handle, response);
2774 } catch (const std::exception& ex) {
2775 setErrorResponse(handle, ex.what());
2776 return (CONTROL_RESULT_ERROR);
2777 }
2778
2779 return (0);
2780}
2781
2782void
2785 uint32_t offer_lifetime;
2786 callout_handle.getArgument("offer_lifetime", offer_lifetime);
2787 if (!offer_lifetime) {
2788 // Offers leases are not being persisted, nothing to do.
2789 return;
2790 }
2791
2792 // Get the remaining arguments we need.
2793 Pkt4Ptr query;
2794 Pkt4Ptr response;
2795 Lease4CollectionPtr leases;
2796
2797 callout_handle.getArgument("query4", query);
2798 callout_handle.getArgument("response4", response);
2799 callout_handle.getArgument("leases4", leases);
2800
2801 if (!leases || leases->empty() || !((*leases)[0])) {
2802 isc_throw(Unexpected, "lease4Offer - no lease!");
2803 }
2804
2805 Lease4Ptr lease = (*leases)[0];
2806 try {
2807 if (mgr->evaluateVariables(query, response, lease)) {
2809 }
2810 } catch (const NoSuchLease&) {
2811 isc_throw(LeaseCmdsConflict, "failed to update"
2812 " the lease with address " << lease->addr_ <<
2813 " either because the lease has been"
2814 " deleted or it has changed in the database");
2815 } catch (const std::exception& ex) {
2816 isc_throw(Unexpected, "evaluating binding variables failed for: "
2817 << query->getLabel() << ", :" << ex.what());
2818 }
2819}
2820
2821void
2824 Pkt4Ptr query;
2825 Pkt4Ptr response;
2826 Lease4CollectionPtr leases;
2827
2828 // Get the necessary arguments.
2829 callout_handle.getArgument("query4", query);
2830 callout_handle.getArgument("response4", response);
2831 callout_handle.getArgument("leases4", leases);
2832
2833 if (!leases) {
2834 isc_throw(Unexpected, "leases4Committed - leases is null");
2835 }
2836
2837 // In some cases we may have no lease, e.g. DHCPNAK,
2838 // or no response e.g. DHCPRELEASE.
2839 if (leases->empty() || !response || (response->getType() != DHCPACK)) {
2840 return;
2841 }
2842
2843 Lease4Ptr lease = (*leases)[0];
2844 if (!lease) {
2845 isc_throw(Unexpected, "leases4Committed - lease is null");
2846 }
2847
2848 try {
2849 if (mgr->evaluateVariables(query, response, lease)) {
2851 }
2852 } catch (const NoSuchLease&) {
2853 isc_throw(LeaseCmdsConflict, "failed to update"
2854 " the lease with address " << lease->addr_ <<
2855 " either because the lease has been"
2856 " deleted or it has changed in the database");
2857 } catch (const std::exception& ex) {
2858 isc_throw(Unexpected, "evaluating binding variables failed for: "
2859 << query->getLabel() << ", :" << ex.what());
2860 }
2861}
2862
2863void
2866 Pkt6Ptr query;
2867 Pkt6Ptr response;
2868 Lease6CollectionPtr leases;
2869
2870 // Get the necessary arguments.
2871 callout_handle.getArgument("query6", query);
2872 callout_handle.getArgument("response6", response);
2873 callout_handle.getArgument("leases6", leases);
2874
2875 if (!leases) {
2876 isc_throw(Unexpected, "leases6Committed - leases is null");
2877 }
2878
2879 // In some cases we may have no active leases or no response.
2880 if (leases->empty() || !response) {
2881 return;
2882 }
2883
2884 int attempted = 0;
2885 int failed = 0;
2886 for (auto lease : *leases) {
2887 try {
2888 if (!lease) {
2889 isc_throw(Unexpected, "leases6Committed - lease is null");
2890 }
2891
2897 // Only update a lease if its active.
2898 if (lease->valid_lft_) {
2899 ++attempted;
2900 if (mgr->evaluateVariables(query, response, lease)) {
2902 }
2903 }
2904 } catch (const NoSuchLease&) {
2905 ++failed;
2907 .arg(lease->addr_.toText())
2908 .arg(query->getLabel());
2909 } catch (const std::exception& ex) {
2910 ++failed;
2912 .arg(query->getLabel())
2913 .arg(lease->addr_.toText())
2914 .arg(ex.what());
2915 }
2916 }
2917
2918 if (failed) {
2919 isc_throw(Unexpected, failed << " out of " << attempted
2920 << " leases failed to update for "
2921 << query->getLabel());
2922 }
2923}
2924
2925int
2927 return (impl_->leaseAddHandler(handle));
2928}
2929
2930int
2932 return (impl_->lease6BulkApplyHandler(handle));
2933}
2934
2935int
2937 return (impl_->leaseGetHandler(handle));
2938}
2939
2940int
2942 return (impl_->leaseGetAllHandler(handle));
2943}
2944
2945int
2947 return (impl_->leaseGetPageHandler(handle));
2948}
2949
2950int
2952 return (impl_->leaseGetByHwAddressHandler(handle));
2953}
2954
2955int
2957 return (impl_->leaseGetByClientIdHandler(handle));
2958}
2959
2960int
2962 return (impl_->leaseGetByDuidHandler(handle));
2963}
2964
2965int
2967 return (impl_->leaseGetByHostnameHandler(handle));
2968}
2969
2970int
2972 return (impl_->lease4DelHandler(handle));
2973}
2974
2975int
2977 return (impl_->lease6DelHandler(handle));
2978}
2979
2980int
2982 return (impl_->lease4UpdateHandler(handle));
2983}
2984
2985int
2987 return (impl_->lease6UpdateHandler(handle));
2988}
2989
2990int
2993 return (impl_->lease4WipeHandler(handle));
2994}
2995
2996int
2999 return (impl_->lease6WipeHandler(handle));
3000}
3001
3002int
3004 return (impl_->lease4ResendDdnsHandler(handle));
3005}
3006
3007int
3009 return (impl_->lease6ResendDdnsHandler(handle));
3010}
3011
3012int
3014 return (impl_->leaseWriteHandler(handle));
3015}
3016
3018}
3019
3020
3021void
3024 impl_->lease4Offer(callout_handle, mgr);
3025}
3026
3027void
3030 impl_->leases4Committed(callout_handle, mgr);
3031}
3032
3033void
3036 impl_->leases6Committed(callout_handle, mgr);
3037}
3038
3039} // end of namespace lease_cmds
3040} // end of namespace isc
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition duid.cc:50
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
@ map
Definition data.h:147
@ integer
Definition data.h:140
@ boolean
Definition data.h:142
@ list
Definition data.h:146
@ string
Definition data.h:144
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
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 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 DHDP 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.
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.
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.
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:46
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:57
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:75
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:61
@ TYPE_CLIENT_ID
query by client identifier (v4 only).
Definition lease_cmds.cc:65
@ TYPE_HWADDR
query by hardware address (v4 only)
Definition lease_cmds.cc:63
@ TYPE_ADDR
query by IP address (either v4 or v6)
Definition lease_cmds.cc:62
isc::dhcp::ClientIdPtr client_id
Specifies identifier value (used when query_type is TYPE_CLIENT_ID)
Definition lease_cmds.cc:81
static Type txtToType(const std::string &txt)
Attempts to covert text to one of specified types.
Definition lease_cmds.cc:92
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:72
SubnetID subnet_id
Specifies subnet-id (always used)
Definition lease_cmds.cc:69
isc::dhcp::DuidPtr duid
Specifies identifier value (used when query_type is TYPE_DUID)
Definition lease_cmds.cc:78
Wrapper class around reservation command handlers.
Definition lease_cmds.cc:53
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.
static void updateStatsOnUpdate(const Lease4Ptr &existing, const Lease4Ptr &lease)
Update stats when updating lease.
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.
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 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
static void updateStatsOnAdd(const Lease4Ptr &lease)
Update stats when adding lease.
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
static void updateStatsOnDelete(const Lease4Ptr &lease)
Update stats when deleting lease.
int lease4ResendDdnsHandler(hooks::CalloutHandle &handle)
lease4-resend-ddns command 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 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.
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_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_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_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_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_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
Definition lease.h:523
boost::shared_ptr< const SrvConfig > ConstSrvConfigPtr
Const pointer to the SrvConfig.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:623
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:458
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:555
boost::shared_ptr< DUID > DuidPtr
Definition duid.h:136
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:528
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition lease.h:693
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:937
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:154
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
Definition pool.h:726
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:866
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
@ DHCPACK
Definition dhcp4.h:239
boost::shared_ptr< const CfgSubnets4 > ConstCfgSubnets4Ptr
Const pointer.
boost::shared_ptr< const CfgSubnets6 > ConstCfgSubnets6Ptr
Const pointer.
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition lease.h:696
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:520
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:315
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.
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:69
Structure that holds a lease for IPv6 address and/or prefix.
Definition lease.h:536
@ ACTION_UPDATE
update extended info tables.
Definition lease.h:576
a common structure for IPv4 and IPv6 leases
Definition lease.h:31
Type
Type of lease or pool.
Definition lease.h:46
@ TYPE_TA
the lease contains temporary IPv6 address
Definition lease.h:48
@ 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
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:321
static std::string typeToText(Type type)
returns text representation of a lease type
Definition lease.cc:56