Kea 2.7.8
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()
2377 << " WARNING: lease4-wipe is deprecated!";
2379 : CONTROL_RESULT_EMPTY, tmp.str());
2380 setResponse(handle, response);
2381 } catch (const std::exception& ex) {
2383 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2384 .arg(ex.what());
2386 setErrorResponse(handle, ex.what());
2387 return (1);
2388 }
2389
2391 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2393 return (0);
2394}
2395
2396int
2398 try {
2399 extractCommand(handle);
2400
2401 SimpleParser parser;
2402 SubnetID id = 0;
2403
2404 size_t num = 0; // number of leases deleted
2405 stringstream ids; // a text with subnet-ids being wiped
2406
2411
2412 // The subnet-id parameter is now optional.
2413 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2414 id = parser.getUint32(cmd_args_, "subnet-id");
2415 }
2416
2417 if (id) {
2418 // Wipe a single subnet.
2420 ids << " " << id;
2421
2422 auto observation = StatsMgr::instance().getObservation(
2423 StatsMgr::generateName("subnet", id, "declined-addresses"));
2424
2425 int64_t previous_declined = 0;
2426
2427 if (observation) {
2428 previous_declined = observation->getInteger().first;
2429 }
2430
2432 StatsMgr::generateName("subnet", id, "assigned-nas" ),
2433 static_cast<int64_t>(0));
2434
2436 StatsMgr::generateName("subnet", id, "assigned-pds"),
2437 static_cast<int64_t>(0));
2438
2440 StatsMgr::generateName("subnet", id, "declined-addresses"),
2441 static_cast<int64_t>(0));
2442
2444 StatsMgr::generateName("subnet", id, "registered-nas"),
2445 static_cast<int64_t>(0));
2446
2447 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(id);
2448 if (sub) {
2449 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2450 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2451 StatsMgr::generateName("pool", pool->getID(),
2452 "assigned-nas")));
2453 if (!StatsMgr::instance().getObservation(name_anas)) {
2454 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2455 }
2456
2457 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2458 StatsMgr::generateName("pool", pool->getID(),
2459 "declined-addresses")));
2460 if (!StatsMgr::instance().getObservation(name_da)) {
2461 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2462 }
2463 }
2464
2465 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2466 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2467 StatsMgr::generateName("pd-pool", pool->getID(),
2468 "assigned-pds")));
2469 if (!StatsMgr::instance().getObservation(name_apds)) {
2470 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2471 }
2472 }
2473 }
2474
2475 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2476 } else {
2477 // Wipe them all!
2479 ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2480 const Subnet6Collection* subs = subnets->getAll();
2481
2482 // Go over all subnets and wipe leases in each of them.
2483 for (auto const& sub : *subs) {
2484 num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2485 ids << " " << sub->getID();
2487 StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2488 static_cast<int64_t>(0));
2489
2491 StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2492 static_cast<int64_t>(0));
2493
2495 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2496 static_cast<int64_t>(0));
2497
2499 StatsMgr::generateName("subnet", sub->getID(), "registered-nas"),
2500 static_cast<int64_t>(0));
2501
2502 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2503 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2504 StatsMgr::generateName("pool", pool->getID(),
2505 "assigned-nas")));
2506 if (!StatsMgr::instance().getObservation(name_anas)) {
2507 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2508 }
2509
2510 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2511 StatsMgr::generateName("pool", pool->getID(),
2512 "declined-addresses")));
2513 if (!StatsMgr::instance().getObservation(name_da)) {
2514 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2515 }
2516 }
2517
2518 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2519 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2520 StatsMgr::generateName("pd-pool", pool->getID(),
2521 "assigned-pds")));
2522 if (!StatsMgr::instance().getObservation(name_apds)) {
2523 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2524 }
2525 }
2526 }
2527
2528 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2529 }
2530
2531 stringstream tmp;
2532 tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str()
2533 << " WARNING: lease6-wipe is deprecated!";
2535 : CONTROL_RESULT_EMPTY, tmp.str());
2536 setResponse(handle, response);
2537 } catch (const std::exception& ex) {
2539 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2540 .arg(ex.what());
2542 setErrorResponse(handle, ex.what());
2543 return (1);
2544 }
2545
2547 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2549 return (0);
2550}
2551
2554 Lease6Ptr lease6;
2555
2556 switch (parameters.query_type) {
2557 case Parameters::TYPE_ADDR: {
2558 // If address was specified explicitly, let's use it as is.
2559
2560 // Let's see if there's such a lease at all.
2561 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2562 parameters.addr);
2563 if (!lease6) {
2564 lease6.reset(new Lease6());
2565 lease6->addr_ = parameters.addr;
2566 }
2567 break;
2568 }
2570 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2571 break;
2572 }
2573 case Parameters::TYPE_DUID: {
2574 if (!parameters.duid) {
2575 isc_throw(InvalidParameter, "Program error: Query by duid "
2576 "requires duid to be specified");
2577 }
2578
2579 // Let's see if there's such a lease at all.
2580 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2581 *parameters.duid,
2582 parameters.iaid,
2583 parameters.subnet_id);
2584 break;
2585 }
2586 default:
2587 isc_throw(InvalidOperation, "Unknown query type: "
2588 << static_cast<int>(parameters.query_type));
2589 }
2590
2591 return (lease6);
2592}
2593
2596 short family) const {
2597 ConstElementPtr param = params->get(name);
2598 if (!param) {
2599 isc_throw(BadValue, "'" << name << "' parameter is missing.");
2600 }
2601
2602 if (param->getType() != Element::string) {
2603 isc_throw(BadValue, "'" << name << "' is not a string.");
2604 }
2605
2606 IOAddress addr(0);
2607 try {
2608 addr = IOAddress(param->stringValue());
2609 } catch (const std::exception& ex) {
2610 isc_throw(BadValue, "'" << param->stringValue()
2611 << "' is not a valid IP address.");
2612 }
2613
2614 if (addr.getFamily() != family) {
2615 isc_throw(BadValue, "Invalid "
2616 << (family == AF_INET6 ? "IPv6" : "IPv4")
2617 << " address specified: " << param->stringValue());
2618 }
2619
2620 return (addr);
2621}
2622
2623int
2625 std::stringstream ss;
2626 int resp_code = CONTROL_RESULT_ERROR;
2627
2628 try {
2629 extractCommand(handle);
2630
2631 // Get the target lease address. Invalid value will throw.
2632 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2633
2634 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2635 ss << "DDNS updating is not enabled";
2636 resp_code = CONTROL_RESULT_CONFLICT;
2637 } else {
2638 // Find the lease.
2640 if (!lease) {
2641 ss << "No lease found for: " << addr.toText();
2642 resp_code = CONTROL_RESULT_EMPTY;
2643 } else if (lease->hostname_.empty()) {
2644 ss << "Lease for: " << addr.toText()
2645 << ", has no hostname, nothing to update";
2646 resp_code = CONTROL_RESULT_CONFLICT;
2647 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2648 ss << "Neither forward nor reverse updates enabled for lease for: "
2649 << addr.toText();
2650 resp_code = CONTROL_RESULT_CONFLICT;
2651 } else {
2652 // We have a lease with a hostname and updates in at least
2653 // one direction enabled. Queue an NCR for it.
2654 queueNCR(CHG_ADD, lease);
2655 ss << "NCR generated for: " << addr.toText()
2656 << ", hostname: " << lease->hostname_;
2657 setSuccessResponse(handle, ss.str());
2659 return (0);
2660 }
2661 }
2662 } catch (const std::exception& ex) {
2663 ss << ex.what();
2664 }
2665
2667 setErrorResponse(handle, ss.str(), resp_code);
2668 return (resp_code == CONTROL_RESULT_EMPTY || resp_code == CONTROL_RESULT_CONFLICT ? 0 : 1);
2669}
2670
2671int
2673 std::stringstream ss;
2674 int resp_code = CONTROL_RESULT_ERROR;
2675
2676 try {
2677 extractCommand(handle);
2678
2679 // Get the target lease address. Invalid value will throw.
2680 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2681
2682 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2683 ss << "DDNS updating is not enabled";
2684 resp_code = CONTROL_RESULT_CONFLICT;
2685 } else {
2686 // Find the lease.
2688 if (!lease) {
2689 ss << "No lease found for: " << addr.toText();
2690 resp_code = CONTROL_RESULT_EMPTY;
2691 } else if (lease->hostname_.empty()) {
2692 ss << "Lease for: " << addr.toText()
2693 << ", has no hostname, nothing to update";
2694 resp_code = CONTROL_RESULT_CONFLICT;
2695 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2696 ss << "Neither forward nor reverse updates enabled for lease for: "
2697 << addr.toText();
2698 resp_code = CONTROL_RESULT_CONFLICT;
2699 } else {
2700 // We have a lease with a hostname and updates in at least
2701 // one direction enabled. Queue an NCR for it.
2702 queueNCR(CHG_ADD, lease);
2703 ss << "NCR generated for: " << addr.toText()
2704 << ", hostname: " << lease->hostname_;
2705 setSuccessResponse(handle, ss.str());
2707 return (0);
2708 }
2709 }
2710 } catch (const std::exception& ex) {
2711 ss << ex.what();
2712 }
2713
2715 setErrorResponse(handle, ss.str(), resp_code);
2716 return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2717}
2718
2721 const IOAddress& lease_address,
2722 const DuidPtr& duid,
2723 const int control_result,
2724 const std::string& error_message) const {
2725 auto failed_lease_map = Element::createMap();
2726 failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2727
2728 if (!lease_address.isV6Zero()) {
2729 failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2730
2731 } else if (duid) {
2732 failed_lease_map->set("duid", Element::create(duid->toText()));
2733 }
2734
2735 // Associate the result with the lease.
2736 failed_lease_map->set("result", Element::create(control_result));
2737 failed_lease_map->set("error-message", Element::create(error_message));
2738
2739 return (failed_lease_map);
2740}
2741
2742int
2744 bool v4 = true;
2745 try {
2746 extractCommand(handle);
2747 v4 = (cmd_name_ == "lease4-write");
2748
2749 if (!cmd_args_) {
2750 isc_throw(isc::BadValue, "no parameters specified for the command");
2751 }
2752
2753 ConstElementPtr file = cmd_args_->get("filename");
2754 if (!file) {
2755 isc_throw(BadValue, "'filename' parameter not specified");
2756 }
2757 if (file->getType() != Element::string) {
2758 isc_throw(BadValue, "'filename' parameter must be a string");
2759 }
2760 string filename = file->stringValue();
2761 if (filename.empty()) {
2762 isc_throw(BadValue, "'filename' parameter is empty");
2763 }
2764
2765 if (v4) {
2767 } else {
2769 }
2770 ostringstream s;
2771 s << (v4 ? "IPv4" : "IPv6")
2772 << " lease database into '"
2773 << filename << "'.";
2775 setResponse(handle, response);
2776 } catch (const std::exception& ex) {
2777 setErrorResponse(handle, ex.what());
2778 return (CONTROL_RESULT_ERROR);
2779 }
2780
2781 return (0);
2782}
2783
2784void
2787 uint32_t offer_lifetime;
2788 callout_handle.getArgument("offer_lifetime", offer_lifetime);
2789 if (!offer_lifetime) {
2790 // Offers leases are not being persisted, nothing to do.
2791 return;
2792 }
2793
2794 // Get the remaining arguments we need.
2795 Pkt4Ptr query;
2796 Pkt4Ptr response;
2797 Lease4CollectionPtr leases;
2798
2799 callout_handle.getArgument("query4", query);
2800 callout_handle.getArgument("response4", response);
2801 callout_handle.getArgument("leases4", leases);
2802
2803 if (!leases || leases->empty() || !((*leases)[0])) {
2804 isc_throw(Unexpected, "lease4Offer - no lease!");
2805 }
2806
2807 Lease4Ptr lease = (*leases)[0];
2808 try {
2809 if (mgr->evaluateVariables(query, response, lease)) {
2811 }
2812 } catch (const NoSuchLease&) {
2813 isc_throw(LeaseCmdsConflict, "failed to update"
2814 " the lease with address " << lease->addr_ <<
2815 " either because the lease has been"
2816 " deleted or it has changed in the database");
2817 } catch (const std::exception& ex) {
2818 isc_throw(Unexpected, "evaluating binding variables failed for: "
2819 << query->getLabel() << ", :" << ex.what());
2820 }
2821}
2822
2823void
2826 Pkt4Ptr query;
2827 Pkt4Ptr response;
2828 Lease4CollectionPtr leases;
2829
2830 // Get the necessary arguments.
2831 callout_handle.getArgument("query4", query);
2832 callout_handle.getArgument("response4", response);
2833 callout_handle.getArgument("leases4", leases);
2834
2835 if (!leases) {
2836 isc_throw(Unexpected, "leases4Committed - leases is null");
2837 }
2838
2839 // In some cases we may have no lease, e.g. DHCPNAK,
2840 // or no response e.g. DHCPRELEASE.
2841 if (leases->empty() || !response || (response->getType() != DHCPACK)) {
2842 return;
2843 }
2844
2845 Lease4Ptr lease = (*leases)[0];
2846 if (!lease) {
2847 isc_throw(Unexpected, "leases4Committed - lease is null");
2848 }
2849
2850 try {
2851 if (mgr->evaluateVariables(query, response, lease)) {
2853 }
2854 } catch (const NoSuchLease&) {
2855 isc_throw(LeaseCmdsConflict, "failed to update"
2856 " the lease with address " << lease->addr_ <<
2857 " either because the lease has been"
2858 " deleted or it has changed in the database");
2859 } catch (const std::exception& ex) {
2860 isc_throw(Unexpected, "evaluating binding variables failed for: "
2861 << query->getLabel() << ", :" << ex.what());
2862 }
2863}
2864
2865void
2868 Pkt6Ptr query;
2869 Pkt6Ptr response;
2870 Lease6CollectionPtr leases;
2871
2872 // Get the necessary arguments.
2873 callout_handle.getArgument("query6", query);
2874 callout_handle.getArgument("response6", response);
2875 callout_handle.getArgument("leases6", leases);
2876
2877 if (!leases) {
2878 isc_throw(Unexpected, "leases6Committed - leases is null");
2879 }
2880
2881 // In some cases we may have no active leases or no response.
2882 if (leases->empty() || !response) {
2883 return;
2884 }
2885
2886 int attempted = 0;
2887 int failed = 0;
2888 for (auto lease : *leases) {
2889 try {
2890 if (!lease) {
2891 isc_throw(Unexpected, "leases6Committed - lease is null");
2892 }
2893
2899 // Only update a lease if its active.
2900 if (lease->valid_lft_) {
2901 ++attempted;
2902 if (mgr->evaluateVariables(query, response, lease)) {
2904 }
2905 }
2906 } catch (const NoSuchLease&) {
2907 ++failed;
2909 .arg(lease->addr_.toText())
2910 .arg(query->getLabel());
2911 } catch (const std::exception& ex) {
2912 ++failed;
2914 .arg(query->getLabel())
2915 .arg(lease->addr_.toText())
2916 .arg(ex.what());
2917 }
2918 }
2919
2920 if (failed) {
2921 isc_throw(Unexpected, failed << " out of " << attempted
2922 << " leases failed to update for "
2923 << query->getLabel());
2924 }
2925}
2926
2927int
2929 return (impl_->leaseAddHandler(handle));
2930}
2931
2932int
2934 return (impl_->lease6BulkApplyHandler(handle));
2935}
2936
2937int
2939 return (impl_->leaseGetHandler(handle));
2940}
2941
2942int
2944 return (impl_->leaseGetAllHandler(handle));
2945}
2946
2947int
2949 return (impl_->leaseGetPageHandler(handle));
2950}
2951
2952int
2954 return (impl_->leaseGetByHwAddressHandler(handle));
2955}
2956
2957int
2959 return (impl_->leaseGetByClientIdHandler(handle));
2960}
2961
2962int
2964 return (impl_->leaseGetByDuidHandler(handle));
2965}
2966
2967int
2969 return (impl_->leaseGetByHostnameHandler(handle));
2970}
2971
2972int
2974 return (impl_->lease4DelHandler(handle));
2975}
2976
2977int
2979 return (impl_->lease6DelHandler(handle));
2980}
2981
2982int
2984 return (impl_->lease4UpdateHandler(handle));
2985}
2986
2987int
2989 return (impl_->lease6UpdateHandler(handle));
2990}
2991
2992int
2995 return (impl_->lease4WipeHandler(handle));
2996}
2997
2998int
3001 return (impl_->lease6WipeHandler(handle));
3002}
3003
3004int
3006 return (impl_->lease4ResendDdnsHandler(handle));
3007}
3008
3009int
3011 return (impl_->lease6ResendDdnsHandler(handle));
3012}
3013
3014int
3016 return (impl_->leaseWriteHandler(handle));
3017}
3018
3020}
3021
3022
3023void
3026 impl_->lease4Offer(callout_handle, mgr);
3027}
3028
3029void
3032 impl_->leases4Committed(callout_handle, mgr);
3033}
3034
3035void
3038 impl_->leases6Committed(callout_handle, mgr);
3039}
3040
3041} // end of namespace lease_cmds
3042} // end of namespace isc
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
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:28
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:115
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 DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition duid.cc:50
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_WIPE4_DEPRECATED
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_WIPE6_DEPRECATED
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