Kea 3.1.1
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>
31#include <util/filesystem.h>
33
34#include <boost/scoped_ptr.hpp>
35#include <boost/algorithm/string.hpp>
36#include <string>
37#include <sstream>
38
39using namespace isc::dhcp;
40using namespace isc::data;
41using namespace isc::dhcp_ddns;
42using namespace isc::config;
43using namespace isc::asiolink;
44using namespace isc::hooks;
45using namespace isc::stats;
46using namespace isc::util;
47using namespace isc::util::file;
48using namespace isc::log;
49using namespace std;
50
51namespace isc {
52namespace lease_cmds {
53
55class LeaseCmdsImpl : private CmdsImpl {
56public:
57
59 class Parameters {
60 public:
61
69
72
75
78
81
84
94 static Type txtToType(const std::string& txt) {
95 if (txt == "address") {
96 return (Parameters::TYPE_ADDR);
97 } else if (txt == "hw-address") {
99 } else if (txt == "duid") {
100 return (Parameters::TYPE_DUID);
101 } else if (txt == "client-id") {
103 } else {
104 isc_throw(BadValue, "Incorrect identifier type: "
105 << txt << ", the only supported values are: "
106 "address, hw-address, duid");
107 }
108 }
109
112
115
117 uint32_t iaid;
118
121
124 : subnet_id(0), addr("::"), query_type(TYPE_ADDR),
125 lease_type(Lease::TYPE_NA), iaid(0), updateDDNS(false) {
126 }
127 };
128
129public:
130
139 int
141
151 int
153
162 int
164
176 int
178
194 int
196
206 int
208
218 int
220
230 int
232
243 int
245
254 int
256
265 int
267
276 int
278
287 int
289
298 int
300
309 int
311
321
331
340 int
342
354 Parameters getParameters(bool v6, const ConstElementPtr& args);
355
373 Lease6Ptr getIPv6LeaseForDelete(const Parameters& parameters) const;
374
390 const IOAddress& lease_address,
391 const DuidPtr& duid,
392 const int control_result,
393 const std::string& error_message) const;
394
405 IOAddress getAddressParam(ConstElementPtr params, const std::string name,
406 short family = AF_INET) const;
407
411 static void updateStatsOnAdd(const Lease4Ptr& lease);
412
416 static void updateStatsOnAdd(const Lease6Ptr& lease);
417
422 static void updateStatsOnUpdate(const Lease4Ptr& existing,
423 const Lease4Ptr& lease);
424
429 static void updateStatsOnUpdate(const Lease6Ptr& existing,
430 const Lease6Ptr& lease);
431
435 static void updateStatsOnDelete(const Lease4Ptr& lease);
436
440 static void updateStatsOnDelete(const Lease6Ptr& lease);
441
450 static bool addOrUpdate4(Lease4Ptr lease, bool force_create);
451
460 static bool addOrUpdate6(Lease6Ptr lease, bool force_create);
461
466 inline static ConstElementPtr getExtendedInfo6(const Lease6Ptr& lease) {
467 ConstElementPtr user_context = lease->getContext();
468 if (!user_context || (user_context->getType() != Element::map)) {
469 return (ConstElementPtr());
470 }
471 ConstElementPtr isc = user_context->get("ISC");
472 if (!isc || (isc->getType() != Element::map)) {
473 return (ConstElementPtr());
474 }
475 return (isc->get("relay-info"));
476 }
477
491 static void lease4Offer(CalloutHandle& callout_handle,
493
505 static void leases4Committed(CalloutHandle& callout_handle,
507
519 static void leases6Committed(CalloutHandle& callout_handle,
521};
522
523void
525 if (!lease->stateExpiredReclaimed()) {
527 StatsMgr::generateName("subnet", lease->subnet_id_,
528 "assigned-addresses"),
529 static_cast<int64_t>(1));
530
531 PoolPtr pool;
532 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
533 if (subnet) {
534 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
535 if (pool) {
537 StatsMgr::generateName("subnet", subnet->getID(),
538 StatsMgr::generateName("pool", pool->getID(),
539 "assigned-addresses")),
540 static_cast<int64_t>(1));
541 }
542 }
543
544 if (lease->stateDeclined()) {
545 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
546
548 StatsMgr::generateName("subnet", lease->subnet_id_,
549 "declined-addresses"),
550 static_cast<int64_t>(1));
551
552 if (pool) {
554 StatsMgr::generateName("subnet", subnet->getID(),
555 StatsMgr::generateName("pool", pool->getID(),
556 "declined-addresses")),
557 static_cast<int64_t>(1));
558 }
559 }
560 }
561}
562
563void
565 if (lease->stateRegistered()) {
567 StatsMgr::generateName("subnet", lease->subnet_id_, "registered-nas"),
568 static_cast<int64_t>(1));
569 } else if (!lease->stateExpiredReclaimed()) {
571 StatsMgr::generateName("subnet", lease->subnet_id_,
572 lease->type_ == Lease::TYPE_NA ?
573 "assigned-nas" : "assigned-pds"),
574 static_cast<int64_t>(1));
575
576 PoolPtr pool;
577 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
578 if (subnet) {
579 pool = subnet->getPool(lease->type_, lease->addr_, false);
580 if (pool) {
582 StatsMgr::generateName("subnet", subnet->getID(),
583 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
584 "pool" : "pd-pool", pool->getID(),
585 lease->type_ == Lease::TYPE_NA ?
586 "assigned-nas" : "assigned-pds")),
587 static_cast<int64_t>(1));
588 }
589 }
590
591 if (lease->stateDeclined()) {
592 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
593
595 StatsMgr::generateName("subnet", lease->subnet_id_,
596 "declined-addresses"),
597 static_cast<int64_t>(1));
598
599 if (pool) {
601 StatsMgr::generateName("subnet", subnet->getID(),
602 StatsMgr::generateName("pool", pool->getID(),
603 "declined-addresses")),
604 static_cast<int64_t>(1));
605 }
606 }
607 }
608}
609
610void
612 const Lease4Ptr& lease) {
613 if (!existing->stateExpiredReclaimed()) {
614 ConstSubnet4Ptr subnet;
615 PoolPtr pool;
616
617 // old lease is non expired-reclaimed
618 if (existing->subnet_id_ != lease->subnet_id_) {
620 StatsMgr::generateName("subnet", existing->subnet_id_,
621 "assigned-addresses"),
622 static_cast<int64_t>(-1));
623
624 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(existing->subnet_id_);
625 if (subnet) {
626 pool = subnet->getPool(Lease::TYPE_V4, existing->addr_, false);
627 if (pool) {
629 StatsMgr::generateName("subnet", subnet->getID(),
630 StatsMgr::generateName("pool", pool->getID(),
631 "assigned-addresses")),
632 static_cast<int64_t>(-1));
633 }
634 }
635 }
636
637 if (existing->stateDeclined()) {
638 // old lease is declined
639 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
640
642 StatsMgr::generateName("subnet", existing->subnet_id_,
643 "declined-addresses"),
644 static_cast<int64_t>(-1));
645
646 if (pool) {
648 StatsMgr::generateName("subnet", subnet->getID(),
649 StatsMgr::generateName("pool", pool->getID(),
650 "declined-addresses")),
651 static_cast<int64_t>(-1));
652 }
653 }
654
655 pool.reset();
656
657 if (!lease->stateExpiredReclaimed()) {
658 // new lease is non expired-reclaimed
659 if (existing->subnet_id_ != lease->subnet_id_) {
661 StatsMgr::generateName("subnet", lease->subnet_id_,
662 "assigned-addresses"),
663 static_cast<int64_t>(1));
664
665 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
666 if (subnet) {
667 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
668 if (pool) {
670 StatsMgr::generateName("subnet", subnet->getID(),
671 StatsMgr::generateName("pool", pool->getID(),
672 "assigned-addresses")),
673 static_cast<int64_t>(1));
674 }
675 }
676 }
677
678 if (lease->stateDeclined()) {
679 // new lease is declined
680 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
681
683 StatsMgr::generateName("subnet", lease->subnet_id_,
684 "declined-addresses"),
685 static_cast<int64_t>(1));
686
687 if (pool) {
689 StatsMgr::generateName("subnet", subnet->getID(),
690 StatsMgr::generateName("pool", pool->getID(),
691 "declined-addresses")),
692 static_cast<int64_t>(1));
693 }
694 }
695 }
696 } else {
697 // old lease is expired-reclaimed
698 if (!lease->stateExpiredReclaimed()) {
699 // new lease is non expired-reclaimed
701 StatsMgr::generateName("subnet", lease->subnet_id_,
702 "assigned-addresses"),
703 static_cast<int64_t>(1));
704
705 PoolPtr pool;
706 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
707 if (subnet) {
708 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
709 if (pool) {
711 StatsMgr::generateName("subnet", subnet->getID(),
712 StatsMgr::generateName("pool", pool->getID(),
713 "assigned-addresses")),
714 static_cast<int64_t>(1));
715 }
716 }
717
718 if (lease->stateDeclined()) {
719 // new lease is declined
720 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
721
723 StatsMgr::generateName("subnet", lease->subnet_id_,
724 "declined-addresses"),
725 static_cast<int64_t>(1));
726
727 if (pool) {
729 StatsMgr::generateName("subnet", subnet->getID(),
730 StatsMgr::generateName("pool", pool->getID(),
731 "declined-addresses")),
732 static_cast<int64_t>(1));
733 }
734 }
735 }
736 }
737}
738
739void
741 const Lease6Ptr& lease) {
742 // Does not cover registered <-> not registered transition.
743 if (existing->stateRegistered()) {
744 if (existing->subnet_id_ != lease->subnet_id_) {
746 StatsMgr::generateName("subnet", existing->subnet_id_,
747 "registered-nas"),
748 static_cast<int64_t>(-1));
750 StatsMgr::generateName("subnet", lease->subnet_id_,
751 "registered-nas"),
752 static_cast<int64_t>(1));
753 }
754 } else if (!existing->stateExpiredReclaimed()) {
755 ConstSubnet6Ptr subnet;
756 PoolPtr pool;
757
758 // old lease is non expired-reclaimed
759 if (existing->subnet_id_ != lease->subnet_id_) {
761 StatsMgr::generateName("subnet", existing->subnet_id_,
762 lease->type_ == Lease::TYPE_NA ?
763 "assigned-nas" : "assigned-pds"),
764 static_cast<int64_t>(-1));
765
766 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(existing->subnet_id_);
767 if (subnet) {
768 pool = subnet->getPool(existing->type_, existing->addr_, false);
769 if (pool) {
771 StatsMgr::generateName("subnet", subnet->getID(),
772 StatsMgr::generateName(existing->type_ == Lease::TYPE_NA ?
773 "pool" : "pd-pool", pool->getID(),
774 existing->type_ == Lease::TYPE_NA ?
775 "assigned-nas" : "assigned-pds")),
776 static_cast<int64_t>(-1));
777 }
778 }
779 }
780
781 if (existing->stateDeclined()) {
782 // old lease is declined
783 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
784
786 StatsMgr::generateName("subnet", existing->subnet_id_,
787 "declined-addresses"),
788 static_cast<int64_t>(-1));
789
790 if (pool) {
792 StatsMgr::generateName("subnet", subnet->getID(),
793 StatsMgr::generateName("pool", pool->getID(),
794 "declined-addresses")),
795 static_cast<int64_t>(-1));
796 }
797 }
798
799 pool.reset();
800
801 if (!lease->stateExpiredReclaimed()) {
802 // new lease is non expired-reclaimed
803 if (existing->subnet_id_ != lease->subnet_id_) {
805 StatsMgr::generateName("subnet", lease->subnet_id_,
806 lease->type_ == Lease::TYPE_NA ?
807 "assigned-nas" : "assigned-pds"),
808 static_cast<int64_t>(1));
809
810 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
811 if (subnet) {
812 pool = subnet->getPool(lease->type_, lease->addr_, false);
813 if (pool) {
815 StatsMgr::generateName("subnet", subnet->getID(),
816 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
817 "pool" : "pd-pool", pool->getID(),
818 lease->type_ == Lease::TYPE_NA ?
819 "assigned-nas" : "assigned-pds")),
820 static_cast<int64_t>(1));
821 }
822 }
823 }
824
825 if (lease->stateDeclined()) {
826 // new lease is declined
827 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
828
830 StatsMgr::generateName("subnet", lease->subnet_id_,
831 "declined-addresses"),
832 static_cast<int64_t>(1));
833
834 if (pool) {
836 StatsMgr::generateName("subnet", subnet->getID(),
837 StatsMgr::generateName("pool", pool->getID(),
838 "declined-addresses")),
839 static_cast<int64_t>(1));
840 }
841 }
842 }
843 } else {
844 // old lease is expired-reclaimed
845 if (!lease->stateExpiredReclaimed()) {
846 // new lease is non expired-reclaimed
848 StatsMgr::generateName("subnet", lease->subnet_id_,
849 lease->type_ == Lease::TYPE_NA ?
850 "assigned-nas" : "assigned-pds"),
851 static_cast<int64_t>(1));
852
853 PoolPtr pool;
854 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
855 if (subnet) {
856 pool = subnet->getPool(lease->type_, lease->addr_, false);
857 if (pool) {
859 StatsMgr::generateName("subnet", subnet->getID(),
860 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
861 "pool" : "pd-pool", pool->getID(),
862 lease->type_ == Lease::TYPE_NA ?
863 "assigned-nas" : "assigned-pds")),
864 static_cast<int64_t>(1));
865 }
866 }
867
868 if (lease->stateDeclined()) {
869 // new lease is declined
870 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
871
873 StatsMgr::generateName("subnet", lease->subnet_id_,
874 "declined-addresses"),
875 static_cast<int64_t>(1));
876
877 if (pool) {
879 StatsMgr::generateName("subnet", subnet->getID(),
880 StatsMgr::generateName("pool", pool->getID(),
881 "declined-addresses")),
882 static_cast<int64_t>(1));
883 }
884 }
885 }
886 }
887}
888
889void
891 if (!lease->stateExpiredReclaimed()) {
893 StatsMgr::generateName("subnet", lease->subnet_id_,
894 "assigned-addresses"),
895 static_cast<int64_t>(-1));
896
897 PoolPtr pool;
898 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
899 if (subnet) {
900 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
901 if (pool) {
903 StatsMgr::generateName("subnet", subnet->getID(),
904 StatsMgr::generateName("pool", pool->getID(),
905 "assigned-addresses")),
906 static_cast<int64_t>(-1));
907 }
908 }
909
910 if (lease->stateDeclined()) {
911 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
912
914 StatsMgr::generateName("subnet", lease->subnet_id_,
915 "declined-addresses"),
916 static_cast<int64_t>(-1));
917
918 if (pool) {
920 StatsMgr::generateName("subnet", subnet->getID(),
921 StatsMgr::generateName("pool", pool->getID(),
922 "declined-addresses")),
923 static_cast<int64_t>(-1));
924 }
925 }
926 }
927}
928
929void
931 if (lease->stateRegistered()) {
933 StatsMgr::generateName("subnet", lease->subnet_id_,
934 "registered-nas"),
935 static_cast<int64_t>(-1));
936 } else if (!lease->stateExpiredReclaimed()) {
938 StatsMgr::generateName("subnet", lease->subnet_id_,
939 lease->type_ == Lease::TYPE_NA ?
940 "assigned-nas" : "assigned-pds"),
941 static_cast<int64_t>(-1));
942
943 PoolPtr pool;
944 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
945 if (subnet) {
946 pool = subnet->getPool(lease->type_, lease->addr_, false);
947 if (pool) {
949 StatsMgr::generateName("subnet", subnet->getID(),
950 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
951 "pool" : "pd-pool", pool->getID(),
952 lease->type_ == Lease::TYPE_NA ?
953 "assigned-nas" : "assigned-pds")),
954 static_cast<int64_t>(-1));
955 }
956 }
957
958 if (lease->stateDeclined()) {
959 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
960
962 StatsMgr::generateName("subnet", lease->subnet_id_,
963 "declined-addresses"),
964 static_cast<int64_t>(-1));
965
966 if (pool) {
968 StatsMgr::generateName("subnet", subnet->getID(),
969 StatsMgr::generateName("pool", pool->getID(),
970 "declined-addresses")),
971 static_cast<int64_t>(-1));
972 }
973 }
974 }
975}
976
977bool
978LeaseCmdsImpl::addOrUpdate4(Lease4Ptr lease, bool force_create) {
979 Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease->addr_);
980 if (force_create && !existing) {
981 // lease does not exist
982 if (!LeaseMgrFactory::instance().addLease(lease)) {
984 "lost race between calls to get and add");
985 }
987 return (true);
988 }
989 if (existing) {
990 // Update lease current expiration time with value received from the
991 // database. Some database backends reject operations on the lease if
992 // the current expiration time value does not match what is stored.
993 Lease::syncCurrentExpirationTime(*existing, *lease);
994 }
995 try {
997 } catch (const NoSuchLease&) {
998 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
999 << lease->addr_ << " either because the lease has been "
1000 "deleted or it has changed in the database, in both cases a "
1001 "retry might succeed");
1002 }
1003
1004 LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
1005 return (false);
1006}
1007
1008bool
1009LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) {
1010 Lease6Ptr existing =
1011 LeaseMgrFactory::instance().getLease6(lease->type_, lease->addr_);
1012 if (force_create && !existing) {
1013 // lease does not exist
1014 if (!LeaseMgrFactory::instance().addLease(lease)) {
1016 "lost race between calls to get and add");
1017 }
1019 return (true);
1020 }
1021 if (existing) {
1022 // Refuse used <-> registered transitions.
1023 if (existing->stateRegistered() && !lease->stateRegistered()) {
1024 isc_throw(BadValue, "illegal reuse of registered address "
1025 << lease->addr_);
1026 } else if (!existing->stateRegistered() && lease->stateRegistered()) {
1027 isc_throw(BadValue, "address in use: " << lease->addr_
1028 << " can't be registered");
1029 }
1030
1031 // Update lease current expiration time with value received from the
1032 // database. Some database backends reject operations on the lease if
1033 // the current expiration time value does not match what is stored.
1034 Lease::syncCurrentExpirationTime(*existing, *lease);
1035
1036 // Check what is the action about extended info.
1037 ConstElementPtr old_extended_info = getExtendedInfo6(existing);
1038 ConstElementPtr extended_info = getExtendedInfo6(lease);
1039 if ((!old_extended_info && !extended_info) ||
1040 (old_extended_info && extended_info &&
1041 (*old_extended_info == *extended_info))) {
1042 // Leave the default Lease6::ACTION_IGNORE.
1043 } else {
1044 lease->extended_info_action_ = Lease6::ACTION_UPDATE;
1045 }
1046 }
1047 try {
1049 } catch (const NoSuchLease&) {
1050 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
1051 << lease->addr_ << " either because the lease has been "
1052 "deleted or it has changed in the database, in both cases a "
1053 "retry might succeed");
1054 }
1055
1056 LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
1057 return (false);
1058}
1059
1060int
1062 // Arbitrary defaulting to DHCPv4 or with other words extractCommand
1063 // below is not expected to throw...
1064 bool v4 = true;
1065 stringstream resp;
1066 string lease_address = "unknown";
1067 try {
1068 extractCommand(handle);
1069 v4 = (cmd_name_ == "lease4-add");
1070 if (!cmd_args_) {
1071 isc_throw(isc::BadValue, "no parameters specified for the command");
1072 }
1073
1075
1076 // This parameter is ignored for the commands adding the lease.
1077 bool force_create = false;
1078 Lease4Ptr lease4;
1079 Lease6Ptr lease6;
1080 if (v4) {
1081 Lease4Parser parser;
1082 lease4 = parser.parse(config, cmd_args_, force_create);
1083 if (lease4) {
1084 lease_address = lease4->addr_.toText();
1085 bool success;
1086 if (!MultiThreadingMgr::instance().getMode()) {
1087 // Not multi-threading.
1088 success = LeaseMgrFactory::instance().addLease(lease4);
1089 } else {
1090 // Multi-threading, try to lock first to avoid a race.
1091 ResourceHandler4 resource_handler;
1092 if (resource_handler.tryLock4(lease4->addr_)) {
1093 success = LeaseMgrFactory::instance().addLease(lease4);
1094 } else {
1096 "ResourceBusy: IP address:" << lease4->addr_
1097 << " could not be added.");
1098 }
1099 }
1100
1101 if (!success) {
1102 isc_throw(LeaseCmdsConflict, "IPv4 lease already exists.");
1103 }
1104
1106 resp << "Lease for address " << lease4->addr_.toText()
1107 << ", subnet-id " << lease4->subnet_id_ << " added.";
1108 }
1109 } else {
1110 Lease6Parser parser;
1111 lease6 = parser.parse(config, cmd_args_, force_create);
1112 if (lease6) {
1113 lease_address = lease6->addr_.toText();
1114 bool success;
1115 if (!MultiThreadingMgr::instance().getMode()) {
1116 // Not multi-threading.
1117 success = LeaseMgrFactory::instance().addLease(lease6);
1118 } else {
1119 // Multi-threading, try to lock first to avoid a race.
1120 ResourceHandler resource_handler;
1121 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
1122 success = LeaseMgrFactory::instance().addLease(lease6);
1123 } else {
1125 "ResourceBusy: IP address:" << lease6->addr_
1126 << " could not be added.");
1127 }
1128 }
1129
1130 if (!success) {
1131 isc_throw(LeaseCmdsConflict, "IPv6 lease already exists.");
1132 }
1133
1135 if (lease6->type_ == Lease::TYPE_NA) {
1136 resp << "Lease for address " << lease6->addr_.toText()
1137 << ", subnet-id " << lease6->subnet_id_ << " added.";
1138 } else {
1139 resp << "Lease for prefix " << lease6->addr_.toText()
1140 << "/" << static_cast<int>(lease6->prefixlen_)
1141 << ", subnet-id " << lease6->subnet_id_ << " added.";
1142 }
1143 }
1144 }
1145 } catch (const LeaseCmdsConflict& ex) {
1147 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1148 .arg(ex.what());
1150 return (0);
1151
1152 } catch (const std::exception& ex) {
1154 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1155 .arg(ex.what());
1156 setErrorResponse(handle, ex.what());
1157 return (1);
1158 }
1159
1162 .arg(lease_address);
1163 setSuccessResponse(handle, resp.str());
1164 return (0);
1165}
1166
1169 Parameters x;
1170
1171 if (!params || params->getType() != Element::map) {
1172 isc_throw(BadValue, "Parameters missing or are not a map.");
1173 }
1174
1175 if (params->contains("update-ddns")) {
1176 ConstElementPtr tmp = params->get("update-ddns");
1177 if (tmp->getType() != Element::boolean) {
1178 isc_throw(BadValue, "'update-ddns' is not a boolean");
1179 } else {
1180 x.updateDDNS = tmp->boolValue();
1181 }
1182 }
1183
1184 // We support several sets of parameters for leaseX-get/lease-del:
1185 // lease-get(type, address)
1186 // lease-get(type, subnet-id, identifier-type, identifier)
1187
1188 if (params->contains("type")) {
1189 string t = params->get("type")->stringValue();
1190 if (t == "IA_NA" || t == "0") {
1192 } else if (t == "IA_TA" || t == "1") {
1194 } else if (t == "IA_PD" || t == "2") {
1196 } else if (t == "V4" || t == "3") {
1198 } else {
1199 isc_throw(BadValue, "Invalid lease type specified: "
1200 << t << ", only supported values are: IA_NA, IA_TA,"
1201 << " IA_PD and V4");
1202 }
1203 }
1204
1205 ConstElementPtr tmp = params->get("ip-address");
1206 if (tmp) {
1207 if (tmp->getType() != Element::string) {
1208 isc_throw(BadValue, "'ip-address' is not a string.");
1209 }
1210
1211 x.addr = IOAddress(tmp->stringValue());
1212
1213 if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
1214 stringstream txt;
1215 txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
1216 << " address specified: " << tmp->stringValue();
1217 isc_throw(BadValue, txt.str());
1218 }
1219
1221 return (x);
1222 }
1223
1224 tmp = params->get("subnet-id");
1225 if (!tmp) {
1226 isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
1227 }
1228 if (tmp->getType() != Element::integer) {
1229 isc_throw(BadValue, "'subnet-id' parameter is not integer.");
1230 }
1231 x.subnet_id = tmp->intValue();
1232
1233 if (params->contains("iaid")) {
1234 x.iaid = params->get("iaid")->intValue();
1235 }
1236
1237 // No address specified. Ok, so it must be identifier based query.
1238 // "identifier-type": "duid",
1239 // "identifier": "aa:bb:cc:dd:ee:..."
1240
1241 ConstElementPtr type = params->get("identifier-type");
1242 ConstElementPtr ident = params->get("identifier");
1243 if (!type || type->getType() != Element::string) {
1244 isc_throw(BadValue, "No 'ip-address' provided"
1245 " and 'identifier-type' is either missing or not a string.");
1246 }
1247 if (!ident || ident->getType() != Element::string) {
1248 isc_throw(BadValue, "No 'ip-address' provided"
1249 " and 'identifier' is either missing or not a string.");
1250 }
1251
1252 // Got the parameters. Let's see if their values make sense.
1253 // Try to convert identifier-type
1254 x.query_type = Parameters::txtToType(type->stringValue());
1255
1256 switch (x.query_type) {
1258 HWAddr hw = HWAddr::fromText(ident->stringValue());
1259 x.hwaddr = HWAddrPtr(new HWAddr(hw));
1260 break;
1261 }
1263 x.client_id = ClientId::fromText(ident->stringValue());
1264 break;
1265 }
1266 case Parameters::TYPE_DUID: {
1267 DUID duid = DUID::fromText(ident->stringValue());
1268 x.duid = DuidPtr(new DUID(duid));
1269 break;
1270 }
1271 case Parameters::TYPE_ADDR: {
1272 // We should never get here. The address clause should have been caught
1273 // earlier.
1274 return (x);
1275 }
1276 default: {
1277 isc_throw(BadValue, "Identifier type " << type->stringValue() <<
1278 " is not supported.");
1279 }
1280 }
1281
1282 return (x);
1283}
1284
1285int
1287 Parameters p;
1288 Lease4Ptr lease4;
1289 Lease6Ptr lease6;
1290 bool v4 = true;
1291 try {
1292 extractCommand(handle);
1293 v4 = (cmd_name_ == "lease4-get");
1294 p = getParameters(!v4, cmd_args_);
1295 switch (p.query_type) {
1296 case Parameters::TYPE_ADDR: {
1297 // Query by address
1298 if (v4) {
1300 } else {
1302 }
1303 break;
1304 }
1306 if (v4) {
1307 if (!p.hwaddr) {
1308 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1309 "requires hwaddr to be specified");
1310 }
1311
1313 } else {
1314 isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
1315 }
1316 break;
1317
1319 if (!v4) {
1320 if (!p.duid) {
1321 isc_throw(InvalidParameter, "Program error: Query by duid "
1322 "requires duid to be specified");
1323 }
1324
1326 p.iaid, p.subnet_id);
1327 } else {
1328 isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
1329 }
1330 break;
1331
1333 if (v4) {
1334 if (!p.client_id) {
1335 isc_throw(InvalidParameter, "Program error: Query by client-id "
1336 "requires client-id to be specified");
1337 }
1338
1340 } else {
1341 isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
1342 }
1343 break;
1344
1345 default: {
1346 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1347 break;
1348 }
1349 }
1350 } catch (const std::exception& ex) {
1352 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1353 .arg(ex.what());
1354 setErrorResponse(handle, ex.what());
1355 return (1);
1356 }
1357
1358 ElementPtr lease_json;
1359 if (v4 && lease4) {
1360 lease_json = lease4->toElement();
1362 "IPv4 lease found.", lease_json);
1363 setResponse(handle, response);
1364 } else if (!v4 && lease6) {
1365 lease_json = lease6->toElement();
1367 "IPv6 lease found.", lease_json);
1368 setResponse(handle, response);
1369 } else {
1370 // If we got here, the lease has not been found.
1371 setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
1372 }
1373
1374 return (0);
1375}
1376
1377int
1379 bool v4 = true;
1380 try {
1381 extractCommand(handle);
1382 v4 = (cmd_name_ == "lease4-get-all");
1383
1384 ElementPtr leases_json = Element::createList();
1385
1386 // The argument may contain a list of subnets for which leases should
1387 // be returned.
1388 if (cmd_args_) {
1389 ConstElementPtr subnets = cmd_args_->get("subnets");
1390 if (!subnets) {
1391 isc_throw(BadValue, "'subnets' parameter not specified");
1392 }
1393 if (subnets->getType() != Element::list) {
1394 isc_throw(BadValue, "'subnets' parameter must be a list");
1395 }
1396
1397 const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
1398 for (auto const& subnet_id : subnet_ids) {
1399 if (subnet_id->getType() != Element::integer) {
1400 isc_throw(BadValue, "listed subnet identifiers must be numbers");
1401 }
1402
1403 if (v4) {
1404 Lease4Collection leases =
1405 LeaseMgrFactory::instance().getLeases4(subnet_id->intValue());
1406 for (auto const& lease : leases) {
1407 ElementPtr lease_json = lease->toElement();
1408 leases_json->add(lease_json);
1409 }
1410 } else {
1411 Lease6Collection leases =
1412 LeaseMgrFactory::instance().getLeases6(subnet_id->intValue());
1413 for (auto const& lease : leases) {
1414 ElementPtr lease_json = lease->toElement();
1415 leases_json->add(lease_json);
1416 }
1417 }
1418 }
1419
1420 } else {
1421 // There is no 'subnets' argument so let's return all leases.
1422 if (v4) {
1424 for (auto const& lease : leases) {
1425 ElementPtr lease_json = lease->toElement();
1426 leases_json->add(lease_json);
1427 }
1428 } else {
1430 for (auto const& lease : leases) {
1431 ElementPtr lease_json = lease->toElement();
1432 leases_json->add(lease_json);
1433 }
1434 }
1435 }
1436
1437 std::ostringstream s;
1438 s << leases_json->size()
1439 << " IPv" << (v4 ? "4" : "6")
1440 << " lease(s) found.";
1442 args->set("leases", leases_json);
1443 ConstElementPtr response =
1444 createAnswer(leases_json->size() > 0 ?
1447 s.str(), args);
1448 setResponse(handle, response);
1449
1450 } catch (const std::exception& ex) {
1451 setErrorResponse(handle, ex.what());
1452 return (CONTROL_RESULT_ERROR);
1453 }
1454
1455 return (0);
1456}
1457
1458int
1460 bool v4 = true;
1461 try {
1462 extractCommand(handle);
1463 v4 = (cmd_name_ == "lease4-get-page");
1464
1465 // arguments must always be present
1466 if (!cmd_args_) {
1467 isc_throw(BadValue, "no parameters specified for the " << cmd_name_
1468 << " command");
1469 }
1470
1471 // The 'from' argument denotes from which lease we should start the
1472 // results page. The results page excludes this lease.
1473 ConstElementPtr from = cmd_args_->get("from");
1474 if (!from) {
1475 isc_throw(BadValue, "'from' parameter not specified");
1476 }
1477
1478 // The 'from' argument is a string. It may contain a 'start' keyword or
1479 // an IP address.
1480 if (from->getType() != Element::string) {
1481 isc_throw(BadValue, "'from' parameter must be a string");
1482 }
1483
1484 boost::scoped_ptr<IOAddress> from_address;
1485 try {
1486 if (from->stringValue() == "start") {
1487 from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1488
1489 } else {
1490 // Conversion of a string to an IP address may throw.
1491 from_address.reset(new IOAddress(from->stringValue()));
1492 }
1493
1494 } catch (...) {
1495 isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1496 "a valid IPv" << (v4 ? "4" : "6") << " address");
1497 }
1498
1499 // It must be either IPv4 address for lease4-get-page or IPv6 address for
1500 // lease6-get-page.
1501 if (v4 && (!from_address->isV4())) {
1502 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1503 << " is not an IPv4 address");
1504
1505 } else if (!v4 && from_address->isV4()) {
1506 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1507 << " is not an IPv6 address");
1508 }
1509
1510 // The 'limit' is a desired page size. It must always be present.
1511 ConstElementPtr page_limit = cmd_args_->get("limit");
1512 if (!page_limit) {
1513 isc_throw(BadValue, "'limit' parameter not specified");
1514 }
1515
1516 // The 'limit' must be a number.
1517 if (page_limit->getType() != Element::integer) {
1518 isc_throw(BadValue, "'limit' parameter must be a number");
1519 }
1520
1521 // Retrieve the desired page size.
1522 size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
1523
1524 ElementPtr leases_json = Element::createList();
1525
1526 if (v4) {
1527 // Get page of IPv4 leases.
1528 Lease4Collection leases =
1529 LeaseMgrFactory::instance().getLeases4(*from_address,
1530 LeasePageSize(page_limit_value));
1531
1532 // Convert leases into JSON list.
1533 for (auto const& lease : leases) {
1534 ElementPtr lease_json = lease->toElement();
1535 leases_json->add(lease_json);
1536 }
1537
1538 } else {
1539 // Get page of IPv6 leases.
1540 Lease6Collection leases =
1541 LeaseMgrFactory::instance().getLeases6(*from_address,
1542 LeasePageSize(page_limit_value));
1543 // Convert leases into JSON list.
1544 for (auto const& lease : leases) {
1545 ElementPtr lease_json = lease->toElement();
1546 leases_json->add(lease_json);
1547 }
1548 }
1549
1550 // Prepare textual status.
1551 std::ostringstream s;
1552 s << leases_json->size()
1553 << " IPv" << (v4 ? "4" : "6")
1554 << " lease(s) found.";
1556
1557 // Put gathered data into arguments map.
1558 args->set("leases", leases_json);
1559 args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1560
1561 // Create the response.
1562 ConstElementPtr response =
1563 createAnswer(leases_json->size() > 0 ?
1566 s.str(), args);
1567 setResponse(handle, response);
1568
1569 } catch (const std::exception& ex) {
1570 setErrorResponse(handle, ex.what());
1571 return (CONTROL_RESULT_ERROR);
1572 }
1573
1574 return (CONTROL_RESULT_SUCCESS);
1575}
1576
1577int
1579 bool v4 = true;
1580 try {
1581 extractCommand(handle);
1582 v4 = (cmd_name_ == "lease4-get-by-hw-address");
1583
1584 // arguments must always be present
1585 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1586 isc_throw(BadValue, "Command arguments missing or a not a map.");
1587 }
1588
1589 // the hw-address parameter is mandatory.
1590 ConstElementPtr hw_address = cmd_args_->get("hw-address");
1591 if (!hw_address) {
1592 isc_throw(BadValue, "'hw-address' parameter not specified");
1593 }
1594
1595 // The 'hw-address' argument is a string.
1596 if (hw_address->getType() != Element::string) {
1597 isc_throw(BadValue, "'hw-address' parameter must be a string");
1598 }
1599
1600 if (hw_address->stringValue().empty()) {
1601 isc_throw(BadValue, "'hw-address' parameter must not be empty");
1602 }
1603
1604 HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
1605
1606 ElementPtr leases_json = Element::createList();
1607
1608 if (v4) {
1609 Lease4Collection leases =
1611 for (auto const& lease : leases) {
1612 ElementPtr lease_json = lease->toElement();
1613 leases_json->add(lease_json);
1614 }
1615 } else {
1616 Lease6Collection leases =
1618 for (auto const& lease : leases) {
1619 ElementPtr lease_json = lease->toElement();
1620 leases_json->add(lease_json);
1621 }
1622 }
1623
1624 std::ostringstream s;
1625 s << leases_json->size()
1626 << " IPv" << (v4 ? "4" : "6")
1627 << " lease(s) found.";
1629 args->set("leases", leases_json);
1630 ConstElementPtr response =
1631 createAnswer(leases_json->size() > 0 ?
1634 s.str(), args);
1635 setResponse(handle, response);
1636
1637 } catch (const std::exception& ex) {
1638 setErrorResponse(handle, ex.what());
1639 return (CONTROL_RESULT_ERROR);
1640 }
1641
1642 return (0);
1643}
1644
1645int
1647 try {
1648 extractCommand(handle);
1649
1650 // arguments must always be present
1651 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1652 isc_throw(BadValue, "Command arguments missing or a not a map.");
1653 }
1654
1655 // the client-id parameter is mandatory.
1656 ConstElementPtr client_id = cmd_args_->get("client-id");
1657 if (!client_id) {
1658 isc_throw(BadValue, "'client-id' parameter not specified");
1659 }
1660
1661 // The 'client-id' argument is a string.
1662 if (client_id->getType() != Element::string) {
1663 isc_throw(BadValue, "'client-id' parameter must be a string");
1664 }
1665
1666 ClientIdPtr clientid = ClientId::fromText(client_id->stringValue());
1667
1668 Lease4Collection leases =
1670 ElementPtr leases_json = Element::createList();
1671 for (auto const& lease : leases) {
1672 ElementPtr lease_json = lease->toElement();
1673 leases_json->add(lease_json);
1674 }
1675
1676 std::ostringstream s;
1677 s << leases_json->size() << " IPv4 lease(s) found.";
1679 args->set("leases", leases_json);
1680 ConstElementPtr response =
1681 createAnswer(leases_json->size() > 0 ?
1684 s.str(), args);
1685 setResponse(handle, response);
1686
1687 } catch (const std::exception& ex) {
1688 setErrorResponse(handle, ex.what());
1689 return (CONTROL_RESULT_ERROR);
1690 }
1691
1692 return (0);
1693}
1694
1695int
1697 try {
1698 extractCommand(handle);
1699
1700 // arguments must always be present
1701 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1702 isc_throw(BadValue, "Command arguments missing or a not a map.");
1703 }
1704
1705 // the duid parameter is mandatory.
1706 ConstElementPtr duid = cmd_args_->get("duid");
1707 if (!duid) {
1708 isc_throw(BadValue, "'duid' parameter not specified");
1709 }
1710
1711 // The 'duid' argument is a string.
1712 if (duid->getType() != Element::string) {
1713 isc_throw(BadValue, "'duid' parameter must be a string");
1714 }
1715
1716 DUID duid_ = DUID::fromText(duid->stringValue());
1717
1718 Lease6Collection leases =
1720 ElementPtr leases_json = Element::createList();
1721 for (auto const& lease : leases) {
1722 ElementPtr lease_json = lease->toElement();
1723 leases_json->add(lease_json);
1724 }
1725
1726 std::ostringstream s;
1727 s << leases_json->size() << " IPv6 lease(s) found.";
1729 args->set("leases", leases_json);
1730 ConstElementPtr response =
1731 createAnswer(leases_json->size() > 0 ?
1734 s.str(), args);
1735 setResponse(handle, response);
1736
1737 } catch (const std::exception& ex) {
1738 setErrorResponse(handle, ex.what());
1739 return (CONTROL_RESULT_ERROR);
1740 }
1741
1742 return (0);
1743}
1744
1745int
1747 bool v4 = true;
1748 try {
1749 extractCommand(handle);
1750 v4 = (cmd_name_ == "lease4-get-by-hostname");
1751
1752 // arguments must always be present
1753 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1754 isc_throw(BadValue, "Command arguments missing or a not a map.");
1755 }
1756
1757 // the hostname parameter is mandatory.
1758 ConstElementPtr hostname = cmd_args_->get("hostname");
1759 if (!hostname) {
1760 isc_throw(BadValue, "'hostname' parameter not specified");
1761 }
1762
1763 // The 'hostname' argument is a string.
1764 if (hostname->getType() != Element::string) {
1765 isc_throw(BadValue, "'hostname' parameter must be a string");
1766 }
1767
1768 std::string hostname_ = hostname->stringValue();
1770 if (hostname_.empty()) {
1771 isc_throw(BadValue, "'hostname' parameter is empty");
1772 }
1773 boost::algorithm::to_lower(hostname_);
1774
1775 ElementPtr leases_json = Element::createList();
1776 if (v4) {
1777 Lease4Collection leases =
1779
1780 for (auto const& lease : leases) {
1781 ElementPtr lease_json = lease->toElement();
1782 leases_json->add(lease_json);
1783 }
1784 } else {
1785 Lease6Collection leases =
1787
1788 for (auto const& lease : leases) {
1789 ElementPtr lease_json = lease->toElement();
1790 leases_json->add(lease_json);
1791 }
1792 }
1793
1794 std::ostringstream s;
1795 s << leases_json->size()
1796 << " IPv" << (v4 ? "4" : "6")
1797 << " lease(s) found.";
1799 args->set("leases", leases_json);
1800 ConstElementPtr response =
1801 createAnswer(leases_json->size() > 0 ?
1804 s.str(), args);
1805 setResponse(handle, response);
1806
1807 } catch (const std::exception& ex) {
1808 setErrorResponse(handle, ex.what());
1809 return (CONTROL_RESULT_ERROR);
1810 }
1811
1812 return (0);
1813}
1814
1815int
1817 Parameters p;
1818 Lease4Ptr lease4;
1819 try {
1820 extractCommand(handle);
1821 p = getParameters(false, cmd_args_);
1822 switch (p.query_type) {
1823 case Parameters::TYPE_ADDR: {
1824 // If address was specified explicitly, let's use it as is.
1826 if (!lease4) {
1827 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1828 return (0);
1829 }
1830 break;
1831 }
1833 if (!p.hwaddr) {
1834 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1835 "requires hwaddr to be specified");
1836 }
1837
1838 // Let's see if there's such a lease at all.
1840 if (!lease4) {
1841 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1842 return (0);
1843 }
1844 break;
1845 }
1847 if (!p.client_id) {
1848 isc_throw(InvalidParameter, "Program error: Query by client-id "
1849 "requires client-id to be specified");
1850 }
1851
1852 // Let's see if there's such a lease at all.
1854 if (!lease4) {
1855 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1856 return (0);
1857 }
1858 break;
1859 }
1860 case Parameters::TYPE_DUID: {
1861 isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
1862 break;
1863 }
1864 default: {
1865 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1866 break;
1867 }
1868 }
1869
1870 if (LeaseMgrFactory::instance().deleteLease(lease4)) {
1871 setSuccessResponse(handle, "IPv4 lease deleted.");
1873 } else {
1874 setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1875 }
1876
1877 // Queue an NCR to remove DNS if configured and the lease has it.
1878 if (p.updateDDNS) {
1879 queueNCR(CHG_REMOVE, lease4);
1880 }
1881
1882 } catch (const std::exception& ex) {
1884 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1885 .arg(ex.what());
1886 setErrorResponse(handle, ex.what());
1887 return (1);
1888 }
1890 .arg(lease4->addr_.toText());
1891 return (0);
1892}
1893
1894int
1896 try {
1897 extractCommand(handle);
1898
1899 // Arguments are mandatory.
1900 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1901 isc_throw(BadValue, "Command arguments missing or a not a map.");
1902 }
1903
1904 // At least one of the 'deleted-leases' or 'leases' must be present.
1905 auto deleted_leases = cmd_args_->get("deleted-leases");
1906 auto leases = cmd_args_->get("leases");
1907
1908 if (!deleted_leases && !leases) {
1909 isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1910 " specified");
1911 }
1912
1913 // Make sure that 'deleted-leases' is a list, if present.
1914 if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1915 isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1916 }
1917
1918 // Make sure that 'leases' is a list, if present.
1919 if (leases && (leases->getType() != Element::list)) {
1920 isc_throw(BadValue, "the 'leases' parameter must be a list");
1921 }
1922
1923 // Parse deleted leases without deleting them from the database
1924 // yet. If any of the deleted leases or new leases appears to be
1925 // malformed we can easily rollback.
1926 std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1927 if (deleted_leases) {
1928 auto leases_list = deleted_leases->listValue();
1929
1930 // Iterate over leases to be deleted.
1931 for (auto const& lease_params : leases_list) {
1932 // Parsing the lease may throw and it means that the lease
1933 // information is malformed.
1934 Parameters p = getParameters(true, lease_params);
1935 auto lease = getIPv6LeaseForDelete(p);
1936 parsed_deleted_list.push_back(std::make_pair(p, lease));
1937 }
1938 }
1939
1940 // Parse new/updated leases without affecting the database to detect
1941 // any errors that should cause an error response.
1942 std::list<Lease6Ptr> parsed_leases_list;
1943 if (leases) {
1945
1946 // Iterate over all leases.
1947 auto leases_list = leases->listValue();
1948 for (auto const& lease_params : leases_list) {
1949
1950 Lease6Parser parser;
1951 bool force_update;
1952
1953 // If parsing the lease fails we throw, as it indicates that the
1954 // command is malformed.
1955 Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1956 parsed_leases_list.push_back(lease6);
1957 }
1958 }
1959
1960 // Count successful deletions and updates.
1961 size_t success_count = 0;
1962
1963 ElementPtr failed_deleted_list;
1964 if (!parsed_deleted_list.empty()) {
1965
1966 // Iterate over leases to be deleted.
1967 for (auto const& lease_params_pair : parsed_deleted_list) {
1968
1969 // This part is outside of the try-catch because an exception
1970 // indicates that the command is malformed.
1971 Parameters p = lease_params_pair.first;
1972 auto lease = lease_params_pair.second;
1973
1974 try {
1975 if (lease) {
1976 // This may throw if the lease couldn't be deleted for
1977 // any reason, but we still want to proceed with other
1978 // leases.
1979 if (LeaseMgrFactory::instance().deleteLease(lease)) {
1980 ++success_count;
1982
1983 } else {
1984 // Lazy creation of the list of leases which failed to delete.
1985 if (!failed_deleted_list) {
1986 failed_deleted_list = Element::createList();
1987 }
1988
1989 // If the lease doesn't exist we also want to put it
1990 // on the list of leases which failed to delete. That
1991 // corresponds to the lease6-del command which returns
1992 // an error when the lease doesn't exist.
1993 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1994 p.addr, p.duid,
1996 "lease not found"));
1997 }
1998 }
1999
2000 } catch (const std::exception& ex) {
2001 // Lazy creation of the list of leases which failed to delete.
2002 if (!failed_deleted_list) {
2003 failed_deleted_list = Element::createList();
2004 }
2005 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
2006 p.addr, p.duid,
2008 ex.what()));
2009 }
2010 }
2011 }
2012
2013 // Process leases to be added or/and updated.
2014 ElementPtr failed_leases_list;
2015 if (!parsed_leases_list.empty()) {
2017
2018 // Iterate over all leases.
2019 for (auto const& lease : parsed_leases_list) {
2020
2021 auto result = CONTROL_RESULT_SUCCESS;
2022 std::ostringstream text;
2023 try {
2024 if (!MultiThreadingMgr::instance().getMode()) {
2025 // Not multi-threading.
2026 addOrUpdate6(lease, true);
2027 } else {
2028 // Multi-threading, try to lock first to avoid a race.
2029 ResourceHandler resource_handler;
2030 if (resource_handler.tryLock(lease->type_, lease->addr_)) {
2031 addOrUpdate6(lease, true);
2032 } else {
2034 "ResourceBusy: IP address:" << lease->addr_
2035 << " could not be updated.");
2036 }
2037 }
2038
2039 ++success_count;
2040 } catch (const LeaseCmdsConflict& ex) {
2041 result = CONTROL_RESULT_CONFLICT;
2042 text << ex.what();
2043
2044 } catch (const std::exception& ex) {
2045 result = CONTROL_RESULT_ERROR;
2046 text << ex.what();
2047 }
2048 // Handle an error.
2049 if (result != CONTROL_RESULT_SUCCESS) {
2050 // Lazy creation of the list of leases which failed to add/update.
2051 if (!failed_leases_list) {
2052 failed_leases_list = Element::createList();
2053 }
2054 failed_leases_list->add(createFailedLeaseMap(lease->type_,
2055 lease->addr_,
2056 lease->duid_,
2057 result,
2058 text.str()));
2059 }
2060 }
2061 }
2062
2063 // Start preparing the response.
2064 ElementPtr args;
2065
2066 if (failed_deleted_list || failed_leases_list) {
2067 // If there are any failed leases, let's include them in the response.
2068 args = Element::createMap();
2069
2070 // failed-deleted-leases
2071 if (failed_deleted_list) {
2072 args->set("failed-deleted-leases", failed_deleted_list);
2073 }
2074
2075 // failed-leases
2076 if (failed_leases_list) {
2077 args->set("failed-leases", failed_leases_list);
2078 }
2079 }
2080
2081 // Send the success response and include failed leases.
2082 std::ostringstream resp_text;
2083 resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
2084 auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
2085 CONTROL_RESULT_EMPTY, resp_text.str(), args);
2086 setResponse(handle, answer);
2087
2090 .arg(success_count);
2091
2092 } catch (const std::exception& ex) {
2093 // Unable to parse the command and similar issues.
2095 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2096 .arg(ex.what());
2097 setErrorResponse(handle, ex.what());
2098 return (CONTROL_RESULT_ERROR);
2099 }
2100
2101 return (0);
2102}
2103
2104int
2106 Parameters p;
2107 Lease6Ptr lease6;
2109 try {
2110 extractCommand(handle);
2111 p = getParameters(true, cmd_args_);
2112
2113 switch (p.query_type) {
2114 case Parameters::TYPE_ADDR: {
2115 // If address was specified explicitly, let's use it as is.
2116
2117 // Let's see if there's such a lease at all.
2119 if (!lease6) {
2120 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2121 return (0);
2122 }
2123 break;
2124 }
2126 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2127 break;
2128 }
2129 case Parameters::TYPE_DUID: {
2130 if (!p.duid) {
2131 isc_throw(InvalidParameter, "Program error: Query by duid "
2132 "requires duid to be specified");
2133 }
2134
2135 // Let's see if there's such a lease at all.
2137 p.iaid, p.subnet_id);
2138 if (!lease6) {
2139 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2140 return (0);
2141 }
2142 break;
2143 }
2144 default: {
2145 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
2146 break;
2147 }
2148 }
2149
2150 if (LeaseMgrFactory::instance().deleteLease(lease6)) {
2151 setSuccessResponse(handle, "IPv6 lease deleted.");
2153 } else {
2154 setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2155 }
2156
2157 // Queue an NCR to remove DNS if configured and the lease has it.
2158 if (p.updateDDNS) {
2159 queueNCR(CHG_REMOVE, lease6);
2160 }
2161
2162 } catch (const std::exception& ex) {
2164 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2165 .arg(ex.what());
2166 setErrorResponse(handle, ex.what());
2167 return (1);
2168 }
2169
2171 .arg(lease6->addr_.toText());
2172 return (0);
2173}
2174
2175int
2177 try {
2178 extractCommand(handle);
2179
2180 // We need the lease to be specified.
2181 if (!cmd_args_) {
2182 isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
2183 }
2184
2185 // Get the parameters specified by the user first.
2187 Lease4Ptr lease4;
2188 Lease4Parser parser;
2189 bool force_create = false;
2190
2191 // The parser does sanity checks (if the address is in scope, if
2192 // subnet-id is valid, etc)
2193 lease4 = parser.parse(config, cmd_args_, force_create);
2194 bool added = false;
2195 if (!MultiThreadingMgr::instance().getMode()) {
2196 // Not multi-threading.
2197 added = addOrUpdate4(lease4, force_create);
2198 } else {
2199 // Multi-threading, try to lock first to avoid a race.
2200 ResourceHandler4 resource_handler;
2201 if (resource_handler.tryLock4(lease4->addr_)) {
2202 added = addOrUpdate4(lease4, force_create);
2203 } else {
2205 "ResourceBusy: IP address:" << lease4->addr_
2206 << " could not be updated.");
2207 }
2208 }
2209
2210 if (added) {
2211 setSuccessResponse(handle, "IPv4 lease added.");
2212 } else {
2213 setSuccessResponse(handle, "IPv4 lease updated.");
2214 }
2217 .arg(lease4->addr_.toText());
2218
2219 } catch (const LeaseCmdsConflict& ex) {
2221 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2222 .arg(ex.what());
2224 return (0);
2225
2226 } catch (const std::exception& ex) {
2228 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2229 .arg(ex.what());
2230 setErrorResponse(handle, ex.what());
2231 return (1);
2232 }
2233
2234 return (0);
2235}
2236
2237int
2239 try {
2240 extractCommand(handle);
2241
2242 // We need the lease to be specified.
2243 if (!cmd_args_) {
2244 isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
2245 }
2246
2247 // Get the parameters specified by the user first.
2249 Lease6Ptr lease6;
2250 Lease6Parser parser;
2251 bool force_create = false;
2252
2253 // The parser does sanity checks (if the address is in scope, if
2254 // subnet-id is valid, etc)
2255 lease6 = parser.parse(config, cmd_args_, force_create);
2256 bool added = false;
2257 if (!MultiThreadingMgr::instance().getMode()) {
2258 // Not multi-threading.
2259 added = addOrUpdate6(lease6, force_create);
2260 } else {
2261 // Multi-threading, try to lock first to avoid a race.
2262 ResourceHandler resource_handler;
2263 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
2264 added = addOrUpdate6(lease6, force_create);
2265 } else {
2267 "ResourceBusy: IP address:" << lease6->addr_
2268 << " could not be updated.");
2269 }
2270 }
2271
2272 if (added) {
2273 setSuccessResponse(handle, "IPv6 lease added.");
2274 } else {
2275 setSuccessResponse(handle, "IPv6 lease updated.");
2276 }
2279 .arg(lease6->addr_.toText());
2280
2281 } catch (const LeaseCmdsConflict& ex) {
2283 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2284 .arg(ex.what());
2286 return (0);
2287
2288 } catch (const std::exception& ex) {
2290 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2291 .arg(ex.what());
2292 setErrorResponse(handle, ex.what());
2293 return (1);
2294 }
2295
2296 return (0);
2297}
2298
2299int
2301 try {
2302 extractCommand(handle);
2303
2304 SimpleParser parser;
2305 SubnetID id = 0;
2306
2307 size_t num = 0; // number of leases deleted
2308 stringstream ids; // a text with subnet-ids being wiped
2309
2310 // The subnet-id parameter is now optional.
2311 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2312 id = parser.getUint32(cmd_args_, "subnet-id");
2313 }
2314
2315 if (id) {
2316 // Wipe a single subnet.
2318 ids << " " << id;
2319
2320 auto observation = StatsMgr::instance().getObservation(
2321 StatsMgr::generateName("subnet", id, "declined-addresses"));
2322
2323 int64_t previous_declined = 0;
2324
2325 if (observation) {
2326 previous_declined = observation->getInteger().first;
2327 }
2328
2330 StatsMgr::generateName("subnet", id, "assigned-addresses"),
2331 static_cast<int64_t>(0));
2332
2334 StatsMgr::generateName("subnet", id, "declined-addresses"),
2335 static_cast<int64_t>(0));
2336
2337 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(id);
2338 if (sub) {
2339 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2340 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2341 StatsMgr::generateName("pool", pool->getID(),
2342 "assigned-addresses")));
2343 if (!StatsMgr::instance().getObservation(name_aa)) {
2344 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2345 }
2346
2347 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2348 StatsMgr::generateName("pool", pool->getID(),
2349 "declined-addresses")));
2350 if (!StatsMgr::instance().getObservation(name_da)) {
2351 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2352 }
2353 }
2354 }
2355
2356 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2357 } else {
2358 // Wipe them all!
2360 ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
2361 const Subnet4Collection* subs = subnets->getAll();
2362
2363 // Go over all subnets and wipe leases in each of them.
2364 for (auto const& sub : *subs) {
2365 num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
2366 ids << " " << sub->getID();
2368 StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
2369 static_cast<int64_t>(0));
2370
2372 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2373 static_cast<int64_t>(0));
2374
2375 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2376 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2377 StatsMgr::generateName("pool", pool->getID(),
2378 "assigned-addresses")));
2379 if (!StatsMgr::instance().getObservation(name_aa)) {
2380 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2381 }
2382
2383 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2384 StatsMgr::generateName("pool", pool->getID(),
2385 "declined-addresses")));
2386 if (!StatsMgr::instance().getObservation(name_da)) {
2387 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2388 }
2389 }
2390 }
2391
2392 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2393 }
2394
2395 stringstream tmp;
2396 tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
2398 : CONTROL_RESULT_EMPTY, tmp.str());
2399 setResponse(handle, response);
2400 } catch (const std::exception& ex) {
2402 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2403 .arg(ex.what());
2404 setErrorResponse(handle, ex.what());
2405 return (1);
2406 }
2407
2409 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2410 return (0);
2411}
2412
2413int
2415 try {
2416 extractCommand(handle);
2417
2418 SimpleParser parser;
2419 SubnetID id = 0;
2420
2421 size_t num = 0; // number of leases deleted
2422 stringstream ids; // a text with subnet-ids being wiped
2423
2428
2429 // The subnet-id parameter is now optional.
2430 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2431 id = parser.getUint32(cmd_args_, "subnet-id");
2432 }
2433
2434 if (id) {
2435 // Wipe a single subnet.
2437 ids << " " << id;
2438
2439 auto observation = StatsMgr::instance().getObservation(
2440 StatsMgr::generateName("subnet", id, "declined-addresses"));
2441
2442 int64_t previous_declined = 0;
2443
2444 if (observation) {
2445 previous_declined = observation->getInteger().first;
2446 }
2447
2449 StatsMgr::generateName("subnet", id, "assigned-nas" ),
2450 static_cast<int64_t>(0));
2451
2453 StatsMgr::generateName("subnet", id, "assigned-pds"),
2454 static_cast<int64_t>(0));
2455
2457 StatsMgr::generateName("subnet", id, "declined-addresses"),
2458 static_cast<int64_t>(0));
2459
2461 StatsMgr::generateName("subnet", id, "registered-nas"),
2462 static_cast<int64_t>(0));
2463
2464 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(id);
2465 if (sub) {
2466 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2467 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2468 StatsMgr::generateName("pool", pool->getID(),
2469 "assigned-nas")));
2470 if (!StatsMgr::instance().getObservation(name_anas)) {
2471 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2472 }
2473
2474 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2475 StatsMgr::generateName("pool", pool->getID(),
2476 "declined-addresses")));
2477 if (!StatsMgr::instance().getObservation(name_da)) {
2478 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2479 }
2480 }
2481
2482 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2483 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2484 StatsMgr::generateName("pd-pool", pool->getID(),
2485 "assigned-pds")));
2486 if (!StatsMgr::instance().getObservation(name_apds)) {
2487 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2488 }
2489 }
2490 }
2491
2492 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2493 } else {
2494 // Wipe them all!
2496 ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2497 const Subnet6Collection* subs = subnets->getAll();
2498
2499 // Go over all subnets and wipe leases in each of them.
2500 for (auto const& sub : *subs) {
2501 num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2502 ids << " " << sub->getID();
2504 StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2505 static_cast<int64_t>(0));
2506
2508 StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2509 static_cast<int64_t>(0));
2510
2512 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2513 static_cast<int64_t>(0));
2514
2516 StatsMgr::generateName("subnet", sub->getID(), "registered-nas"),
2517 static_cast<int64_t>(0));
2518
2519 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2520 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2521 StatsMgr::generateName("pool", pool->getID(),
2522 "assigned-nas")));
2523 if (!StatsMgr::instance().getObservation(name_anas)) {
2524 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2525 }
2526
2527 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2528 StatsMgr::generateName("pool", pool->getID(),
2529 "declined-addresses")));
2530 if (!StatsMgr::instance().getObservation(name_da)) {
2531 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2532 }
2533 }
2534
2535 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2536 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2537 StatsMgr::generateName("pd-pool", pool->getID(),
2538 "assigned-pds")));
2539 if (!StatsMgr::instance().getObservation(name_apds)) {
2540 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2541 }
2542 }
2543 }
2544
2545 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2546 }
2547
2548 stringstream tmp;
2549 tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2551 : CONTROL_RESULT_EMPTY, tmp.str());
2552 setResponse(handle, response);
2553 } catch (const std::exception& ex) {
2555 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2556 .arg(ex.what());
2557 setErrorResponse(handle, ex.what());
2558 return (1);
2559 }
2560
2562 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2563 return (0);
2564}
2565
2568 Lease6Ptr lease6;
2569
2570 switch (parameters.query_type) {
2571 case Parameters::TYPE_ADDR: {
2572 // If address was specified explicitly, let's use it as is.
2573
2574 // Let's see if there's such a lease at all.
2575 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2576 parameters.addr);
2577 if (!lease6) {
2578 lease6.reset(new Lease6());
2579 lease6->addr_ = parameters.addr;
2580 }
2581 break;
2582 }
2584 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2585 break;
2586 }
2587 case Parameters::TYPE_DUID: {
2588 if (!parameters.duid) {
2589 isc_throw(InvalidParameter, "Program error: Query by duid "
2590 "requires duid to be specified");
2591 }
2592
2593 // Let's see if there's such a lease at all.
2594 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2595 *parameters.duid,
2596 parameters.iaid,
2597 parameters.subnet_id);
2598 break;
2599 }
2600 default:
2601 isc_throw(InvalidOperation, "Unknown query type: "
2602 << static_cast<int>(parameters.query_type));
2603 }
2604
2605 return (lease6);
2606}
2607
2610 short family) const {
2611 ConstElementPtr param = params->get(name);
2612 if (!param) {
2613 isc_throw(BadValue, "'" << name << "' parameter is missing.");
2614 }
2615
2616 if (param->getType() != Element::string) {
2617 isc_throw(BadValue, "'" << name << "' is not a string.");
2618 }
2619
2620 IOAddress addr(0);
2621 try {
2622 addr = IOAddress(param->stringValue());
2623 } catch (const std::exception& ex) {
2624 isc_throw(BadValue, "'" << param->stringValue()
2625 << "' is not a valid IP address.");
2626 }
2627
2628 if (addr.getFamily() != family) {
2629 isc_throw(BadValue, "Invalid "
2630 << (family == AF_INET6 ? "IPv6" : "IPv4")
2631 << " address specified: " << param->stringValue());
2632 }
2633
2634 return (addr);
2635}
2636
2637int
2639 std::stringstream ss;
2640 int resp_code = CONTROL_RESULT_ERROR;
2641
2642 try {
2643 extractCommand(handle);
2644
2645 // Get the target lease address. Invalid value will throw.
2646 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2647
2648 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2649 ss << "DDNS updating is not enabled";
2650 resp_code = CONTROL_RESULT_CONFLICT;
2651 } else {
2652 // Find the lease.
2654 if (!lease) {
2655 ss << "No lease found for: " << addr.toText();
2656 resp_code = CONTROL_RESULT_EMPTY;
2657 } else if (lease->hostname_.empty()) {
2658 ss << "Lease for: " << addr.toText()
2659 << ", has no hostname, nothing to update";
2660 resp_code = CONTROL_RESULT_CONFLICT;
2661 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2662 ss << "Neither forward nor reverse updates enabled for lease for: "
2663 << addr.toText();
2664 resp_code = CONTROL_RESULT_CONFLICT;
2665 } else {
2666 // We have a lease with a hostname and updates in at least
2667 // one direction enabled. Queue an NCR for it.
2668 queueNCR(CHG_ADD, lease);
2669 ss << "NCR generated for: " << addr.toText()
2670 << ", hostname: " << lease->hostname_;
2671 setSuccessResponse(handle, ss.str());
2673 return (0);
2674 }
2675 }
2676 } catch (const std::exception& ex) {
2677 ss << ex.what();
2678 }
2679
2681 setErrorResponse(handle, ss.str(), resp_code);
2682 return (resp_code == CONTROL_RESULT_EMPTY || resp_code == CONTROL_RESULT_CONFLICT ? 0 : 1);
2683}
2684
2685int
2687 std::stringstream ss;
2688 int resp_code = CONTROL_RESULT_ERROR;
2689
2690 try {
2691 extractCommand(handle);
2692
2693 // Get the target lease address. Invalid value will throw.
2694 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2695
2696 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2697 ss << "DDNS updating is not enabled";
2698 resp_code = CONTROL_RESULT_CONFLICT;
2699 } else {
2700 // Find the lease.
2702 if (!lease) {
2703 ss << "No lease found for: " << addr.toText();
2704 resp_code = CONTROL_RESULT_EMPTY;
2705 } else if (lease->hostname_.empty()) {
2706 ss << "Lease for: " << addr.toText()
2707 << ", has no hostname, nothing to update";
2708 resp_code = CONTROL_RESULT_CONFLICT;
2709 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2710 ss << "Neither forward nor reverse updates enabled for lease for: "
2711 << addr.toText();
2712 resp_code = CONTROL_RESULT_CONFLICT;
2713 } else {
2714 // We have a lease with a hostname and updates in at least
2715 // one direction enabled. Queue an NCR for it.
2716 queueNCR(CHG_ADD, lease);
2717 ss << "NCR generated for: " << addr.toText()
2718 << ", hostname: " << lease->hostname_;
2719 setSuccessResponse(handle, ss.str());
2721 return (0);
2722 }
2723 }
2724 } catch (const std::exception& ex) {
2725 ss << ex.what();
2726 }
2727
2729 setErrorResponse(handle, ss.str(), resp_code);
2730 return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2731}
2732
2735 const IOAddress& lease_address,
2736 const DuidPtr& duid,
2737 const int control_result,
2738 const std::string& error_message) const {
2739 auto failed_lease_map = Element::createMap();
2740 failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2741
2742 if (!lease_address.isV6Zero()) {
2743 failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2744
2745 } else if (duid) {
2746 failed_lease_map->set("duid", Element::create(duid->toText()));
2747 }
2748
2749 // Associate the result with the lease.
2750 failed_lease_map->set("result", Element::create(control_result));
2751 failed_lease_map->set("error-message", Element::create(error_message));
2752
2753 return (failed_lease_map);
2754}
2755
2756int
2758 bool v4 = true;
2759 try {
2760 extractCommand(handle);
2761 v4 = (cmd_name_ == "lease4-write");
2762
2763 if (!cmd_args_) {
2764 isc_throw(isc::BadValue, "no parameters specified for the command");
2765 }
2766
2767 ConstElementPtr file = cmd_args_->get("filename");
2768 if (!file) {
2769 isc_throw(BadValue, "'filename' parameter not specified");
2770 }
2771 if (file->getType() != Element::string) {
2772 isc_throw(BadValue, "'filename' parameter must be a string");
2773 }
2774
2775 std::string filename;
2776 try {
2777 filename = CfgMgr::instance().validatePath(file->stringValue());
2778 } catch (const SecurityWarn& ex) {
2780 .arg(ex.what());
2781 filename = file->stringValue();
2782 } catch (const std::exception& ex) {
2783 isc_throw(BadValue, "'filename' parameter is invalid: " << ex.what());
2784 }
2785
2786 if (v4) {
2788 } else {
2790 }
2791
2792 ostringstream s;
2793 s << (v4 ? "IPv4" : "IPv6")
2794 << " lease database into '"
2795 << filename << "'.";
2797 setResponse(handle, response);
2798 } catch (const std::exception& ex) {
2799 setErrorResponse(handle, ex.what());
2800 return (CONTROL_RESULT_ERROR);
2801 }
2802
2803 return (0);
2804}
2805
2806void
2809 uint32_t offer_lifetime;
2810 callout_handle.getArgument("offer_lifetime", offer_lifetime);
2811 if (!offer_lifetime) {
2812 // Offers leases are not being persisted, nothing to do.
2813 return;
2814 }
2815
2816 // Get the remaining arguments we need.
2817 Pkt4Ptr query;
2818 Pkt4Ptr response;
2819 Lease4CollectionPtr leases;
2820
2821 callout_handle.getArgument("query4", query);
2822 callout_handle.getArgument("response4", response);
2823 callout_handle.getArgument("leases4", leases);
2824
2825 if (!leases || leases->empty() || !((*leases)[0])) {
2826 isc_throw(Unexpected, "lease4Offer - no lease!");
2827 }
2828
2829 Lease4Ptr lease = (*leases)[0];
2830 try {
2831 if (mgr->evaluateVariables(query, response, lease)) {
2833 }
2834 } catch (const NoSuchLease&) {
2835 isc_throw(LeaseCmdsConflict, "failed to update"
2836 " the lease with address " << lease->addr_ <<
2837 " either because the lease has been"
2838 " deleted or it has changed in the database");
2839 } catch (const std::exception& ex) {
2840 isc_throw(Unexpected, "evaluating binding variables failed for: "
2841 << query->getLabel() << ", :" << ex.what());
2842 }
2843}
2844
2845void
2848 Pkt4Ptr query;
2849 Pkt4Ptr response;
2850 Lease4CollectionPtr leases;
2851
2852 // Get the necessary arguments.
2853 callout_handle.getArgument("query4", query);
2854 callout_handle.getArgument("response4", response);
2855 callout_handle.getArgument("leases4", leases);
2856
2857 if (!leases) {
2858 isc_throw(Unexpected, "leases4Committed - leases is null");
2859 }
2860
2861 // In some cases we may have no lease, e.g. DHCPNAK,
2862 // or no response e.g. DHCPRELEASE.
2863 if (leases->empty() || !response || (response->getType() != DHCPACK)) {
2864 return;
2865 }
2866
2867 Lease4Ptr lease = (*leases)[0];
2868 if (!lease) {
2869 isc_throw(Unexpected, "leases4Committed - lease is null");
2870 }
2871
2872 try {
2873 if (mgr->evaluateVariables(query, response, lease)) {
2875 }
2876 } catch (const NoSuchLease&) {
2877 isc_throw(LeaseCmdsConflict, "failed to update"
2878 " the lease with address " << lease->addr_ <<
2879 " either because the lease has been"
2880 " deleted or it has changed in the database");
2881 } catch (const std::exception& ex) {
2882 isc_throw(Unexpected, "evaluating binding variables failed for: "
2883 << query->getLabel() << ", :" << ex.what());
2884 }
2885}
2886
2887void
2890 Pkt6Ptr query;
2891 Pkt6Ptr response;
2892 Lease6CollectionPtr leases;
2893
2894 // Get the necessary arguments.
2895 callout_handle.getArgument("query6", query);
2896 callout_handle.getArgument("response6", response);
2897 callout_handle.getArgument("leases6", leases);
2898
2899 if (!leases) {
2900 isc_throw(Unexpected, "leases6Committed - leases is null");
2901 }
2902
2903 // In some cases we may have no active leases or no response.
2904 if (leases->empty() || !response) {
2905 return;
2906 }
2907
2908 int attempted = 0;
2909 int failed = 0;
2910 for (auto lease : *leases) {
2911 try {
2912 if (!lease) {
2913 isc_throw(Unexpected, "leases6Committed - lease is null");
2914 }
2915
2921 // Only update a lease if its active.
2922 if (lease->valid_lft_) {
2923 ++attempted;
2924 if (mgr->evaluateVariables(query, response, lease)) {
2926 }
2927 }
2928 } catch (const NoSuchLease&) {
2929 ++failed;
2931 .arg(lease->addr_.toText())
2932 .arg(query->getLabel());
2933 } catch (const std::exception& ex) {
2934 ++failed;
2936 .arg(query->getLabel())
2937 .arg(lease->addr_.toText())
2938 .arg(ex.what());
2939 }
2940 }
2941
2942 if (failed) {
2943 isc_throw(Unexpected, failed << " out of " << attempted
2944 << " leases failed to update for "
2945 << query->getLabel());
2946 }
2947}
2948
2949int
2951 return (impl_->leaseAddHandler(handle));
2952}
2953
2954int
2956 return (impl_->lease6BulkApplyHandler(handle));
2957}
2958
2959int
2961 return (impl_->leaseGetHandler(handle));
2962}
2963
2964int
2966 return (impl_->leaseGetAllHandler(handle));
2967}
2968
2969int
2971 return (impl_->leaseGetPageHandler(handle));
2972}
2973
2974int
2976 return (impl_->leaseGetByHwAddressHandler(handle));
2977}
2978
2979int
2981 return (impl_->leaseGetByClientIdHandler(handle));
2982}
2983
2984int
2986 return (impl_->leaseGetByDuidHandler(handle));
2987}
2988
2989int
2991 return (impl_->leaseGetByHostnameHandler(handle));
2992}
2993
2994int
2996 return (impl_->lease4DelHandler(handle));
2997}
2998
2999int
3001 return (impl_->lease6DelHandler(handle));
3002}
3003
3004int
3006 return (impl_->lease4UpdateHandler(handle));
3007}
3008
3009int
3011 return (impl_->lease6UpdateHandler(handle));
3012}
3013
3014int
3017 return (impl_->lease4WipeHandler(handle));
3018}
3019
3020int
3023 return (impl_->lease6WipeHandler(handle));
3024}
3025
3026int
3028 return (impl_->lease4ResendDdnsHandler(handle));
3029}
3030
3031int
3033 return (impl_->lease6ResendDdnsHandler(handle));
3034}
3035
3036int
3038 return (impl_->leaseWriteHandler(handle));
3039}
3040
3042}
3043
3044
3045void
3048 impl_->lease4Offer(callout_handle, mgr);
3049}
3050
3051void
3054 impl_->leases4Committed(callout_handle, mgr);
3055}
3056
3057void
3060 impl_->leases6Committed(callout_handle, mgr);
3061}
3062
3063} // end of namespace lease_cmds
3064} // end of namespace isc
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition duid.cc:50
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
@ map
Definition data.h:147
@ integer
Definition data.h:140
@ boolean
Definition data.h:142
@ list
Definition data.h:146
@ string
Definition data.h:144
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
Exception thrown when a command failed due to a conflict.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown when an unexpected error condition occurs.
Base class that command handler implementers may use for common tasks.
Definition cmds_impl.h:21
std::string cmd_name_
Stores the command name extracted by a call to extractCommand.
Definition cmds_impl.h:69
void setErrorResponse(hooks::CalloutHandle &handle, const std::string &text, int status=CONTROL_RESULT_ERROR)
Set the callout argument "response" to indicate an error.
Definition cmds_impl.h:54
data::ConstElementPtr cmd_args_
Stores the command arguments extracted by a call to extractCommand.
Definition cmds_impl.h:72
void extractCommand(hooks::CalloutHandle &handle)
Extracts the command name and arguments from a Callout handle.
Definition cmds_impl.h:29
void setSuccessResponse(hooks::CalloutHandle &handle, const std::string &text)
Set the callout argument "response" to indicate success.
Definition cmds_impl.h:43
void setResponse(hooks::CalloutHandle &handle, data::ConstElementPtr &response)
Set the callout argument "response" to the given response.
Definition cmds_impl.h:64
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
std::string validatePath(const std::string data_path) const
Validates a file path against the supported directory for DHDP data.
Definition cfgmgr.cc:40
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Definition duid.cc:73
Holds DUID (DHCPv6 Unique Identifier)
Definition duid.h:142
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual size_t wipeLeases6(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
virtual Lease4Collection getLeases4(SubnetID subnet_id) const =0
Returns all IPv4 leases for the particular subnet identifier.
virtual void writeLeases6(const std::string &filename)=0
Write V6 leases to a file.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual size_t wipeLeases4(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual void writeLeases4(const std::string &filename)=0
Write V4 leases to a file.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
Wraps value holding size of the page with leases.
Definition lease_mgr.h:46
Attempt to update lease that was not there.
Resource race avoidance RAII handler for DHCPv4.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
Resource race avoidance RAII handler.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
Per-packet callout handle.
void getArgument(const std::string &name, T &value) const
Get argument.
Parser for Lease4 structure.
virtual isc::dhcp::Lease4Ptr parse(isc::dhcp::ConstSrvConfigPtr &cfg, const isc::data::ConstElementPtr &lease_info, bool &force_create)
Parses Element tree and tries to convert to Lease4.
Parser for Lease6 structure.
virtual isc::dhcp::Lease6Ptr parse(isc::dhcp::ConstSrvConfigPtr &cfg, const isc::data::ConstElementPtr &lease_info, bool &force_create)
Parses Element tree and tries to convert to Lease4.
Parameters specified for lease commands.
Definition lease_cmds.cc:59
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:77
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:63
@ TYPE_CLIENT_ID
query by client identifier (v4 only).
Definition lease_cmds.cc:67
@ TYPE_HWADDR
query by hardware address (v4 only)
Definition lease_cmds.cc:65
@ TYPE_ADDR
query by IP address (either v4 or v6)
Definition lease_cmds.cc:64
isc::dhcp::ClientIdPtr client_id
Specifies identifier value (used when query_type is TYPE_CLIENT_ID)
Definition lease_cmds.cc:83
static Type txtToType(const std::string &txt)
Attempts to covert text to one of specified types.
Definition lease_cmds.cc:94
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:74
SubnetID subnet_id
Specifies subnet-id (always used)
Definition lease_cmds.cc:71
isc::dhcp::DuidPtr duid
Specifies identifier value (used when query_type is TYPE_DUID)
Definition lease_cmds.cc:80
Wrapper class around reservation command handlers.
Definition lease_cmds.cc:55
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, lease6-get-by-hw-address command handler
static ConstElementPtr getExtendedInfo6(const Lease6Ptr &lease)
Get DHCPv6 extended info.
int leaseGetHandler(CalloutHandle &handle)
lease4-get, lease6-get command handler
static bool addOrUpdate4(Lease4Ptr lease, bool force_create)
Add or update lease.
static void leases4Committed(CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases4_committed hookpoint handler.
int lease6WipeHandler(CalloutHandle &handle)
lease6-wipe handler
int leaseGetByClientIdHandler(hooks::CalloutHandle &handle)
lease4-get-by-client-id command handler
int lease6ResendDdnsHandler(CalloutHandle &handle)
lease6-resend-ddns handler
int leaseAddHandler(CalloutHandle &handle)
lease4-add, lease6-add command handler
int lease4ResendDdnsHandler(CalloutHandle &handle)
lease4-resend-ddns handler
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, lease6-get-by-hw-address command handler
int lease6UpdateHandler(hooks::CalloutHandle &handle)
lease6-update handler
void leases6Committed(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases6_committed hookpoint handler.
int leaseGetByDuidHandler(hooks::CalloutHandle &handle)
lease6-get-by-duid command handler
int lease6BulkApplyHandler(hooks::CalloutHandle &handle)
lease6-bulk-apply command handler
int lease4WipeHandler(hooks::CalloutHandle &handle)
lease4-wipe handler
int lease6ResendDdnsHandler(hooks::CalloutHandle &handle)
lease6-resend-ddns command handler
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
A generic exception that is thrown if a parameter given violates security check but enforcement is la...
Definition filesystem.h:21
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
const isc::log::MessageID LEASE_CMDS_DEL4
const isc::log::MessageID LEASE_CMDS_WIPE4_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE4_FAILED
const isc::log::MessageID LEASE_CMDS_WIPE6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6_CONFLICT
const isc::log::MessageID LEASE_CMDS_UPDATE4_CONFLICT
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED
const isc::log::MessageID LEASE_CMDS_DEL6
const isc::log::MessageID LEASE_CMDS_ADD4_FAILED
const isc::log::MessageID LEASE_CMDS_LEASES6_COMMITTED_LEASE_ERROR
const isc::log::MessageID LEASE_CMDS_PATH_SECURITY_WARNING
const isc::log::MessageID LEASE_CMDS_ADD6
const isc::log::MessageID LEASE_CMDS_ADD4
const isc::log::MessageID LEASE_CMDS_WIPE6
const isc::log::MessageID LEASE_CMDS_ADD6_CONFLICT
const isc::log::MessageID LEASE_CMDS_BULK_APPLY6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4
const isc::log::MessageID LEASE_CMDS_GET6_FAILED
const isc::log::MessageID LEASE_CMDS_WIPE4
const isc::log::MessageID LEASE_CMDS_BULK_APPLY6
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6_FAILED
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6
const isc::log::MessageID LEASE_CMDS_GET4_FAILED
const isc::log::MessageID LEASE_CMDS_ADD4_CONFLICT
const isc::log::MessageID LEASE_CMDS_LEASES6_COMMITTED_CONFLICT
const isc::log::MessageID LEASE_CMDS_DEL4_FAILED
const isc::log::MessageID LEASE_CMDS_ADD6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE4
const isc::log::MessageID LEASE_CMDS_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:556
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