Kea 3.1.3
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()) {
526 StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(1));
527
529 StatsMgr::generateName("subnet", lease->subnet_id_,
530 "assigned-addresses"),
531 static_cast<int64_t>(1));
532
533 PoolPtr pool;
534 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
535 if (subnet) {
536 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
537 if (pool) {
539 StatsMgr::generateName("subnet", subnet->getID(),
540 StatsMgr::generateName("pool", pool->getID(),
541 "assigned-addresses")),
542 static_cast<int64_t>(1));
543 }
544 }
545
546 if (lease->stateDeclined()) {
547 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
548
550 StatsMgr::generateName("subnet", lease->subnet_id_,
551 "declined-addresses"),
552 static_cast<int64_t>(1));
553
554 if (pool) {
556 StatsMgr::generateName("subnet", subnet->getID(),
557 StatsMgr::generateName("pool", pool->getID(),
558 "declined-addresses")),
559 static_cast<int64_t>(1));
560 }
561 }
562 }
563}
564
565void
567 if (lease->stateRegistered()) {
569 StatsMgr::generateName("subnet", lease->subnet_id_, "registered-nas"),
570 static_cast<int64_t>(1));
571 } else if (!lease->stateExpiredReclaimed()) {
572 StatsMgr::instance().addValue(lease->type_ == Lease::TYPE_NA ?
573 "assigned-nas" : "assigned-pds",
574 static_cast<int64_t>(1));
575
577 StatsMgr::generateName("subnet", lease->subnet_id_,
578 lease->type_ == Lease::TYPE_NA ?
579 "assigned-nas" : "assigned-pds"),
580 static_cast<int64_t>(1));
581
582 PoolPtr pool;
583 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
584 if (subnet) {
585 pool = subnet->getPool(lease->type_, lease->addr_, false);
586 if (pool) {
588 StatsMgr::generateName("subnet", subnet->getID(),
589 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
590 "pool" : "pd-pool", pool->getID(),
591 lease->type_ == Lease::TYPE_NA ?
592 "assigned-nas" : "assigned-pds")),
593 static_cast<int64_t>(1));
594 }
595 }
596
597 if (lease->stateDeclined()) {
598 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
599
601 StatsMgr::generateName("subnet", lease->subnet_id_,
602 "declined-addresses"),
603 static_cast<int64_t>(1));
604
605 if (pool) {
607 StatsMgr::generateName("subnet", subnet->getID(),
608 StatsMgr::generateName("pool", pool->getID(),
609 "declined-addresses")),
610 static_cast<int64_t>(1));
611 }
612 }
613 }
614}
615
616void
618 const Lease4Ptr& lease) {
619 if (!existing->stateExpiredReclaimed()) {
620 ConstSubnet4Ptr subnet;
621 PoolPtr pool;
622
623 // old lease is non expired-reclaimed
624 if (existing->subnet_id_ != lease->subnet_id_) {
626 StatsMgr::generateName("subnet", existing->subnet_id_,
627 "assigned-addresses"),
628 static_cast<int64_t>(-1));
629
630 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(existing->subnet_id_);
631 if (subnet) {
632 pool = subnet->getPool(Lease::TYPE_V4, existing->addr_, false);
633 if (pool) {
635 StatsMgr::generateName("subnet", subnet->getID(),
636 StatsMgr::generateName("pool", pool->getID(),
637 "assigned-addresses")),
638 static_cast<int64_t>(-1));
639 }
640 }
641 }
642
643 if (existing->stateDeclined()) {
644 // old lease is declined
645 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
646
648 StatsMgr::generateName("subnet", existing->subnet_id_,
649 "declined-addresses"),
650 static_cast<int64_t>(-1));
651
652 if (pool) {
654 StatsMgr::generateName("subnet", subnet->getID(),
655 StatsMgr::generateName("pool", pool->getID(),
656 "declined-addresses")),
657 static_cast<int64_t>(-1));
658 }
659 }
660
661 pool.reset();
662
663 if (!lease->stateExpiredReclaimed()) {
664 // new lease is non expired-reclaimed
665 if (existing->subnet_id_ != lease->subnet_id_) {
667 StatsMgr::generateName("subnet", lease->subnet_id_,
668 "assigned-addresses"),
669 static_cast<int64_t>(1));
670
671 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
672 if (subnet) {
673 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
674 if (pool) {
676 StatsMgr::generateName("subnet", subnet->getID(),
677 StatsMgr::generateName("pool", pool->getID(),
678 "assigned-addresses")),
679 static_cast<int64_t>(1));
680 }
681 }
682 }
683
684 if (lease->stateDeclined()) {
685 // new lease is declined
686 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
687
689 StatsMgr::generateName("subnet", lease->subnet_id_,
690 "declined-addresses"),
691 static_cast<int64_t>(1));
692
693 if (pool) {
695 StatsMgr::generateName("subnet", subnet->getID(),
696 StatsMgr::generateName("pool", pool->getID(),
697 "declined-addresses")),
698 static_cast<int64_t>(1));
699 }
700 }
701 }
702 } else {
703 // old lease is expired-reclaimed
704 if (!lease->stateExpiredReclaimed()) {
705 // new lease is non expired-reclaimed
706 StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(1));
707
709 StatsMgr::generateName("subnet", lease->subnet_id_,
710 "assigned-addresses"),
711 static_cast<int64_t>(1));
712
713 PoolPtr pool;
714 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
715 if (subnet) {
716 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
717 if (pool) {
719 StatsMgr::generateName("subnet", subnet->getID(),
720 StatsMgr::generateName("pool", pool->getID(),
721 "assigned-addresses")),
722 static_cast<int64_t>(1));
723 }
724 }
725
726 if (lease->stateDeclined()) {
727 // new lease is declined
728 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
729
731 StatsMgr::generateName("subnet", lease->subnet_id_,
732 "declined-addresses"),
733 static_cast<int64_t>(1));
734
735 if (pool) {
737 StatsMgr::generateName("subnet", subnet->getID(),
738 StatsMgr::generateName("pool", pool->getID(),
739 "declined-addresses")),
740 static_cast<int64_t>(1));
741 }
742 }
743 }
744 }
745}
746
747void
749 const Lease6Ptr& lease) {
750 // Does not cover registered <-> not registered transition.
751 if (existing->stateRegistered()) {
752 if (existing->subnet_id_ != lease->subnet_id_) {
754 StatsMgr::generateName("subnet", existing->subnet_id_,
755 "registered-nas"),
756 static_cast<int64_t>(-1));
758 StatsMgr::generateName("subnet", lease->subnet_id_,
759 "registered-nas"),
760 static_cast<int64_t>(1));
761 }
762 } else if (!existing->stateExpiredReclaimed()) {
763 ConstSubnet6Ptr subnet;
764 PoolPtr pool;
765
766 // old lease is non expired-reclaimed
767 if (existing->subnet_id_ != lease->subnet_id_) {
769 StatsMgr::generateName("subnet", existing->subnet_id_,
770 lease->type_ == Lease::TYPE_NA ?
771 "assigned-nas" : "assigned-pds"),
772 static_cast<int64_t>(-1));
773
774 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(existing->subnet_id_);
775 if (subnet) {
776 pool = subnet->getPool(existing->type_, existing->addr_, false);
777 if (pool) {
779 StatsMgr::generateName("subnet", subnet->getID(),
780 StatsMgr::generateName(existing->type_ == Lease::TYPE_NA ?
781 "pool" : "pd-pool", pool->getID(),
782 existing->type_ == Lease::TYPE_NA ?
783 "assigned-nas" : "assigned-pds")),
784 static_cast<int64_t>(-1));
785 }
786 }
787 }
788
789 if (existing->stateDeclined()) {
790 // old lease is declined
791 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
792
794 StatsMgr::generateName("subnet", existing->subnet_id_,
795 "declined-addresses"),
796 static_cast<int64_t>(-1));
797
798 if (pool) {
800 StatsMgr::generateName("subnet", subnet->getID(),
801 StatsMgr::generateName("pool", pool->getID(),
802 "declined-addresses")),
803 static_cast<int64_t>(-1));
804 }
805 }
806
807 pool.reset();
808
809 if (!lease->stateExpiredReclaimed()) {
810 // new lease is non expired-reclaimed
811 if (existing->subnet_id_ != lease->subnet_id_) {
813 StatsMgr::generateName("subnet", lease->subnet_id_,
814 lease->type_ == Lease::TYPE_NA ?
815 "assigned-nas" : "assigned-pds"),
816 static_cast<int64_t>(1));
817
818 subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
819 if (subnet) {
820 pool = subnet->getPool(lease->type_, lease->addr_, false);
821 if (pool) {
823 StatsMgr::generateName("subnet", subnet->getID(),
824 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
825 "pool" : "pd-pool", pool->getID(),
826 lease->type_ == Lease::TYPE_NA ?
827 "assigned-nas" : "assigned-pds")),
828 static_cast<int64_t>(1));
829 }
830 }
831 }
832
833 if (lease->stateDeclined()) {
834 // new lease is declined
835 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
836
838 StatsMgr::generateName("subnet", lease->subnet_id_,
839 "declined-addresses"),
840 static_cast<int64_t>(1));
841
842 if (pool) {
844 StatsMgr::generateName("subnet", subnet->getID(),
845 StatsMgr::generateName("pool", pool->getID(),
846 "declined-addresses")),
847 static_cast<int64_t>(1));
848 }
849 }
850 }
851 } else {
852 // old lease is expired-reclaimed
853 if (!lease->stateExpiredReclaimed()) {
854 // new lease is non expired-reclaimed
855 StatsMgr::instance().addValue(lease->type_ == Lease::TYPE_NA ?
856 "assigned-nas" : "assigned-pds",
857 static_cast<int64_t>(1));
858
860 StatsMgr::generateName("subnet", lease->subnet_id_,
861 lease->type_ == Lease::TYPE_NA ?
862 "assigned-nas" : "assigned-pds"),
863 static_cast<int64_t>(1));
864
865 PoolPtr pool;
866 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
867 if (subnet) {
868 pool = subnet->getPool(lease->type_, lease->addr_, false);
869 if (pool) {
871 StatsMgr::generateName("subnet", subnet->getID(),
872 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
873 "pool" : "pd-pool", pool->getID(),
874 lease->type_ == Lease::TYPE_NA ?
875 "assigned-nas" : "assigned-pds")),
876 static_cast<int64_t>(1));
877 }
878 }
879
880 if (lease->stateDeclined()) {
881 // new lease is declined
882 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
883
885 StatsMgr::generateName("subnet", lease->subnet_id_,
886 "declined-addresses"),
887 static_cast<int64_t>(1));
888
889 if (pool) {
891 StatsMgr::generateName("subnet", subnet->getID(),
892 StatsMgr::generateName("pool", pool->getID(),
893 "declined-addresses")),
894 static_cast<int64_t>(1));
895 }
896 }
897 }
898 }
899}
900
901void
903 if (!lease->stateExpiredReclaimed()) {
904 StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(-1));
905
907 StatsMgr::generateName("subnet", lease->subnet_id_,
908 "assigned-addresses"),
909 static_cast<int64_t>(-1));
910
911 PoolPtr pool;
912 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
913 if (subnet) {
914 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
915 if (pool) {
917 StatsMgr::generateName("subnet", subnet->getID(),
918 StatsMgr::generateName("pool", pool->getID(),
919 "assigned-addresses")),
920 static_cast<int64_t>(-1));
921 }
922 }
923
924 if (lease->stateDeclined()) {
925 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
926
928 StatsMgr::generateName("subnet", lease->subnet_id_,
929 "declined-addresses"),
930 static_cast<int64_t>(-1));
931
932 if (pool) {
934 StatsMgr::generateName("subnet", subnet->getID(),
935 StatsMgr::generateName("pool", pool->getID(),
936 "declined-addresses")),
937 static_cast<int64_t>(-1));
938 }
939 }
940 }
941}
942
943void
945 if (lease->stateRegistered()) {
947 StatsMgr::generateName("subnet", lease->subnet_id_,
948 "registered-nas"),
949 static_cast<int64_t>(-1));
950 } else if (!lease->stateExpiredReclaimed()) {
951 StatsMgr::instance().addValue(lease->type_ == Lease::TYPE_NA ?
952 "assigned-nas" : "assigned-pds",
953 static_cast<int64_t>(-1));
954
956 StatsMgr::generateName("subnet", lease->subnet_id_,
957 lease->type_ == Lease::TYPE_NA ?
958 "assigned-nas" : "assigned-pds"),
959 static_cast<int64_t>(-1));
960
961 PoolPtr pool;
962 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
963 if (subnet) {
964 pool = subnet->getPool(lease->type_, lease->addr_, false);
965 if (pool) {
967 StatsMgr::generateName("subnet", subnet->getID(),
968 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
969 "pool" : "pd-pool", pool->getID(),
970 lease->type_ == Lease::TYPE_NA ?
971 "assigned-nas" : "assigned-pds")),
972 static_cast<int64_t>(-1));
973 }
974 }
975
976 if (lease->stateDeclined()) {
977 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
978
980 StatsMgr::generateName("subnet", lease->subnet_id_,
981 "declined-addresses"),
982 static_cast<int64_t>(-1));
983
984 if (pool) {
986 StatsMgr::generateName("subnet", subnet->getID(),
987 StatsMgr::generateName("pool", pool->getID(),
988 "declined-addresses")),
989 static_cast<int64_t>(-1));
990 }
991 }
992 }
993}
994
995bool
996LeaseCmdsImpl::addOrUpdate4(Lease4Ptr lease, bool force_create) {
997 Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease->addr_);
998 if (force_create && !existing) {
999 // lease does not exist
1000 if (!LeaseMgrFactory::instance().addLease(lease)) {
1002 "lost race between calls to get and add");
1003 }
1005 return (true);
1006 }
1007 if (existing) {
1008 // Update lease current expiration time with value received from the
1009 // database. Some database backends reject operations on the lease if
1010 // the current expiration time value does not match what is stored.
1011 Lease::syncCurrentExpirationTime(*existing, *lease);
1012 }
1013 try {
1015 } catch (const NoSuchLease&) {
1016 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
1017 << lease->addr_ << " either because the lease has been "
1018 "deleted or it has changed in the database, in both cases a "
1019 "retry might succeed");
1020 }
1021
1022 LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
1023 return (false);
1024}
1025
1026bool
1027LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) {
1028 Lease6Ptr existing =
1029 LeaseMgrFactory::instance().getLease6(lease->type_, lease->addr_);
1030 if (force_create && !existing) {
1031 // lease does not exist
1032 if (!LeaseMgrFactory::instance().addLease(lease)) {
1034 "lost race between calls to get and add");
1035 }
1037 return (true);
1038 }
1039 if (existing) {
1040 // Refuse used <-> registered transitions.
1041 if (existing->stateRegistered() && !lease->stateRegistered()) {
1042 isc_throw(BadValue, "illegal reuse of registered address "
1043 << lease->addr_);
1044 } else if (!existing->stateRegistered() && lease->stateRegistered()) {
1045 isc_throw(BadValue, "address in use: " << lease->addr_
1046 << " can't be registered");
1047 }
1048
1049 // Update lease current expiration time with value received from the
1050 // database. Some database backends reject operations on the lease if
1051 // the current expiration time value does not match what is stored.
1052 Lease::syncCurrentExpirationTime(*existing, *lease);
1053
1054 // Check what is the action about extended info.
1055 ConstElementPtr old_extended_info = getExtendedInfo6(existing);
1056 ConstElementPtr extended_info = getExtendedInfo6(lease);
1057 if ((!old_extended_info && !extended_info) ||
1058 (old_extended_info && extended_info &&
1059 (*old_extended_info == *extended_info))) {
1060 // Leave the default Lease6::ACTION_IGNORE.
1061 } else {
1062 lease->extended_info_action_ = Lease6::ACTION_UPDATE;
1063 }
1064 }
1065 try {
1067 } catch (const NoSuchLease&) {
1068 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
1069 << lease->addr_ << " either because the lease has been "
1070 "deleted or it has changed in the database, in both cases a "
1071 "retry might succeed");
1072 }
1073
1074 LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
1075 return (false);
1076}
1077
1078int
1080 // Arbitrary defaulting to DHCPv4 or with other words extractCommand
1081 // below is not expected to throw...
1082 bool v4 = true;
1083 stringstream resp;
1084 string lease_address = "unknown";
1085 try {
1086 extractCommand(handle);
1087 v4 = (cmd_name_ == "lease4-add");
1088 if (!cmd_args_) {
1089 isc_throw(isc::BadValue, "no parameters specified for the command");
1090 }
1091
1093
1094 // This parameter is ignored for the commands adding the lease.
1095 bool force_create = false;
1096 Lease4Ptr lease4;
1097 Lease6Ptr lease6;
1098 if (v4) {
1099 Lease4Parser parser;
1100 lease4 = parser.parse(config, cmd_args_, force_create);
1101 if (lease4) {
1102 lease_address = lease4->addr_.toText();
1103 bool success;
1104 if (!MultiThreadingMgr::instance().getMode()) {
1105 // Not multi-threading.
1106 success = LeaseMgrFactory::instance().addLease(lease4);
1107 } else {
1108 // Multi-threading, try to lock first to avoid a race.
1109 ResourceHandler4 resource_handler;
1110 if (resource_handler.tryLock4(lease4->addr_)) {
1111 success = LeaseMgrFactory::instance().addLease(lease4);
1112 } else {
1114 "ResourceBusy: IP address:" << lease4->addr_
1115 << " could not be added.");
1116 }
1117 }
1118
1119 if (!success) {
1120 isc_throw(LeaseCmdsConflict, "IPv4 lease already exists.");
1121 }
1122
1124 resp << "Lease for address " << lease4->addr_.toText()
1125 << ", subnet-id " << lease4->subnet_id_ << " added.";
1126 }
1127 } else {
1128 Lease6Parser parser;
1129 lease6 = parser.parse(config, cmd_args_, force_create);
1130 if (lease6) {
1131 lease_address = lease6->addr_.toText();
1132 bool success;
1133 if (!MultiThreadingMgr::instance().getMode()) {
1134 // Not multi-threading.
1135 success = LeaseMgrFactory::instance().addLease(lease6);
1136 } else {
1137 // Multi-threading, try to lock first to avoid a race.
1138 ResourceHandler resource_handler;
1139 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
1140 success = LeaseMgrFactory::instance().addLease(lease6);
1141 } else {
1143 "ResourceBusy: IP address:" << lease6->addr_
1144 << " could not be added.");
1145 }
1146 }
1147
1148 if (!success) {
1149 isc_throw(LeaseCmdsConflict, "IPv6 lease already exists.");
1150 }
1151
1153 if (lease6->type_ == Lease::TYPE_NA) {
1154 resp << "Lease for address " << lease6->addr_.toText()
1155 << ", subnet-id " << lease6->subnet_id_ << " added.";
1156 } else {
1157 resp << "Lease for prefix " << lease6->addr_.toText()
1158 << "/" << static_cast<int>(lease6->prefixlen_)
1159 << ", subnet-id " << lease6->subnet_id_ << " added.";
1160 }
1161 }
1162 }
1163 } catch (const LeaseCmdsConflict& ex) {
1165 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1166 .arg(ex.what());
1168 return (0);
1169
1170 } catch (const std::exception& ex) {
1172 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1173 .arg(ex.what());
1174 setErrorResponse(handle, ex.what());
1175 return (1);
1176 }
1177
1180 .arg(lease_address);
1181 setSuccessResponse(handle, resp.str());
1182 return (0);
1183}
1184
1187 Parameters x;
1188
1189 if (!params || params->getType() != Element::map) {
1190 isc_throw(BadValue, "Parameters missing or are not a map.");
1191 }
1192
1193 if (params->contains("update-ddns")) {
1194 ConstElementPtr tmp = params->get("update-ddns");
1195 if (tmp->getType() != Element::boolean) {
1196 isc_throw(BadValue, "'update-ddns' is not a boolean");
1197 } else {
1198 x.updateDDNS = tmp->boolValue();
1199 }
1200 }
1201
1202 // We support several sets of parameters for leaseX-get/lease-del:
1203 // lease-get(type, address)
1204 // lease-get(type, subnet-id, identifier-type, identifier)
1205
1206 if (params->contains("type")) {
1207 string t = params->get("type")->stringValue();
1208 if (t == "IA_NA" || t == "0") {
1210 } else if (t == "IA_TA" || t == "1") {
1212 } else if (t == "IA_PD" || t == "2") {
1214 } else if (t == "V4" || t == "3") {
1216 } else {
1217 isc_throw(BadValue, "Invalid lease type specified: "
1218 << t << ", only supported values are: IA_NA, IA_TA,"
1219 << " IA_PD and V4");
1220 }
1221 }
1222
1223 ConstElementPtr tmp = params->get("ip-address");
1224 if (tmp) {
1225 if (tmp->getType() != Element::string) {
1226 isc_throw(BadValue, "'ip-address' is not a string.");
1227 }
1228
1229 x.addr = IOAddress(tmp->stringValue());
1230
1231 if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
1232 stringstream txt;
1233 txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
1234 << " address specified: " << tmp->stringValue();
1235 isc_throw(BadValue, txt.str());
1236 }
1237
1239 return (x);
1240 }
1241
1242 tmp = params->get("subnet-id");
1243 if (!tmp) {
1244 isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
1245 }
1246 if (tmp->getType() != Element::integer) {
1247 isc_throw(BadValue, "'subnet-id' parameter is not integer.");
1248 }
1249 x.subnet_id = tmp->intValue();
1250
1251 if (params->contains("iaid")) {
1252 x.iaid = params->get("iaid")->intValue();
1253 }
1254
1255 // No address specified. Ok, so it must be identifier based query.
1256 // "identifier-type": "duid",
1257 // "identifier": "aa:bb:cc:dd:ee:..."
1258
1259 ConstElementPtr type = params->get("identifier-type");
1260 ConstElementPtr ident = params->get("identifier");
1261 if (!type || type->getType() != Element::string) {
1262 isc_throw(BadValue, "No 'ip-address' provided"
1263 " and 'identifier-type' is either missing or not a string.");
1264 }
1265 if (!ident || ident->getType() != Element::string) {
1266 isc_throw(BadValue, "No 'ip-address' provided"
1267 " and 'identifier' is either missing or not a string.");
1268 }
1269
1270 // Got the parameters. Let's see if their values make sense.
1271 // Try to convert identifier-type
1272 x.query_type = Parameters::txtToType(type->stringValue());
1273
1274 switch (x.query_type) {
1276 HWAddr hw = HWAddr::fromText(ident->stringValue());
1277 x.hwaddr = HWAddrPtr(new HWAddr(hw));
1278 break;
1279 }
1281 x.client_id = ClientId::fromText(ident->stringValue());
1282 break;
1283 }
1284 case Parameters::TYPE_DUID: {
1285 DUID duid = DUID::fromText(ident->stringValue());
1286 x.duid = DuidPtr(new DUID(duid));
1287 break;
1288 }
1289 case Parameters::TYPE_ADDR: {
1290 // We should never get here. The address clause should have been caught
1291 // earlier.
1292 return (x);
1293 }
1294 default: {
1295 isc_throw(BadValue, "Identifier type " << type->stringValue() <<
1296 " is not supported.");
1297 }
1298 }
1299
1300 return (x);
1301}
1302
1303int
1305 Parameters p;
1306 Lease4Ptr lease4;
1307 Lease6Ptr lease6;
1308 bool v4 = true;
1309 try {
1310 extractCommand(handle);
1311 v4 = (cmd_name_ == "lease4-get");
1312 p = getParameters(!v4, cmd_args_);
1313 switch (p.query_type) {
1314 case Parameters::TYPE_ADDR: {
1315 // Query by address
1316 if (v4) {
1318 } else {
1320 }
1321 break;
1322 }
1324 if (v4) {
1325 if (!p.hwaddr) {
1326 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1327 "requires hwaddr to be specified");
1328 }
1329
1331 } else {
1332 isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
1333 }
1334 break;
1335
1337 if (!v4) {
1338 if (!p.duid) {
1339 isc_throw(InvalidParameter, "Program error: Query by duid "
1340 "requires duid to be specified");
1341 }
1342
1344 p.iaid, p.subnet_id);
1345 } else {
1346 isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
1347 }
1348 break;
1349
1351 if (v4) {
1352 if (!p.client_id) {
1353 isc_throw(InvalidParameter, "Program error: Query by client-id "
1354 "requires client-id to be specified");
1355 }
1356
1358 } else {
1359 isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
1360 }
1361 break;
1362
1363 default: {
1364 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1365 break;
1366 }
1367 }
1368 } catch (const std::exception& ex) {
1370 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1371 .arg(ex.what());
1372 setErrorResponse(handle, ex.what());
1373 return (1);
1374 }
1375
1376 ElementPtr lease_json;
1377 if (v4 && lease4) {
1378 lease_json = lease4->toElement();
1380 "IPv4 lease found.", lease_json);
1381 setResponse(handle, response);
1382 } else if (!v4 && lease6) {
1383 lease_json = lease6->toElement();
1385 "IPv6 lease found.", lease_json);
1386 setResponse(handle, response);
1387 } else {
1388 // If we got here, the lease has not been found.
1389 setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
1390 }
1391
1392 return (0);
1393}
1394
1395int
1397 bool v4 = true;
1398 try {
1399 extractCommand(handle);
1400 v4 = (cmd_name_ == "lease4-get-all");
1401
1402 ElementPtr leases_json = Element::createList();
1403
1404 // The argument may contain a list of subnets for which leases should
1405 // be returned.
1406 if (cmd_args_) {
1407 ConstElementPtr subnets = cmd_args_->get("subnets");
1408 if (!subnets) {
1409 isc_throw(BadValue, "'subnets' parameter not specified");
1410 }
1411 if (subnets->getType() != Element::list) {
1412 isc_throw(BadValue, "'subnets' parameter must be a list");
1413 }
1414
1415 const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
1416 for (auto const& subnet_id : subnet_ids) {
1417 if (subnet_id->getType() != Element::integer) {
1418 isc_throw(BadValue, "listed subnet identifiers must be numbers");
1419 }
1420
1421 if (v4) {
1422 Lease4Collection leases =
1423 LeaseMgrFactory::instance().getLeases4(subnet_id->intValue());
1424 for (auto const& lease : leases) {
1425 ElementPtr lease_json = lease->toElement();
1426 leases_json->add(lease_json);
1427 }
1428 } else {
1429 Lease6Collection leases =
1430 LeaseMgrFactory::instance().getLeases6(subnet_id->intValue());
1431 for (auto const& lease : leases) {
1432 ElementPtr lease_json = lease->toElement();
1433 leases_json->add(lease_json);
1434 }
1435 }
1436 }
1437
1438 } else {
1439 // There is no 'subnets' argument so let's return all leases.
1440 if (v4) {
1442 for (auto const& lease : leases) {
1443 ElementPtr lease_json = lease->toElement();
1444 leases_json->add(lease_json);
1445 }
1446 } else {
1448 for (auto const& lease : leases) {
1449 ElementPtr lease_json = lease->toElement();
1450 leases_json->add(lease_json);
1451 }
1452 }
1453 }
1454
1455 std::ostringstream s;
1456 s << leases_json->size()
1457 << " IPv" << (v4 ? "4" : "6")
1458 << " lease(s) found.";
1460 args->set("leases", leases_json);
1461 ConstElementPtr response =
1462 createAnswer(leases_json->size() > 0 ?
1465 s.str(), args);
1466 setResponse(handle, response);
1467
1468 } catch (const std::exception& ex) {
1469 setErrorResponse(handle, ex.what());
1470 return (CONTROL_RESULT_ERROR);
1471 }
1472
1473 return (0);
1474}
1475
1476int
1478 bool v4 = true;
1479 try {
1480 extractCommand(handle);
1481 v4 = (cmd_name_ == "lease4-get-page");
1482
1483 // arguments must always be present
1484 if (!cmd_args_) {
1485 isc_throw(BadValue, "no parameters specified for the " << cmd_name_
1486 << " command");
1487 }
1488
1489 // The 'from' argument denotes from which lease we should start the
1490 // results page. The results page excludes this lease.
1491 ConstElementPtr from = cmd_args_->get("from");
1492 if (!from) {
1493 isc_throw(BadValue, "'from' parameter not specified");
1494 }
1495
1496 // The 'from' argument is a string. It may contain a 'start' keyword or
1497 // an IP address.
1498 if (from->getType() != Element::string) {
1499 isc_throw(BadValue, "'from' parameter must be a string");
1500 }
1501
1502 boost::scoped_ptr<IOAddress> from_address;
1503 try {
1504 if (from->stringValue() == "start") {
1505 from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1506
1507 } else {
1508 // Conversion of a string to an IP address may throw.
1509 from_address.reset(new IOAddress(from->stringValue()));
1510 }
1511
1512 } catch (...) {
1513 isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1514 "a valid IPv" << (v4 ? "4" : "6") << " address");
1515 }
1516
1517 // It must be either IPv4 address for lease4-get-page or IPv6 address for
1518 // lease6-get-page.
1519 if (v4 && (!from_address->isV4())) {
1520 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1521 << " is not an IPv4 address");
1522
1523 } else if (!v4 && from_address->isV4()) {
1524 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1525 << " is not an IPv6 address");
1526 }
1527
1528 // The 'limit' is a desired page size. It must always be present.
1529 ConstElementPtr page_limit = cmd_args_->get("limit");
1530 if (!page_limit) {
1531 isc_throw(BadValue, "'limit' parameter not specified");
1532 }
1533
1534 // The 'limit' must be a number.
1535 if (page_limit->getType() != Element::integer) {
1536 isc_throw(BadValue, "'limit' parameter must be a number");
1537 }
1538
1539 // Retrieve the desired page size.
1540 size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
1541
1542 ElementPtr leases_json = Element::createList();
1543
1544 if (v4) {
1545 // Get page of IPv4 leases.
1546 Lease4Collection leases =
1547 LeaseMgrFactory::instance().getLeases4(*from_address,
1548 LeasePageSize(page_limit_value));
1549
1550 // Convert leases into JSON list.
1551 for (auto const& lease : leases) {
1552 ElementPtr lease_json = lease->toElement();
1553 leases_json->add(lease_json);
1554 }
1555
1556 } else {
1557 // Get page of IPv6 leases.
1558 Lease6Collection leases =
1559 LeaseMgrFactory::instance().getLeases6(*from_address,
1560 LeasePageSize(page_limit_value));
1561 // Convert leases into JSON list.
1562 for (auto const& lease : leases) {
1563 ElementPtr lease_json = lease->toElement();
1564 leases_json->add(lease_json);
1565 }
1566 }
1567
1568 // Prepare textual status.
1569 std::ostringstream s;
1570 s << leases_json->size()
1571 << " IPv" << (v4 ? "4" : "6")
1572 << " lease(s) found.";
1574
1575 // Put gathered data into arguments map.
1576 args->set("leases", leases_json);
1577 args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1578
1579 // Create the response.
1580 ConstElementPtr response =
1581 createAnswer(leases_json->size() > 0 ?
1584 s.str(), args);
1585 setResponse(handle, response);
1586
1587 } catch (const std::exception& ex) {
1588 setErrorResponse(handle, ex.what());
1589 return (CONTROL_RESULT_ERROR);
1590 }
1591
1592 return (CONTROL_RESULT_SUCCESS);
1593}
1594
1595int
1597 bool v4 = true;
1598 try {
1599 extractCommand(handle);
1600 v4 = (cmd_name_ == "lease4-get-by-hw-address");
1601
1602 // arguments must always be present
1603 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1604 isc_throw(BadValue, "Command arguments missing or a not a map.");
1605 }
1606
1607 // the hw-address parameter is mandatory.
1608 ConstElementPtr hw_address = cmd_args_->get("hw-address");
1609 if (!hw_address) {
1610 isc_throw(BadValue, "'hw-address' parameter not specified");
1611 }
1612
1613 // The 'hw-address' argument is a string.
1614 if (hw_address->getType() != Element::string) {
1615 isc_throw(BadValue, "'hw-address' parameter must be a string");
1616 }
1617
1618 if (hw_address->stringValue().empty()) {
1619 isc_throw(BadValue, "'hw-address' parameter must not be empty");
1620 }
1621
1622 HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
1623
1624 ElementPtr leases_json = Element::createList();
1625
1626 if (v4) {
1627 Lease4Collection leases =
1629 for (auto const& lease : leases) {
1630 ElementPtr lease_json = lease->toElement();
1631 leases_json->add(lease_json);
1632 }
1633 } else {
1634 Lease6Collection leases =
1636 for (auto const& lease : leases) {
1637 ElementPtr lease_json = lease->toElement();
1638 leases_json->add(lease_json);
1639 }
1640 }
1641
1642 std::ostringstream s;
1643 s << leases_json->size()
1644 << " IPv" << (v4 ? "4" : "6")
1645 << " lease(s) found.";
1647 args->set("leases", leases_json);
1648 ConstElementPtr response =
1649 createAnswer(leases_json->size() > 0 ?
1652 s.str(), args);
1653 setResponse(handle, response);
1654
1655 } catch (const std::exception& ex) {
1656 setErrorResponse(handle, ex.what());
1657 return (CONTROL_RESULT_ERROR);
1658 }
1659
1660 return (0);
1661}
1662
1663int
1665 try {
1666 extractCommand(handle);
1667
1668 // arguments must always be present
1669 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1670 isc_throw(BadValue, "Command arguments missing or a not a map.");
1671 }
1672
1673 // the client-id parameter is mandatory.
1674 ConstElementPtr client_id = cmd_args_->get("client-id");
1675 if (!client_id) {
1676 isc_throw(BadValue, "'client-id' parameter not specified");
1677 }
1678
1679 // The 'client-id' argument is a string.
1680 if (client_id->getType() != Element::string) {
1681 isc_throw(BadValue, "'client-id' parameter must be a string");
1682 }
1683
1684 ClientIdPtr clientid = ClientId::fromText(client_id->stringValue());
1685
1686 Lease4Collection leases =
1688 ElementPtr leases_json = Element::createList();
1689 for (auto const& lease : leases) {
1690 ElementPtr lease_json = lease->toElement();
1691 leases_json->add(lease_json);
1692 }
1693
1694 std::ostringstream s;
1695 s << leases_json->size() << " IPv4 lease(s) found.";
1697 args->set("leases", leases_json);
1698 ConstElementPtr response =
1699 createAnswer(leases_json->size() > 0 ?
1702 s.str(), args);
1703 setResponse(handle, response);
1704
1705 } catch (const std::exception& ex) {
1706 setErrorResponse(handle, ex.what());
1707 return (CONTROL_RESULT_ERROR);
1708 }
1709
1710 return (0);
1711}
1712
1713int
1715 try {
1716 extractCommand(handle);
1717
1718 // arguments must always be present
1719 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1720 isc_throw(BadValue, "Command arguments missing or a not a map.");
1721 }
1722
1723 // the duid parameter is mandatory.
1724 ConstElementPtr duid = cmd_args_->get("duid");
1725 if (!duid) {
1726 isc_throw(BadValue, "'duid' parameter not specified");
1727 }
1728
1729 // The 'duid' argument is a string.
1730 if (duid->getType() != Element::string) {
1731 isc_throw(BadValue, "'duid' parameter must be a string");
1732 }
1733
1734 DUID duid_ = DUID::fromText(duid->stringValue());
1735
1736 Lease6Collection leases =
1738 ElementPtr leases_json = Element::createList();
1739 for (auto const& lease : leases) {
1740 ElementPtr lease_json = lease->toElement();
1741 leases_json->add(lease_json);
1742 }
1743
1744 std::ostringstream s;
1745 s << leases_json->size() << " IPv6 lease(s) found.";
1747 args->set("leases", leases_json);
1748 ConstElementPtr response =
1749 createAnswer(leases_json->size() > 0 ?
1752 s.str(), args);
1753 setResponse(handle, response);
1754
1755 } catch (const std::exception& ex) {
1756 setErrorResponse(handle, ex.what());
1757 return (CONTROL_RESULT_ERROR);
1758 }
1759
1760 return (0);
1761}
1762
1763int
1765 bool v4 = true;
1766 try {
1767 extractCommand(handle);
1768 v4 = (cmd_name_ == "lease4-get-by-hostname");
1769
1770 // arguments must always be present
1771 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1772 isc_throw(BadValue, "Command arguments missing or a not a map.");
1773 }
1774
1775 // the hostname parameter is mandatory.
1776 ConstElementPtr hostname = cmd_args_->get("hostname");
1777 if (!hostname) {
1778 isc_throw(BadValue, "'hostname' parameter not specified");
1779 }
1780
1781 // The 'hostname' argument is a string.
1782 if (hostname->getType() != Element::string) {
1783 isc_throw(BadValue, "'hostname' parameter must be a string");
1784 }
1785
1786 std::string hostname_ = hostname->stringValue();
1788 if (hostname_.empty()) {
1789 isc_throw(BadValue, "'hostname' parameter is empty");
1790 }
1791 boost::algorithm::to_lower(hostname_);
1792
1793 ElementPtr leases_json = Element::createList();
1794 if (v4) {
1795 Lease4Collection leases =
1797
1798 for (auto const& lease : leases) {
1799 ElementPtr lease_json = lease->toElement();
1800 leases_json->add(lease_json);
1801 }
1802 } else {
1803 Lease6Collection leases =
1805
1806 for (auto const& lease : leases) {
1807 ElementPtr lease_json = lease->toElement();
1808 leases_json->add(lease_json);
1809 }
1810 }
1811
1812 std::ostringstream s;
1813 s << leases_json->size()
1814 << " IPv" << (v4 ? "4" : "6")
1815 << " lease(s) found.";
1817 args->set("leases", leases_json);
1818 ConstElementPtr response =
1819 createAnswer(leases_json->size() > 0 ?
1822 s.str(), args);
1823 setResponse(handle, response);
1824
1825 } catch (const std::exception& ex) {
1826 setErrorResponse(handle, ex.what());
1827 return (CONTROL_RESULT_ERROR);
1828 }
1829
1830 return (0);
1831}
1832
1833int
1835 Parameters p;
1836 Lease4Ptr lease4;
1837 try {
1838 extractCommand(handle);
1839 p = getParameters(false, cmd_args_);
1840 switch (p.query_type) {
1841 case Parameters::TYPE_ADDR: {
1842 // If address was specified explicitly, let's use it as is.
1844 if (!lease4) {
1845 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1846 return (0);
1847 }
1848 break;
1849 }
1851 if (!p.hwaddr) {
1852 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1853 "requires hwaddr to be specified");
1854 }
1855
1856 // Let's see if there's such a lease at all.
1858 if (!lease4) {
1859 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1860 return (0);
1861 }
1862 break;
1863 }
1865 if (!p.client_id) {
1866 isc_throw(InvalidParameter, "Program error: Query by client-id "
1867 "requires client-id to be specified");
1868 }
1869
1870 // Let's see if there's such a lease at all.
1872 if (!lease4) {
1873 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1874 return (0);
1875 }
1876 break;
1877 }
1878 case Parameters::TYPE_DUID: {
1879 isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
1880 break;
1881 }
1882 default: {
1883 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1884 break;
1885 }
1886 }
1887
1888 if (LeaseMgrFactory::instance().deleteLease(lease4)) {
1889 setSuccessResponse(handle, "IPv4 lease deleted.");
1891 } else {
1892 setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1893 }
1894
1895 // Queue an NCR to remove DNS if configured and the lease has it.
1896 if (p.updateDDNS) {
1897 queueNCR(CHG_REMOVE, lease4);
1898 }
1899
1900 } catch (const std::exception& ex) {
1902 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1903 .arg(ex.what());
1904 setErrorResponse(handle, ex.what());
1905 return (1);
1906 }
1908 .arg(lease4->addr_.toText());
1909 return (0);
1910}
1911
1912int
1914 try {
1915 extractCommand(handle);
1916
1917 // Arguments are mandatory.
1918 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1919 isc_throw(BadValue, "Command arguments missing or a not a map.");
1920 }
1921
1922 // At least one of the 'deleted-leases' or 'leases' must be present.
1923 auto deleted_leases = cmd_args_->get("deleted-leases");
1924 auto leases = cmd_args_->get("leases");
1925
1926 if (!deleted_leases && !leases) {
1927 isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1928 " specified");
1929 }
1930
1931 // Make sure that 'deleted-leases' is a list, if present.
1932 if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1933 isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1934 }
1935
1936 // Make sure that 'leases' is a list, if present.
1937 if (leases && (leases->getType() != Element::list)) {
1938 isc_throw(BadValue, "the 'leases' parameter must be a list");
1939 }
1940
1941 // Parse deleted leases without deleting them from the database
1942 // yet. If any of the deleted leases or new leases appears to be
1943 // malformed we can easily rollback.
1944 std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1945 if (deleted_leases) {
1946 auto leases_list = deleted_leases->listValue();
1947
1948 // Iterate over leases to be deleted.
1949 for (auto const& lease_params : leases_list) {
1950 // Parsing the lease may throw and it means that the lease
1951 // information is malformed.
1952 Parameters p = getParameters(true, lease_params);
1953 auto lease = getIPv6LeaseForDelete(p);
1954 parsed_deleted_list.push_back(std::make_pair(p, lease));
1955 }
1956 }
1957
1958 // Parse new/updated leases without affecting the database to detect
1959 // any errors that should cause an error response.
1960 std::list<Lease6Ptr> parsed_leases_list;
1961 if (leases) {
1963
1964 // Iterate over all leases.
1965 auto leases_list = leases->listValue();
1966 for (auto const& lease_params : leases_list) {
1967
1968 Lease6Parser parser;
1969 bool force_update;
1970
1971 // If parsing the lease fails we throw, as it indicates that the
1972 // command is malformed.
1973 Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1974 parsed_leases_list.push_back(lease6);
1975 }
1976 }
1977
1978 // Count successful deletions and updates.
1979 size_t success_count = 0;
1980
1981 ElementPtr failed_deleted_list;
1982 if (!parsed_deleted_list.empty()) {
1983
1984 // Iterate over leases to be deleted.
1985 for (auto const& lease_params_pair : parsed_deleted_list) {
1986
1987 // This part is outside of the try-catch because an exception
1988 // indicates that the command is malformed.
1989 Parameters p = lease_params_pair.first;
1990 auto lease = lease_params_pair.second;
1991
1992 try {
1993 if (lease) {
1994 // This may throw if the lease couldn't be deleted for
1995 // any reason, but we still want to proceed with other
1996 // leases.
1997 if (LeaseMgrFactory::instance().deleteLease(lease)) {
1998 ++success_count;
2000
2001 } else {
2002 // Lazy creation of the list of leases which failed to delete.
2003 if (!failed_deleted_list) {
2004 failed_deleted_list = Element::createList();
2005 }
2006
2007 // If the lease doesn't exist we also want to put it
2008 // on the list of leases which failed to delete. That
2009 // corresponds to the lease6-del command which returns
2010 // an error when the lease doesn't exist.
2011 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
2012 p.addr, p.duid,
2014 "lease not found"));
2015 }
2016 }
2017
2018 } catch (const std::exception& ex) {
2019 // Lazy creation of the list of leases which failed to delete.
2020 if (!failed_deleted_list) {
2021 failed_deleted_list = Element::createList();
2022 }
2023 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
2024 p.addr, p.duid,
2026 ex.what()));
2027 }
2028 }
2029 }
2030
2031 // Process leases to be added or/and updated.
2032 ElementPtr failed_leases_list;
2033 if (!parsed_leases_list.empty()) {
2035
2036 // Iterate over all leases.
2037 for (auto const& lease : parsed_leases_list) {
2038
2039 auto result = CONTROL_RESULT_SUCCESS;
2040 std::ostringstream text;
2041 try {
2042 if (!MultiThreadingMgr::instance().getMode()) {
2043 // Not multi-threading.
2044 addOrUpdate6(lease, true);
2045 } else {
2046 // Multi-threading, try to lock first to avoid a race.
2047 ResourceHandler resource_handler;
2048 if (resource_handler.tryLock(lease->type_, lease->addr_)) {
2049 addOrUpdate6(lease, true);
2050 } else {
2052 "ResourceBusy: IP address:" << lease->addr_
2053 << " could not be updated.");
2054 }
2055 }
2056
2057 ++success_count;
2058 } catch (const LeaseCmdsConflict& ex) {
2059 result = CONTROL_RESULT_CONFLICT;
2060 text << ex.what();
2061
2062 } catch (const std::exception& ex) {
2063 result = CONTROL_RESULT_ERROR;
2064 text << ex.what();
2065 }
2066 // Handle an error.
2067 if (result != CONTROL_RESULT_SUCCESS) {
2068 // Lazy creation of the list of leases which failed to add/update.
2069 if (!failed_leases_list) {
2070 failed_leases_list = Element::createList();
2071 }
2072 failed_leases_list->add(createFailedLeaseMap(lease->type_,
2073 lease->addr_,
2074 lease->duid_,
2075 result,
2076 text.str()));
2077 }
2078 }
2079 }
2080
2081 // Start preparing the response.
2082 ElementPtr args;
2083
2084 if (failed_deleted_list || failed_leases_list) {
2085 // If there are any failed leases, let's include them in the response.
2086 args = Element::createMap();
2087
2088 // failed-deleted-leases
2089 if (failed_deleted_list) {
2090 args->set("failed-deleted-leases", failed_deleted_list);
2091 }
2092
2093 // failed-leases
2094 if (failed_leases_list) {
2095 args->set("failed-leases", failed_leases_list);
2096 }
2097 }
2098
2099 // Send the success response and include failed leases.
2100 std::ostringstream resp_text;
2101 resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
2102 auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
2103 CONTROL_RESULT_EMPTY, resp_text.str(), args);
2104 setResponse(handle, answer);
2105
2108 .arg(success_count);
2109
2110 } catch (const std::exception& ex) {
2111 // Unable to parse the command and similar issues.
2113 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2114 .arg(ex.what());
2115 setErrorResponse(handle, ex.what());
2116 return (CONTROL_RESULT_ERROR);
2117 }
2118
2119 return (0);
2120}
2121
2122int
2124 Parameters p;
2125 Lease6Ptr lease6;
2127 try {
2128 extractCommand(handle);
2129 p = getParameters(true, cmd_args_);
2130
2131 switch (p.query_type) {
2132 case Parameters::TYPE_ADDR: {
2133 // If address was specified explicitly, let's use it as is.
2134
2135 // Let's see if there's such a lease at all.
2137 if (!lease6) {
2138 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2139 return (0);
2140 }
2141 break;
2142 }
2144 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2145 break;
2146 }
2147 case Parameters::TYPE_DUID: {
2148 if (!p.duid) {
2149 isc_throw(InvalidParameter, "Program error: Query by duid "
2150 "requires duid to be specified");
2151 }
2152
2153 // Let's see if there's such a lease at all.
2155 p.iaid, p.subnet_id);
2156 if (!lease6) {
2157 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2158 return (0);
2159 }
2160 break;
2161 }
2162 default: {
2163 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
2164 break;
2165 }
2166 }
2167
2168 if (LeaseMgrFactory::instance().deleteLease(lease6)) {
2169 setSuccessResponse(handle, "IPv6 lease deleted.");
2171 } else {
2172 setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
2173 }
2174
2175 // Queue an NCR to remove DNS if configured and the lease has it.
2176 if (p.updateDDNS) {
2177 queueNCR(CHG_REMOVE, lease6);
2178 }
2179
2180 } catch (const std::exception& ex) {
2182 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2183 .arg(ex.what());
2184 setErrorResponse(handle, ex.what());
2185 return (1);
2186 }
2187
2189 .arg(lease6->addr_.toText());
2190 return (0);
2191}
2192
2193int
2195 try {
2196 extractCommand(handle);
2197
2198 // We need the lease to be specified.
2199 if (!cmd_args_) {
2200 isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
2201 }
2202
2203 // Get the parameters specified by the user first.
2205 Lease4Ptr lease4;
2206 Lease4Parser parser;
2207 bool force_create = false;
2208
2209 // The parser does sanity checks (if the address is in scope, if
2210 // subnet-id is valid, etc)
2211 lease4 = parser.parse(config, cmd_args_, force_create);
2212 bool added = false;
2213 if (!MultiThreadingMgr::instance().getMode()) {
2214 // Not multi-threading.
2215 added = addOrUpdate4(lease4, force_create);
2216 } else {
2217 // Multi-threading, try to lock first to avoid a race.
2218 ResourceHandler4 resource_handler;
2219 if (resource_handler.tryLock4(lease4->addr_)) {
2220 added = addOrUpdate4(lease4, force_create);
2221 } else {
2223 "ResourceBusy: IP address:" << lease4->addr_
2224 << " could not be updated.");
2225 }
2226 }
2227
2228 if (added) {
2229 setSuccessResponse(handle, "IPv4 lease added.");
2230 } else {
2231 setSuccessResponse(handle, "IPv4 lease updated.");
2232 }
2235 .arg(lease4->addr_.toText());
2236
2237 } catch (const LeaseCmdsConflict& ex) {
2239 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2240 .arg(ex.what());
2242 return (0);
2243
2244 } catch (const std::exception& ex) {
2246 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2247 .arg(ex.what());
2248 setErrorResponse(handle, ex.what());
2249 return (1);
2250 }
2251
2252 return (0);
2253}
2254
2255int
2257 try {
2258 extractCommand(handle);
2259
2260 // We need the lease to be specified.
2261 if (!cmd_args_) {
2262 isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
2263 }
2264
2265 // Get the parameters specified by the user first.
2267 Lease6Ptr lease6;
2268 Lease6Parser parser;
2269 bool force_create = false;
2270
2271 // The parser does sanity checks (if the address is in scope, if
2272 // subnet-id is valid, etc)
2273 lease6 = parser.parse(config, cmd_args_, force_create);
2274 bool added = false;
2275 if (!MultiThreadingMgr::instance().getMode()) {
2276 // Not multi-threading.
2277 added = addOrUpdate6(lease6, force_create);
2278 } else {
2279 // Multi-threading, try to lock first to avoid a race.
2280 ResourceHandler resource_handler;
2281 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
2282 added = addOrUpdate6(lease6, force_create);
2283 } else {
2285 "ResourceBusy: IP address:" << lease6->addr_
2286 << " could not be updated.");
2287 }
2288 }
2289
2290 if (added) {
2291 setSuccessResponse(handle, "IPv6 lease added.");
2292 } else {
2293 setSuccessResponse(handle, "IPv6 lease updated.");
2294 }
2297 .arg(lease6->addr_.toText());
2298
2299 } catch (const LeaseCmdsConflict& ex) {
2301 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2302 .arg(ex.what());
2304 return (0);
2305
2306 } catch (const std::exception& ex) {
2308 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2309 .arg(ex.what());
2310 setErrorResponse(handle, ex.what());
2311 return (1);
2312 }
2313
2314 return (0);
2315}
2316
2317int
2319 try {
2320 extractCommand(handle);
2321
2322 SimpleParser parser;
2323 SubnetID id = 0;
2324
2325 size_t num = 0; // number of leases deleted
2326 stringstream ids; // a text with subnet-ids being wiped
2327
2328 // The subnet-id parameter is now optional.
2329 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2330 id = parser.getUint32(cmd_args_, "subnet-id");
2331 }
2332
2333 if (id) {
2334 // Wipe a single subnet.
2336 ids << " " << id;
2337
2338 auto assigned_observation = StatsMgr::instance().getObservation(
2339 StatsMgr::generateName("subnet", id, "assigned-addresses"));
2340
2341 int64_t previous_assigned = 0;
2342
2343 if (assigned_observation) {
2344 previous_assigned = assigned_observation->getInteger().first;
2345 }
2346
2347 auto declined_observation = StatsMgr::instance().getObservation(
2348 StatsMgr::generateName("subnet", id, "declined-addresses"));
2349
2350 int64_t previous_declined = 0;
2351
2352 if (declined_observation) {
2353 previous_declined = declined_observation->getInteger().first;
2354 }
2355
2357 StatsMgr::generateName("subnet", id, "assigned-addresses"),
2358 static_cast<int64_t>(0));
2359
2361 StatsMgr::generateName("subnet", id, "declined-addresses"),
2362 static_cast<int64_t>(0));
2363
2364 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(id);
2365 if (sub) {
2366 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2367 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2368 StatsMgr::generateName("pool", pool->getID(),
2369 "assigned-addresses")));
2370 if (!StatsMgr::instance().getObservation(name_aa)) {
2371 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2372 }
2373
2374 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2375 StatsMgr::generateName("pool", pool->getID(),
2376 "declined-addresses")));
2377 if (!StatsMgr::instance().getObservation(name_da)) {
2378 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2379 }
2380 }
2381 }
2382
2383 StatsMgr::instance().addValue("assigned-addresses", -previous_assigned);
2384
2385 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2386 } else {
2387 // Wipe them all!
2389 ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
2390 const Subnet4Collection* subs = subnets->getAll();
2391
2392 // Go over all subnets and wipe leases in each of them.
2393 for (auto const& sub : *subs) {
2394 num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
2395 ids << " " << sub->getID();
2397 StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
2398 static_cast<int64_t>(0));
2399
2401 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2402 static_cast<int64_t>(0));
2403
2404 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2405 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2406 StatsMgr::generateName("pool", pool->getID(),
2407 "assigned-addresses")));
2408 if (!StatsMgr::instance().getObservation(name_aa)) {
2409 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2410 }
2411
2412 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2413 StatsMgr::generateName("pool", pool->getID(),
2414 "declined-addresses")));
2415 if (!StatsMgr::instance().getObservation(name_da)) {
2416 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2417 }
2418 }
2419 }
2420
2421 StatsMgr::instance().setValue("assigned-addresses", static_cast<int64_t>(0));
2422
2423 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2424 }
2425
2426 stringstream tmp;
2427 tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
2429 : CONTROL_RESULT_EMPTY, tmp.str());
2430 setResponse(handle, response);
2431 } catch (const std::exception& ex) {
2433 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2434 .arg(ex.what());
2435 setErrorResponse(handle, ex.what());
2436 return (1);
2437 }
2438
2440 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2441 return (0);
2442}
2443
2444int
2446 try {
2447 extractCommand(handle);
2448
2449 SimpleParser parser;
2450 SubnetID id = 0;
2451
2452 size_t num = 0; // number of leases deleted
2453 stringstream ids; // a text with subnet-ids being wiped
2454
2459
2460 // The subnet-id parameter is now optional.
2461 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2462 id = parser.getUint32(cmd_args_, "subnet-id");
2463 }
2464
2465 if (id) {
2466 // Wipe a single subnet.
2468 ids << " " << id;
2469
2470 auto assigned_na_observation = StatsMgr::instance().getObservation(
2471 StatsMgr::generateName("subnet", id, "assigned-nas"));
2472
2473 int64_t previous_assigned_na = 0;
2474
2475 if (assigned_na_observation) {
2476 previous_assigned_na = assigned_na_observation->getInteger().first;
2477 }
2478
2479 auto assigned_pd_observation = StatsMgr::instance().getObservation(
2480 StatsMgr::generateName("subnet", id, "assigned-pds"));
2481
2482 int64_t previous_assigned_pd = 0;
2483
2484 if (assigned_pd_observation) {
2485 previous_assigned_pd = assigned_pd_observation->getInteger().first;
2486 }
2487
2488 auto declined_observation = StatsMgr::instance().getObservation(
2489 StatsMgr::generateName("subnet", id, "declined-addresses"));
2490
2491 int64_t previous_declined = 0;
2492
2493 if (declined_observation) {
2494 previous_declined = declined_observation->getInteger().first;
2495 }
2496
2498 StatsMgr::generateName("subnet", id, "assigned-nas" ),
2499 static_cast<int64_t>(0));
2500
2502 StatsMgr::generateName("subnet", id, "assigned-pds"),
2503 static_cast<int64_t>(0));
2504
2506 StatsMgr::generateName("subnet", id, "declined-addresses"),
2507 static_cast<int64_t>(0));
2508
2510 StatsMgr::generateName("subnet", id, "registered-nas"),
2511 static_cast<int64_t>(0));
2512
2513 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(id);
2514 if (sub) {
2515 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2516 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2517 StatsMgr::generateName("pool", pool->getID(),
2518 "assigned-nas")));
2519 if (!StatsMgr::instance().getObservation(name_anas)) {
2520 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2521 }
2522
2523 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2524 StatsMgr::generateName("pool", pool->getID(),
2525 "declined-addresses")));
2526 if (!StatsMgr::instance().getObservation(name_da)) {
2527 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2528 }
2529 }
2530
2531 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2532 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2533 StatsMgr::generateName("pd-pool", pool->getID(),
2534 "assigned-pds")));
2535 if (!StatsMgr::instance().getObservation(name_apds)) {
2536 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2537 }
2538 }
2539 }
2540
2541 StatsMgr::instance().addValue("assigned-nas", -previous_assigned_na);
2542
2543 StatsMgr::instance().addValue("assigned-pds", -previous_assigned_pd);
2544
2545 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2546 } else {
2547 // Wipe them all!
2549 ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2550 const Subnet6Collection* subs = subnets->getAll();
2551
2552 // Go over all subnets and wipe leases in each of them.
2553 for (auto const& sub : *subs) {
2554 num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2555 ids << " " << sub->getID();
2557 StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2558 static_cast<int64_t>(0));
2559
2561 StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2562 static_cast<int64_t>(0));
2563
2565 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2566 static_cast<int64_t>(0));
2567
2569 StatsMgr::generateName("subnet", sub->getID(), "registered-nas"),
2570 static_cast<int64_t>(0));
2571
2572 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2573 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2574 StatsMgr::generateName("pool", pool->getID(),
2575 "assigned-nas")));
2576 if (!StatsMgr::instance().getObservation(name_anas)) {
2577 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2578 }
2579
2580 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2581 StatsMgr::generateName("pool", pool->getID(),
2582 "declined-addresses")));
2583 if (!StatsMgr::instance().getObservation(name_da)) {
2584 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2585 }
2586 }
2587
2588 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2589 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2590 StatsMgr::generateName("pd-pool", pool->getID(),
2591 "assigned-pds")));
2592 if (!StatsMgr::instance().getObservation(name_apds)) {
2593 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2594 }
2595 }
2596 }
2597
2598 StatsMgr::instance().setValue("assigned-nas", static_cast<int64_t>(0));
2599
2600 StatsMgr::instance().setValue("assigned-pds", static_cast<int64_t>(0));
2601
2602 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2603 }
2604
2605 stringstream tmp;
2606 tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2608 : CONTROL_RESULT_EMPTY, tmp.str());
2609 setResponse(handle, response);
2610 } catch (const std::exception& ex) {
2612 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2613 .arg(ex.what());
2614 setErrorResponse(handle, ex.what());
2615 return (1);
2616 }
2617
2619 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2620 return (0);
2621}
2622
2625 Lease6Ptr lease6;
2626
2627 switch (parameters.query_type) {
2628 case Parameters::TYPE_ADDR: {
2629 // If address was specified explicitly, let's use it as is.
2630
2631 // Let's see if there's such a lease at all.
2632 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2633 parameters.addr);
2634 if (!lease6) {
2635 lease6.reset(new Lease6());
2636 lease6->addr_ = parameters.addr;
2637 }
2638 break;
2639 }
2641 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2642 break;
2643 }
2644 case Parameters::TYPE_DUID: {
2645 if (!parameters.duid) {
2646 isc_throw(InvalidParameter, "Program error: Query by duid "
2647 "requires duid to be specified");
2648 }
2649
2650 // Let's see if there's such a lease at all.
2651 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2652 *parameters.duid,
2653 parameters.iaid,
2654 parameters.subnet_id);
2655 break;
2656 }
2657 default:
2658 isc_throw(InvalidOperation, "Unknown query type: "
2659 << static_cast<int>(parameters.query_type));
2660 }
2661
2662 return (lease6);
2663}
2664
2667 short family) const {
2668 ConstElementPtr param = params->get(name);
2669 if (!param) {
2670 isc_throw(BadValue, "'" << name << "' parameter is missing.");
2671 }
2672
2673 if (param->getType() != Element::string) {
2674 isc_throw(BadValue, "'" << name << "' is not a string.");
2675 }
2676
2677 IOAddress addr(0);
2678 try {
2679 addr = IOAddress(param->stringValue());
2680 } catch (const std::exception& ex) {
2681 isc_throw(BadValue, "'" << param->stringValue()
2682 << "' is not a valid IP address.");
2683 }
2684
2685 if (addr.getFamily() != family) {
2686 isc_throw(BadValue, "Invalid "
2687 << (family == AF_INET6 ? "IPv6" : "IPv4")
2688 << " address specified: " << param->stringValue());
2689 }
2690
2691 return (addr);
2692}
2693
2694int
2696 std::stringstream ss;
2697 int resp_code = CONTROL_RESULT_ERROR;
2698
2699 try {
2700 extractCommand(handle);
2701
2702 // Get the target lease address. Invalid value will throw.
2703 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2704
2705 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2706 ss << "DDNS updating is not enabled";
2707 resp_code = CONTROL_RESULT_CONFLICT;
2708 } else {
2709 // Find the lease.
2711 if (!lease) {
2712 ss << "No lease found for: " << addr.toText();
2713 resp_code = CONTROL_RESULT_EMPTY;
2714 } else if (lease->hostname_.empty()) {
2715 ss << "Lease for: " << addr.toText()
2716 << ", has no hostname, nothing to update";
2717 resp_code = CONTROL_RESULT_CONFLICT;
2718 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2719 ss << "Neither forward nor reverse updates enabled for lease for: "
2720 << addr.toText();
2721 resp_code = CONTROL_RESULT_CONFLICT;
2722 } else {
2723 // We have a lease with a hostname and updates in at least
2724 // one direction enabled. Queue an NCR for it.
2725 queueNCR(CHG_ADD, lease);
2726 ss << "NCR generated for: " << addr.toText()
2727 << ", hostname: " << lease->hostname_;
2728 setSuccessResponse(handle, ss.str());
2730 return (0);
2731 }
2732 }
2733 } catch (const std::exception& ex) {
2734 ss << ex.what();
2735 }
2736
2738 setErrorResponse(handle, ss.str(), resp_code);
2739 return (resp_code == CONTROL_RESULT_EMPTY || resp_code == CONTROL_RESULT_CONFLICT ? 0 : 1);
2740}
2741
2742int
2744 std::stringstream ss;
2745 int resp_code = CONTROL_RESULT_ERROR;
2746
2747 try {
2748 extractCommand(handle);
2749
2750 // Get the target lease address. Invalid value will throw.
2751 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2752
2753 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2754 ss << "DDNS updating is not enabled";
2755 resp_code = CONTROL_RESULT_CONFLICT;
2756 } else {
2757 // Find the lease.
2759 if (!lease) {
2760 ss << "No lease found for: " << addr.toText();
2761 resp_code = CONTROL_RESULT_EMPTY;
2762 } else if (lease->hostname_.empty()) {
2763 ss << "Lease for: " << addr.toText()
2764 << ", has no hostname, nothing to update";
2765 resp_code = CONTROL_RESULT_CONFLICT;
2766 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2767 ss << "Neither forward nor reverse updates enabled for lease for: "
2768 << addr.toText();
2769 resp_code = CONTROL_RESULT_CONFLICT;
2770 } else {
2771 // We have a lease with a hostname and updates in at least
2772 // one direction enabled. Queue an NCR for it.
2773 queueNCR(CHG_ADD, lease);
2774 ss << "NCR generated for: " << addr.toText()
2775 << ", hostname: " << lease->hostname_;
2776 setSuccessResponse(handle, ss.str());
2778 return (0);
2779 }
2780 }
2781 } catch (const std::exception& ex) {
2782 ss << ex.what();
2783 }
2784
2786 setErrorResponse(handle, ss.str(), resp_code);
2787 return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2788}
2789
2792 const IOAddress& lease_address,
2793 const DuidPtr& duid,
2794 const int control_result,
2795 const std::string& error_message) const {
2796 auto failed_lease_map = Element::createMap();
2797 failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2798
2799 if (!lease_address.isV6Zero()) {
2800 failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2801
2802 } else if (duid) {
2803 failed_lease_map->set("duid", Element::create(duid->toText()));
2804 }
2805
2806 // Associate the result with the lease.
2807 failed_lease_map->set("result", Element::create(control_result));
2808 failed_lease_map->set("error-message", Element::create(error_message));
2809
2810 return (failed_lease_map);
2811}
2812
2813int
2815 bool v4 = true;
2816 try {
2817 extractCommand(handle);
2818 v4 = (cmd_name_ == "lease4-write");
2819
2820 if (!cmd_args_) {
2821 isc_throw(isc::BadValue, "no parameters specified for the command");
2822 }
2823
2824 ConstElementPtr file = cmd_args_->get("filename");
2825 if (!file) {
2826 isc_throw(BadValue, "'filename' parameter not specified");
2827 }
2828 if (file->getType() != Element::string) {
2829 isc_throw(BadValue, "'filename' parameter must be a string");
2830 }
2831
2832 std::string filename;
2833 try {
2834 filename = CfgMgr::instance().validatePath(file->stringValue());
2835 } catch (const SecurityWarn& ex) {
2837 .arg(ex.what());
2838 filename = file->stringValue();
2839 } catch (const std::exception& ex) {
2840 isc_throw(BadValue, "'filename' parameter is invalid: " << ex.what());
2841 }
2842
2843 if (v4) {
2845 } else {
2847 }
2848
2849 ostringstream s;
2850 s << (v4 ? "IPv4" : "IPv6")
2851 << " lease database into '"
2852 << filename << "'.";
2854 setResponse(handle, response);
2855 } catch (const std::exception& ex) {
2856 setErrorResponse(handle, ex.what());
2857 return (CONTROL_RESULT_ERROR);
2858 }
2859
2860 return (0);
2861}
2862
2863void
2866 uint32_t offer_lifetime;
2867 callout_handle.getArgument("offer_lifetime", offer_lifetime);
2868 if (!offer_lifetime) {
2869 // Offers leases are not being persisted, nothing to do.
2870 return;
2871 }
2872
2873 // Get the remaining arguments we need.
2874 Pkt4Ptr query;
2875 Pkt4Ptr response;
2876 Lease4CollectionPtr leases;
2877
2878 callout_handle.getArgument("query4", query);
2879 callout_handle.getArgument("response4", response);
2880 callout_handle.getArgument("leases4", leases);
2881
2882 if (!leases || leases->empty() || !((*leases)[0])) {
2883 isc_throw(Unexpected, "lease4Offer - no lease!");
2884 }
2885
2886 Lease4Ptr lease = (*leases)[0];
2887 try {
2888 if (mgr->evaluateVariables(query, response, lease)) {
2890 }
2891 } catch (const NoSuchLease&) {
2892 isc_throw(LeaseCmdsConflict, "failed to update"
2893 " the lease with address " << lease->addr_ <<
2894 " either because the lease has been"
2895 " deleted or it has changed in the database");
2896 } catch (const std::exception& ex) {
2897 isc_throw(Unexpected, "evaluating binding variables failed for: "
2898 << query->getLabel() << ", :" << ex.what());
2899 }
2900}
2901
2902void
2905 Pkt4Ptr query;
2906 Pkt4Ptr response;
2907 Lease4CollectionPtr leases;
2908
2909 // Get the necessary arguments.
2910 callout_handle.getArgument("query4", query);
2911 callout_handle.getArgument("response4", response);
2912 callout_handle.getArgument("leases4", leases);
2913
2914 if (!leases) {
2915 isc_throw(Unexpected, "leases4Committed - leases is null");
2916 }
2917
2918 // In some cases we may have no lease, e.g. DHCPNAK,
2919 // or no response e.g. DHCPRELEASE.
2920 if (leases->empty() || !response || (response->getType() != DHCPACK)) {
2921 return;
2922 }
2923
2924 Lease4Ptr lease = (*leases)[0];
2925 if (!lease) {
2926 isc_throw(Unexpected, "leases4Committed - lease is null");
2927 }
2928
2929 try {
2930 if (mgr->evaluateVariables(query, response, lease)) {
2932 }
2933 } catch (const NoSuchLease&) {
2934 isc_throw(LeaseCmdsConflict, "failed to update"
2935 " the lease with address " << lease->addr_ <<
2936 " either because the lease has been"
2937 " deleted or it has changed in the database");
2938 } catch (const std::exception& ex) {
2939 isc_throw(Unexpected, "evaluating binding variables failed for: "
2940 << query->getLabel() << ", :" << ex.what());
2941 }
2942}
2943
2944void
2947 Pkt6Ptr query;
2948 Pkt6Ptr response;
2949 Lease6CollectionPtr leases;
2950
2951 // Get the necessary arguments.
2952 callout_handle.getArgument("query6", query);
2953 callout_handle.getArgument("response6", response);
2954 callout_handle.getArgument("leases6", leases);
2955
2956 if (!leases) {
2957 isc_throw(Unexpected, "leases6Committed - leases is null");
2958 }
2959
2960 // In some cases we may have no active leases or no response.
2961 if (leases->empty() || !response) {
2962 return;
2963 }
2964
2965 int attempted = 0;
2966 int failed = 0;
2967 for (auto lease : *leases) {
2968 try {
2969 if (!lease) {
2970 isc_throw(Unexpected, "leases6Committed - lease is null");
2971 }
2972
2978 // Only update a lease if its active.
2979 if (lease->valid_lft_) {
2980 ++attempted;
2981 if (mgr->evaluateVariables(query, response, lease)) {
2983 }
2984 }
2985 } catch (const NoSuchLease&) {
2986 ++failed;
2988 .arg(lease->addr_.toText())
2989 .arg(query->getLabel());
2990 } catch (const std::exception& ex) {
2991 ++failed;
2993 .arg(query->getLabel())
2994 .arg(lease->addr_.toText())
2995 .arg(ex.what());
2996 }
2997 }
2998
2999 if (failed) {
3000 isc_throw(Unexpected, failed << " out of " << attempted
3001 << " leases failed to update for "
3002 << query->getLabel());
3003 }
3004}
3005
3006int
3008 return (impl_->leaseAddHandler(handle));
3009}
3010
3011int
3013 return (impl_->lease6BulkApplyHandler(handle));
3014}
3015
3016int
3018 return (impl_->leaseGetHandler(handle));
3019}
3020
3021int
3023 return (impl_->leaseGetAllHandler(handle));
3024}
3025
3026int
3028 return (impl_->leaseGetPageHandler(handle));
3029}
3030
3031int
3033 return (impl_->leaseGetByHwAddressHandler(handle));
3034}
3035
3036int
3038 return (impl_->leaseGetByClientIdHandler(handle));
3039}
3040
3041int
3043 return (impl_->leaseGetByDuidHandler(handle));
3044}
3045
3046int
3048 return (impl_->leaseGetByHostnameHandler(handle));
3049}
3050
3051int
3053 return (impl_->lease4DelHandler(handle));
3054}
3055
3056int
3058 return (impl_->lease6DelHandler(handle));
3059}
3060
3061int
3063 return (impl_->lease4UpdateHandler(handle));
3064}
3065
3066int
3068 return (impl_->lease6UpdateHandler(handle));
3069}
3070
3071int
3074 return (impl_->lease4WipeHandler(handle));
3075}
3076
3077int
3080 return (impl_->lease6WipeHandler(handle));
3081}
3082
3083int
3085 return (impl_->lease4ResendDdnsHandler(handle));
3086}
3087
3088int
3090 return (impl_->lease6ResendDdnsHandler(handle));
3091}
3092
3093int
3095 return (impl_->leaseWriteHandler(handle));
3096}
3097
3099}
3100
3101
3102void
3105 impl_->lease4Offer(callout_handle, mgr);
3106}
3107
3108void
3111 impl_->leases4Committed(callout_handle, mgr);
3112}
3113
3114void
3117 impl_->leases6Committed(callout_handle, mgr);
3118}
3119
3120} // end of namespace lease_cmds
3121} // 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