Kea 3.2.0-git
lease_cmds.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
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
242 int
244
255 int
257
266 int
268
277 int
279
288 int
290
299 int
301
310 int
312
321 int
323
333
343
352 int
354
366 Parameters getParameters(bool v6, const ConstElementPtr& args);
367
385 Lease6Ptr getIPv6LeaseForDelete(const Parameters& parameters) const;
386
402 const IOAddress& lease_address,
403 const DuidPtr& duid,
404 const int control_result,
405 const std::string& error_message) const;
406
417 IOAddress getAddressParam(ConstElementPtr params, const std::string name,
418 short family = AF_INET) const;
427 static bool addOrUpdate4(Lease4Ptr lease, bool force_create);
428
437 static bool addOrUpdate6(Lease6Ptr lease, bool force_create);
438
443 inline static ConstElementPtr getExtendedInfo6(const Lease6Ptr& lease) {
444 ConstElementPtr user_context = lease->getContext();
445 if (!user_context || (user_context->getType() != Element::map)) {
446 return (ConstElementPtr());
447 }
448 ConstElementPtr isc = user_context->get("ISC");
449 if (!isc || (isc->getType() != Element::map)) {
450 return (ConstElementPtr());
451 }
452 return (isc->get("relay-info"));
453 }
454
468 static void lease4Offer(CalloutHandle& callout_handle,
470
482 static void leases4Committed(CalloutHandle& callout_handle,
484
496 static void leases6Committed(CalloutHandle& callout_handle,
498};
499
500bool
501LeaseCmdsImpl::addOrUpdate4(Lease4Ptr lease, bool force_create) {
502 if (lease->stateRegistered()) {
503 isc_throw(BadValue, "DHCPv4 leases do not support registered state");
504 }
505
506 Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease->addr_);
507 if (force_create && !existing) {
508 // lease does not exist
509 if (!LeaseMgrFactory::instance().addLease(lease)) {
511 "lost race between calls to get and add");
512 }
514 return (true);
515 }
516 if (existing) {
517 // Update lease current expiration time with value received from the
518 // database. Some database backends reject operations on the lease if
519 // the current expiration time value does not match what is stored.
520 Lease::syncCurrentExpirationTime(*existing, *lease);
521 }
522 try {
524 } catch (const NoSuchLease&) {
525 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
526 << lease->addr_ << " either because the lease has been "
527 "deleted or it has changed in the database, in both cases a "
528 "retry might succeed");
529 }
530
531 LeaseMgr::updateStatsOnUpdate(existing, lease);
532 return (false);
533}
534
535bool
536LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) {
537 Lease6Ptr existing =
538 LeaseMgrFactory::instance().getLease6(lease->type_, lease->addr_);
539 if (force_create && !existing) {
540 // lease does not exist
541 if (!LeaseMgrFactory::instance().addLease(lease)) {
543 "lost race between calls to get and add");
544 }
546 return (true);
547 }
548 if (existing) {
549 // Refuse used <-> registered transitions.
550 if (existing->stateRegistered() && !lease->stateRegistered()) {
551 isc_throw(BadValue, "illegal reuse of registered address "
552 << lease->addr_);
553 } else if (!existing->stateRegistered() && lease->stateRegistered()) {
554 isc_throw(BadValue, "address in use: " << lease->addr_
555 << " can't be registered");
556 }
557
558 // Update lease current expiration time with value received from the
559 // database. Some database backends reject operations on the lease if
560 // the current expiration time value does not match what is stored.
561 Lease::syncCurrentExpirationTime(*existing, *lease);
562
563 // Check what is the action about extended info.
564 ConstElementPtr old_extended_info = getExtendedInfo6(existing);
565 ConstElementPtr extended_info = getExtendedInfo6(lease);
566 if ((!old_extended_info && !extended_info) ||
567 (old_extended_info && extended_info &&
568 (*old_extended_info == *extended_info))) {
569 // Leave the default Lease6::ACTION_IGNORE.
570 } else {
571 lease->extended_info_action_ = Lease6::ACTION_UPDATE;
572 }
573 }
574 try {
576 } catch (const NoSuchLease&) {
577 isc_throw(LeaseCmdsConflict, "failed to update the lease with address "
578 << lease->addr_ << " either because the lease has been "
579 "deleted or it has changed in the database, in both cases a "
580 "retry might succeed");
581 }
582
583 LeaseMgr::updateStatsOnUpdate(existing, lease);
584 return (false);
585}
586
587int
589 // Arbitrary defaulting to DHCPv4 or with other words extractCommand
590 // below is not expected to throw...
591 bool v4 = true;
592 stringstream resp;
593 string lease_address = "unknown";
594 try {
595 extractCommand(handle);
596 v4 = (cmd_name_ == "lease4-add");
597 if (!cmd_args_) {
598 isc_throw(isc::BadValue, "no parameters specified for the command");
599 }
600
602
603 // This parameter is ignored for the commands adding the lease.
604 bool force_create = false;
605 Lease4Ptr lease4;
606 Lease6Ptr lease6;
607 if (v4) {
608 Lease4Parser parser;
609 lease4 = parser.parse(config, cmd_args_, force_create);
610 if (lease4) {
611 lease_address = lease4->addr_.toText();
612 bool success;
613 if (!MultiThreadingMgr::instance().getMode()) {
614 // Not multi-threading.
615 success = LeaseMgrFactory::instance().addLease(lease4);
616 } else {
617 // Multi-threading, try to lock first to avoid a race.
618 ResourceHandler4 resource_handler;
619 if (resource_handler.tryLock4(lease4->addr_)) {
620 success = LeaseMgrFactory::instance().addLease(lease4);
621 } else {
623 "ResourceBusy: IP address:" << lease4->addr_
624 << " could not be added.");
625 }
626 }
627
628 if (!success) {
629 isc_throw(LeaseCmdsConflict, "IPv4 lease already exists.");
630 }
631
633 resp << "Lease for address " << lease4->addr_.toText()
634 << ", subnet-id " << lease4->subnet_id_ << " added.";
635 }
636 } else {
637 Lease6Parser parser;
638 lease6 = parser.parse(config, cmd_args_, force_create);
639 if (lease6) {
640 lease_address = lease6->addr_.toText();
641 bool success;
642 if (!MultiThreadingMgr::instance().getMode()) {
643 // Not multi-threading.
644 success = LeaseMgrFactory::instance().addLease(lease6);
645 } else {
646 // Multi-threading, try to lock first to avoid a race.
647 ResourceHandler resource_handler;
648 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
649 success = LeaseMgrFactory::instance().addLease(lease6);
650 } else {
652 "ResourceBusy: IP address:" << lease6->addr_
653 << " could not be added.");
654 }
655 }
656
657 if (!success) {
658 isc_throw(LeaseCmdsConflict, "IPv6 lease already exists.");
659 }
660
662 if (lease6->type_ == Lease::TYPE_NA) {
663 resp << "Lease for address " << lease6->addr_.toText()
664 << ", subnet-id " << lease6->subnet_id_ << " added.";
665 } else {
666 resp << "Lease for prefix " << lease6->addr_.toText()
667 << "/" << static_cast<int>(lease6->prefixlen_)
668 << ", subnet-id " << lease6->subnet_id_ << " added.";
669 }
670 }
671 }
672 } catch (const LeaseCmdsConflict& ex) {
674 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
675 .arg(ex.what());
677 return (0);
678
679 } catch (const std::exception& ex) {
681 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
682 .arg(ex.what());
683 setErrorResponse(handle, ex.what());
684 return (1);
685 }
686
689 .arg(lease_address);
690 setSuccessResponse(handle, resp.str());
691 return (0);
692}
693
696 Parameters x;
697
698 if (!params || params->getType() != Element::map) {
699 isc_throw(BadValue, "Parameters missing or are not a map.");
700 }
701
702 if (params->contains("update-ddns")) {
703 ConstElementPtr tmp = params->get("update-ddns");
704 if (tmp->getType() != Element::boolean) {
705 isc_throw(BadValue, "'update-ddns' is not a boolean");
706 } else {
707 x.updateDDNS = tmp->boolValue();
708 }
709 }
710
711 // We support several sets of parameters for leaseX-get/lease-del:
712 // lease-get(type, address)
713 // lease-get(type, subnet-id, identifier-type, identifier)
714
715 if (params->contains("type")) {
716 string t = params->get("type")->stringValue();
717 if (t == "IA_NA" || t == "0") {
719 } else if (t == "IA_PD" || t == "2") {
721 } else if (t == "V4" || t == "3") {
723 } else {
724 isc_throw(BadValue, "Invalid lease type specified: " << t
725 << ", only supported values are: IA_NA, IA_PD and V4");
726 }
727 }
728
729 ConstElementPtr tmp = params->get("ip-address");
730 if (tmp) {
731 if (tmp->getType() != Element::string) {
732 isc_throw(BadValue, "'ip-address' is not a string.");
733 }
734
735 x.addr = IOAddress(tmp->stringValue());
736
737 if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
738 stringstream txt;
739 txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
740 << " address specified: " << tmp->stringValue();
741 isc_throw(BadValue, txt.str());
742 }
743
745 return (x);
746 }
747
748 tmp = params->get("subnet-id");
749 if (!tmp) {
750 isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
751 }
752 if (tmp->getType() != Element::integer) {
753 isc_throw(BadValue, "'subnet-id' parameter is not integer.");
754 }
755 x.subnet_id = tmp->intValue();
756
757 if (params->contains("iaid")) {
758 x.iaid = params->get("iaid")->intValue();
759 }
760
761 // No address specified. Ok, so it must be identifier based query.
762 // "identifier-type": "duid",
763 // "identifier": "aa:bb:cc:dd:ee:..."
764
765 ConstElementPtr type = params->get("identifier-type");
766 ConstElementPtr ident = params->get("identifier");
767 if (!type || type->getType() != Element::string) {
768 isc_throw(BadValue, "No 'ip-address' provided"
769 " and 'identifier-type' is either missing or not a string.");
770 }
771 if (!ident || ident->getType() != Element::string) {
772 isc_throw(BadValue, "No 'ip-address' provided"
773 " and 'identifier' is either missing or not a string.");
774 }
775
776 // Got the parameters. Let's see if their values make sense.
777 // Try to convert identifier-type
778 x.query_type = Parameters::txtToType(type->stringValue());
779
780 switch (x.query_type) {
782 HWAddr hw = HWAddr::fromText(ident->stringValue());
783 x.hwaddr = HWAddrPtr(new HWAddr(hw));
784 break;
785 }
787 x.client_id = ClientId::fromText(ident->stringValue());
788 break;
789 }
791 DUID duid = DUID::fromText(ident->stringValue());
792 x.duid = DuidPtr(new DUID(duid));
793 break;
794 }
796 // We should never get here. The address clause should have been caught
797 // earlier.
798 return (x);
799 }
800 default: {
801 isc_throw(BadValue, "Identifier type " << type->stringValue() <<
802 " is not supported.");
803 }
804 }
805
806 return (x);
807}
808
809int
811 Parameters p;
812 Lease4Ptr lease4;
813 Lease6Ptr lease6;
814 bool v4 = true;
815 try {
816 extractCommand(handle);
817 v4 = (cmd_name_ == "lease4-get");
818 p = getParameters(!v4, cmd_args_);
819 switch (p.query_type) {
821 // Query by address
822 if (v4) {
824 } else {
826 }
827 break;
828 }
830 if (v4) {
831 if (!p.hwaddr) {
832 isc_throw(InvalidParameter, "Program error: Query by hw-address "
833 "requires hwaddr to be specified");
834 }
835
837 } else {
838 isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
839 }
840 break;
841
843 if (!v4) {
844 if (!p.duid) {
845 isc_throw(InvalidParameter, "Program error: Query by duid "
846 "requires duid to be specified");
847 }
848
850 p.iaid, p.subnet_id);
851 } else {
852 isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
853 }
854 break;
855
857 if (v4) {
858 if (!p.client_id) {
859 isc_throw(InvalidParameter, "Program error: Query by client-id "
860 "requires client-id to be specified");
861 }
862
864 } else {
865 isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
866 }
867 break;
868
869 default: {
870 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
871 break;
872 }
873 }
874 } catch (const std::exception& ex) {
876 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
877 .arg(ex.what());
878 setErrorResponse(handle, ex.what());
879 return (1);
880 }
881
882 ElementPtr lease_json;
883 if (v4 && lease4) {
884 lease_json = lease4->toElement();
886 "IPv4 lease found.", lease_json);
887 setResponse(handle, response);
888 } else if (!v4 && lease6) {
889 lease_json = lease6->toElement();
891 "IPv6 lease found.", lease_json);
892 setResponse(handle, response);
893 } else {
894 // If we got here, the lease has not been found.
895 setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
896 }
897
898 return (0);
899}
900
901int
903 bool v4 = true;
904 try {
905 extractCommand(handle);
906 v4 = (cmd_name_ == "lease4-get-all");
907
908 ElementPtr leases_json = Element::createList();
909
910 // The argument may contain a list of subnets for which leases should
911 // be returned.
912 if (cmd_args_) {
913 ConstElementPtr subnets = cmd_args_->get("subnets");
914 if (!subnets) {
915 isc_throw(BadValue, "'subnets' parameter not specified");
916 }
917 if (subnets->getType() != Element::list) {
918 isc_throw(BadValue, "'subnets' parameter must be a list");
919 }
920
921 const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
922 for (auto const& subnet_id : subnet_ids) {
923 if (subnet_id->getType() != Element::integer) {
924 isc_throw(BadValue, "listed subnet identifiers must be numbers");
925 }
926
927 if (v4) {
928 Lease4Collection leases =
929 LeaseMgrFactory::instance().getLeases4(subnet_id->intValue());
930 for (auto const& lease : leases) {
931 ElementPtr lease_json = lease->toElement();
932 leases_json->add(lease_json);
933 }
934 } else {
935 Lease6Collection leases =
936 LeaseMgrFactory::instance().getLeases6(subnet_id->intValue());
937 for (auto const& lease : leases) {
938 ElementPtr lease_json = lease->toElement();
939 leases_json->add(lease_json);
940 }
941 }
942 }
943
944 } else {
945 // There is no 'subnets' argument so let's return all leases.
946 if (v4) {
948 for (auto const& lease : leases) {
949 ElementPtr lease_json = lease->toElement();
950 leases_json->add(lease_json);
951 }
952 } else {
954 for (auto const& lease : leases) {
955 ElementPtr lease_json = lease->toElement();
956 leases_json->add(lease_json);
957 }
958 }
959 }
960
961 std::ostringstream s;
962 s << leases_json->size()
963 << " IPv" << (v4 ? "4" : "6")
964 << " lease(s) found.";
966 args->set("leases", leases_json);
967 ConstElementPtr response =
968 createAnswer(leases_json->size() > 0 ?
971 s.str(), args);
972 setResponse(handle, response);
973
974 } catch (const std::exception& ex) {
975 setErrorResponse(handle, ex.what());
976 return (CONTROL_RESULT_ERROR);
977 }
978
979 return (0);
980}
981
982int
984 bool v4 = true;
985 try {
986 extractCommand(handle);
987 v4 = (cmd_name_ == "lease4-get-page");
988
989 // arguments must always be present
990 if (!cmd_args_) {
991 isc_throw(BadValue, "no parameters specified for the " << cmd_name_
992 << " command");
993 }
994
995 // The 'from' argument denotes from which lease we should start the
996 // results page. The results page excludes this lease.
997 ConstElementPtr from = cmd_args_->get("from");
998 if (!from) {
999 isc_throw(BadValue, "'from' parameter not specified");
1000 }
1001
1002 // The 'from' argument is a string. It may contain a 'start' keyword or
1003 // an IP address.
1004 if (from->getType() != Element::string) {
1005 isc_throw(BadValue, "'from' parameter must be a string");
1006 }
1007
1008 boost::scoped_ptr<IOAddress> from_address;
1009 try {
1010 if (from->stringValue() == "start") {
1011 from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1012
1013 } else {
1014 // Conversion of a string to an IP address may throw.
1015 from_address.reset(new IOAddress(from->stringValue()));
1016 }
1017
1018 } catch (...) {
1019 isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1020 "a valid IPv" << (v4 ? "4" : "6") << " address");
1021 }
1022
1023 // It must be either IPv4 address for lease4-get-page or IPv6 address for
1024 // lease6-get-page.
1025 if (v4 && (!from_address->isV4())) {
1026 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1027 << " is not an IPv4 address");
1028
1029 } else if (!v4 && from_address->isV4()) {
1030 isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1031 << " is not an IPv6 address");
1032 }
1033
1034 // The 'limit' is a desired page size. It must always be present.
1035 ConstElementPtr page_limit = cmd_args_->get("limit");
1036 if (!page_limit) {
1037 isc_throw(BadValue, "'limit' parameter not specified");
1038 }
1039
1040 // The 'limit' must be a number.
1041 if (page_limit->getType() != Element::integer) {
1042 isc_throw(BadValue, "'limit' parameter must be a number");
1043 }
1044
1045 // Retrieve the desired page size.
1046 size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
1047
1048 ElementPtr leases_json = Element::createList();
1049
1050 if (v4) {
1051 // Get page of IPv4 leases.
1052 Lease4Collection leases =
1053 LeaseMgrFactory::instance().getLeases4(*from_address,
1054 LeasePageSize(page_limit_value));
1055
1056 // Convert leases into JSON list.
1057 for (auto const& lease : leases) {
1058 ElementPtr lease_json = lease->toElement();
1059 leases_json->add(lease_json);
1060 }
1061
1062 } else {
1063 // Get page of IPv6 leases.
1064 Lease6Collection leases =
1065 LeaseMgrFactory::instance().getLeases6(*from_address,
1066 LeasePageSize(page_limit_value));
1067 // Convert leases into JSON list.
1068 for (auto const& lease : leases) {
1069 ElementPtr lease_json = lease->toElement();
1070 leases_json->add(lease_json);
1071 }
1072 }
1073
1074 // Prepare textual status.
1075 std::ostringstream s;
1076 s << leases_json->size()
1077 << " IPv" << (v4 ? "4" : "6")
1078 << " lease(s) found.";
1080
1081 // Put gathered data into arguments map.
1082 args->set("leases", leases_json);
1083 args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1084
1085 // Create the response.
1086 ConstElementPtr response =
1087 createAnswer(leases_json->size() > 0 ?
1090 s.str(), args);
1091 setResponse(handle, response);
1092
1093 } catch (const std::exception& ex) {
1094 setErrorResponse(handle, ex.what());
1095 return (CONTROL_RESULT_ERROR);
1096 }
1097
1098 return (CONTROL_RESULT_SUCCESS);
1099}
1100
1101int
1103 bool v4 = true;
1104 try {
1105 extractCommand(handle);
1106 v4 = (cmd_name_ == "lease4-get-by-hw-address");
1107
1108 // arguments must always be present
1109 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1110 isc_throw(BadValue, "Command arguments missing or a not a map.");
1111 }
1112
1113 // the hw-address parameter is mandatory.
1114 ConstElementPtr hw_address = cmd_args_->get("hw-address");
1115 if (!hw_address) {
1116 isc_throw(BadValue, "'hw-address' parameter not specified");
1117 }
1118
1119 // The 'hw-address' argument is a string.
1120 if (hw_address->getType() != Element::string) {
1121 isc_throw(BadValue, "'hw-address' parameter must be a string");
1122 }
1123
1124 if (hw_address->stringValue().empty()) {
1125 isc_throw(BadValue, "'hw-address' parameter must not be empty");
1126 }
1127
1128 HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
1129
1130 ElementPtr leases_json = Element::createList();
1131
1132 if (v4) {
1133 Lease4Collection leases =
1135 for (auto const& lease : leases) {
1136 ElementPtr lease_json = lease->toElement();
1137 leases_json->add(lease_json);
1138 }
1139 } else {
1140 Lease6Collection leases =
1142 for (auto const& lease : leases) {
1143 ElementPtr lease_json = lease->toElement();
1144 leases_json->add(lease_json);
1145 }
1146 }
1147
1148 std::ostringstream s;
1149 s << leases_json->size()
1150 << " IPv" << (v4 ? "4" : "6")
1151 << " lease(s) found.";
1153 args->set("leases", leases_json);
1154 ConstElementPtr response =
1155 createAnswer(leases_json->size() > 0 ?
1158 s.str(), args);
1159 setResponse(handle, response);
1160
1161 } catch (const std::exception& ex) {
1162 setErrorResponse(handle, ex.what());
1163 return (CONTROL_RESULT_ERROR);
1164 }
1165
1166 return (0);
1167}
1168
1169int
1171 try {
1172 extractCommand(handle);
1173
1174 // arguments must always be present
1175 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1176 isc_throw(BadValue, "Command arguments missing or a not a map.");
1177 }
1178
1179 // the client-id parameter is mandatory.
1180 ConstElementPtr client_id = cmd_args_->get("client-id");
1181 if (!client_id) {
1182 isc_throw(BadValue, "'client-id' parameter not specified");
1183 }
1184
1185 // The 'client-id' argument is a string.
1186 if (client_id->getType() != Element::string) {
1187 isc_throw(BadValue, "'client-id' parameter must be a string");
1188 }
1189
1190 ClientIdPtr clientid = ClientId::fromText(client_id->stringValue());
1191
1192 Lease4Collection leases =
1194 ElementPtr leases_json = Element::createList();
1195 for (auto const& lease : leases) {
1196 ElementPtr lease_json = lease->toElement();
1197 leases_json->add(lease_json);
1198 }
1199
1200 std::ostringstream s;
1201 s << leases_json->size() << " IPv4 lease(s) found.";
1203 args->set("leases", leases_json);
1204 ConstElementPtr response =
1205 createAnswer(leases_json->size() > 0 ?
1208 s.str(), args);
1209 setResponse(handle, response);
1210
1211 } catch (const std::exception& ex) {
1212 setErrorResponse(handle, ex.what());
1213 return (CONTROL_RESULT_ERROR);
1214 }
1215
1216 return (0);
1217}
1218
1219int
1221 try {
1222 extractCommand(handle);
1223
1224 // arguments must always be present
1225 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1226 isc_throw(BadValue, "Command arguments missing or a not a map.");
1227 }
1228
1229 // the duid parameter is mandatory.
1230 ConstElementPtr duid = cmd_args_->get("duid");
1231 if (!duid) {
1232 isc_throw(BadValue, "'duid' parameter not specified");
1233 }
1234
1235 // The 'duid' argument is a string.
1236 if (duid->getType() != Element::string) {
1237 isc_throw(BadValue, "'duid' parameter must be a string");
1238 }
1239
1240 DUID duid_ = DUID::fromText(duid->stringValue());
1241
1242 Lease6Collection leases =
1244 ElementPtr leases_json = Element::createList();
1245 for (auto const& lease : leases) {
1246 ElementPtr lease_json = lease->toElement();
1247 leases_json->add(lease_json);
1248 }
1249
1250 std::ostringstream s;
1251 s << leases_json->size() << " IPv6 lease(s) found.";
1253 args->set("leases", leases_json);
1254 ConstElementPtr response =
1255 createAnswer(leases_json->size() > 0 ?
1258 s.str(), args);
1259 setResponse(handle, response);
1260
1261 } catch (const std::exception& ex) {
1262 setErrorResponse(handle, ex.what());
1263 return (CONTROL_RESULT_ERROR);
1264 }
1265
1266 return (0);
1267}
1268
1269int
1271 bool v4 = true;
1272 try {
1273 extractCommand(handle);
1274 v4 = (cmd_name_ == "lease4-get-by-state");
1275
1276 // arguments must always be present
1277 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1278 isc_throw(BadValue, "Command arguments missing or a not a map.");
1279 }
1280
1281 // the state parameter is mandatory.
1282 ConstElementPtr state = cmd_args_->get("state");
1283 if (!state) {
1284 isc_throw(BadValue, "'state' parameter not specified");
1285 }
1286
1287 uint32_t state_ = 0;
1288 // We accept string (nicknames) and integer values.
1289 if (state->getType() == Element::string) {
1290 std::string state_str = state->stringValue();
1291 if (state_str.empty()) {
1292 isc_throw(BadValue, "'state' parameter is empty");
1293 } else if ((state_str == "default") || (state_str == "assigned")) {
1294 state_ = Lease::STATE_DEFAULT;;
1295 } else if (state_str == "declined") {
1296 state_ = Lease::STATE_DECLINED;
1297 } else if (state_str == "expired-reclaimed") {
1299 } else if (state_str == "released") {
1300 state_ = Lease::STATE_RELEASED;
1301 } else if (state_str == "registered") {
1302 state_ = Lease::STATE_REGISTERED;
1303 } else {
1304 isc_throw(BadValue, "'state' parameter value (" << state_str
1305 << ") is not recognized");
1306 }
1307 } else if (state->getType() == Element::integer) {
1308 state_ = state->intValue();
1309 } else {
1310 isc_throw(BadValue, "'state' parameter must be a number or a string");
1311 }
1312
1313 SubnetID subnet_id_ = 0;
1314 ConstElementPtr subnet = cmd_args_->get("subnet-id");
1315 if (subnet) {
1316 if (subnet->getType() != Element::integer) {
1317 isc_throw(BadValue, "'subnet-id' parameter must be a number");
1318 }
1319 subnet_id_ = subnet->intValue();
1320 }
1321
1322 ElementPtr leases_json = Element::createList();
1323 if (v4) {
1324 Lease4Collection leases =
1325 LeaseMgrFactory::instance().getLeases4(state_, subnet_id_);
1326
1327 for (auto const& lease : leases) {
1328 ElementPtr lease_json = lease->toElement();
1329 leases_json->add(lease_json);
1330 }
1331 } else {
1332 Lease6Collection leases =
1333 LeaseMgrFactory::instance().getLeases6(state_, subnet_id_);
1334
1335 for (auto const& lease : leases) {
1336 ElementPtr lease_json = lease->toElement();
1337 leases_json->add(lease_json);
1338 }
1339 }
1340
1341 std::ostringstream s;
1342 s << leases_json->size()
1343 << " IPv" << (v4 ? "4" : "6")
1344 << " lease(s) found with state ";
1345 if (state_ <= Lease::STATE_REGISTERED) {
1346 s << Lease::basicStatesToText(state_) << " (" << state_ << ")";
1347 } else {
1348 s << state_;
1349 }
1350 if (subnet_id_ != 0) {
1351 s << " in subnet " << subnet_id_;
1352 }
1353 s << ".";
1355 args->set("leases", leases_json);
1356 ConstElementPtr response =
1357 createAnswer(leases_json->size() > 0 ?
1360 s.str(), args);
1361 setResponse(handle, response);
1362
1363 } catch (const std::exception& ex) {
1364 setErrorResponse(handle, ex.what());
1365 return (CONTROL_RESULT_ERROR);
1366 }
1367
1368 return (0);
1369}
1370
1371int
1373 bool v4 = true;
1374 try {
1375 extractCommand(handle);
1376 v4 = (cmd_name_ == "lease4-get-by-hostname");
1377
1378 // arguments must always be present
1379 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1380 isc_throw(BadValue, "Command arguments missing or a not a map.");
1381 }
1382
1383 // the hostname parameter is mandatory.
1384 ConstElementPtr hostname = cmd_args_->get("hostname");
1385 if (!hostname) {
1386 isc_throw(BadValue, "'hostname' parameter not specified");
1387 }
1388
1389 // The 'hostname' argument is a string.
1390 if (hostname->getType() != Element::string) {
1391 isc_throw(BadValue, "'hostname' parameter must be a string");
1392 }
1393
1394 std::string hostname_ = hostname->stringValue();
1396 if (hostname_.empty()) {
1397 isc_throw(BadValue, "'hostname' parameter is empty");
1398 }
1399 boost::algorithm::to_lower(hostname_);
1400
1401 ElementPtr leases_json = Element::createList();
1402 if (v4) {
1403 Lease4Collection leases =
1405
1406 for (auto const& lease : leases) {
1407 ElementPtr lease_json = lease->toElement();
1408 leases_json->add(lease_json);
1409 }
1410 } else {
1411 Lease6Collection leases =
1413
1414 for (auto const& lease : leases) {
1415 ElementPtr lease_json = lease->toElement();
1416 leases_json->add(lease_json);
1417 }
1418 }
1419
1420 std::ostringstream s;
1421 s << leases_json->size()
1422 << " IPv" << (v4 ? "4" : "6")
1423 << " lease(s) found.";
1425 args->set("leases", leases_json);
1426 ConstElementPtr response =
1427 createAnswer(leases_json->size() > 0 ?
1430 s.str(), args);
1431 setResponse(handle, response);
1432
1433 } catch (const std::exception& ex) {
1434 setErrorResponse(handle, ex.what());
1435 return (CONTROL_RESULT_ERROR);
1436 }
1437
1438 return (0);
1439}
1440
1441int
1443 Parameters p;
1444 Lease4Ptr lease4;
1445 try {
1446 extractCommand(handle);
1447 p = getParameters(false, cmd_args_);
1448 switch (p.query_type) {
1449 case Parameters::TYPE_ADDR: {
1450 // If address was specified explicitly, let's use it as is.
1452 if (!lease4) {
1453 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1454 return (0);
1455 }
1456 break;
1457 }
1459 if (!p.hwaddr) {
1460 isc_throw(InvalidParameter, "Program error: Query by hw-address "
1461 "requires hwaddr to be specified");
1462 }
1463
1464 // Let's see if there's such a lease at all.
1466 if (!lease4) {
1467 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1468 return (0);
1469 }
1470 break;
1471 }
1473 if (!p.client_id) {
1474 isc_throw(InvalidParameter, "Program error: Query by client-id "
1475 "requires client-id to be specified");
1476 }
1477
1478 // Let's see if there's such a lease at all.
1480 if (!lease4) {
1481 setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1482 return (0);
1483 }
1484 break;
1485 }
1486 case Parameters::TYPE_DUID: {
1487 isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
1488 break;
1489 }
1490 default: {
1491 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1492 break;
1493 }
1494 }
1495
1496 if (LeaseMgrFactory::instance().deleteLease(lease4)) {
1497 setSuccessResponse(handle, "IPv4 lease deleted.");
1499 } else {
1500 setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1501 }
1502
1503 // Queue an NCR to remove DNS if configured and the lease has it.
1504 if (p.updateDDNS) {
1505 queueNCR(CHG_REMOVE, lease4);
1506 }
1507
1508 } catch (const std::exception& ex) {
1510 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1511 .arg(ex.what());
1512 setErrorResponse(handle, ex.what());
1513 return (1);
1514 }
1516 .arg(lease4->addr_.toText());
1517 return (0);
1518}
1519
1520int
1522 try {
1523 extractCommand(handle);
1524
1525 // Arguments are mandatory.
1526 if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1527 isc_throw(BadValue, "Command arguments missing or a not a map.");
1528 }
1529
1530 // At least one of the 'deleted-leases' or 'leases' must be present.
1531 auto deleted_leases = cmd_args_->get("deleted-leases");
1532 auto leases = cmd_args_->get("leases");
1533
1534 if (!deleted_leases && !leases) {
1535 isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1536 " specified");
1537 }
1538
1539 // Make sure that 'deleted-leases' is a list, if present.
1540 if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1541 isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1542 }
1543
1544 // Make sure that 'leases' is a list, if present.
1545 if (leases && (leases->getType() != Element::list)) {
1546 isc_throw(BadValue, "the 'leases' parameter must be a list");
1547 }
1548
1549 // Parse deleted leases without deleting them from the database
1550 // yet. If any of the deleted leases or new leases appears to be
1551 // malformed we can easily rollback.
1552 std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1553 if (deleted_leases) {
1554 auto leases_list = deleted_leases->listValue();
1555
1556 // Iterate over leases to be deleted.
1557 for (auto const& lease_params : leases_list) {
1558 // Parsing the lease may throw and it means that the lease
1559 // information is malformed.
1560 Parameters p = getParameters(true, lease_params);
1561 auto lease = getIPv6LeaseForDelete(p);
1562 parsed_deleted_list.push_back(std::make_pair(p, lease));
1563 }
1564 }
1565
1566 // Parse new/updated leases without affecting the database to detect
1567 // any errors that should cause an error response.
1568 std::list<Lease6Ptr> parsed_leases_list;
1569 if (leases) {
1571
1572 // Iterate over all leases.
1573 auto leases_list = leases->listValue();
1574 for (auto const& lease_params : leases_list) {
1575
1576 Lease6Parser parser;
1577 bool force_update;
1578
1579 // If parsing the lease fails we throw, as it indicates that the
1580 // command is malformed.
1581 Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1582 parsed_leases_list.push_back(lease6);
1583 }
1584 }
1585
1586 // Count successful deletions and updates.
1587 size_t success_count = 0;
1588
1589 ElementPtr failed_deleted_list;
1590 if (!parsed_deleted_list.empty()) {
1591
1592 // Iterate over leases to be deleted.
1593 for (auto const& lease_params_pair : parsed_deleted_list) {
1594
1595 // This part is outside of the try-catch because an exception
1596 // indicates that the command is malformed.
1597 Parameters p = lease_params_pair.first;
1598 auto lease = lease_params_pair.second;
1599
1600 try {
1601 if (lease) {
1602 // This may throw if the lease couldn't be deleted for
1603 // any reason, but we still want to proceed with other
1604 // leases.
1605 if (LeaseMgrFactory::instance().deleteLease(lease)) {
1606 ++success_count;
1608
1609 } else {
1610 // Lazy creation of the list of leases which failed to delete.
1611 if (!failed_deleted_list) {
1612 failed_deleted_list = Element::createList();
1613 }
1614
1615 // If the lease doesn't exist we also want to put it
1616 // on the list of leases which failed to delete. That
1617 // corresponds to the lease6-del command which returns
1618 // an error when the lease doesn't exist.
1619 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1620 p.addr, p.duid,
1622 "lease not found"));
1623 }
1624 }
1625
1626 } catch (const std::exception& ex) {
1627 // Lazy creation of the list of leases which failed to delete.
1628 if (!failed_deleted_list) {
1629 failed_deleted_list = Element::createList();
1630 }
1631 failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1632 p.addr, p.duid,
1634 ex.what()));
1635 }
1636 }
1637 }
1638
1639 // Process leases to be added or/and updated.
1640 ElementPtr failed_leases_list;
1641 if (!parsed_leases_list.empty()) {
1643
1644 // Iterate over all leases.
1645 for (auto const& lease : parsed_leases_list) {
1646
1647 auto result = CONTROL_RESULT_SUCCESS;
1648 std::ostringstream text;
1649 try {
1650 if (!MultiThreadingMgr::instance().getMode()) {
1651 // Not multi-threading.
1652 addOrUpdate6(lease, true);
1653 } else {
1654 // Multi-threading, try to lock first to avoid a race.
1655 ResourceHandler resource_handler;
1656 if (resource_handler.tryLock(lease->type_, lease->addr_)) {
1657 addOrUpdate6(lease, true);
1658 } else {
1660 "ResourceBusy: IP address:" << lease->addr_
1661 << " could not be updated.");
1662 }
1663 }
1664
1665 ++success_count;
1666 } catch (const LeaseCmdsConflict& ex) {
1667 result = CONTROL_RESULT_CONFLICT;
1668 text << ex.what();
1669
1670 } catch (const std::exception& ex) {
1671 result = CONTROL_RESULT_ERROR;
1672 text << ex.what();
1673 }
1674 // Handle an error.
1675 if (result != CONTROL_RESULT_SUCCESS) {
1676 // Lazy creation of the list of leases which failed to add/update.
1677 if (!failed_leases_list) {
1678 failed_leases_list = Element::createList();
1679 }
1680 failed_leases_list->add(createFailedLeaseMap(lease->type_,
1681 lease->addr_,
1682 lease->duid_,
1683 result,
1684 text.str()));
1685 }
1686 }
1687 }
1688
1689 // Start preparing the response.
1690 ElementPtr args;
1691
1692 if (failed_deleted_list || failed_leases_list) {
1693 // If there are any failed leases, let's include them in the response.
1694 args = Element::createMap();
1695
1696 // failed-deleted-leases
1697 if (failed_deleted_list) {
1698 args->set("failed-deleted-leases", failed_deleted_list);
1699 }
1700
1701 // failed-leases
1702 if (failed_leases_list) {
1703 args->set("failed-leases", failed_leases_list);
1704 }
1705 }
1706
1707 // Send the success response and include failed leases.
1708 std::ostringstream resp_text;
1709 resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
1710 auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
1711 CONTROL_RESULT_EMPTY, resp_text.str(), args);
1712 setResponse(handle, answer);
1713
1716 .arg(success_count);
1717
1718 } catch (const std::exception& ex) {
1719 // Unable to parse the command and similar issues.
1721 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1722 .arg(ex.what());
1723 setErrorResponse(handle, ex.what());
1724 return (CONTROL_RESULT_ERROR);
1725 }
1726
1727 return (0);
1728}
1729
1730int
1732 Parameters p;
1733 Lease6Ptr lease6;
1735 try {
1736 extractCommand(handle);
1737 p = getParameters(true, cmd_args_);
1738
1739 switch (p.query_type) {
1740 case Parameters::TYPE_ADDR: {
1741 // If address was specified explicitly, let's use it as is.
1742
1743 // Let's see if there's such a lease at all.
1745 if (!lease6) {
1746 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1747 return (0);
1748 }
1749 break;
1750 }
1752 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
1753 break;
1754 }
1755 case Parameters::TYPE_DUID: {
1756 if (!p.duid) {
1757 isc_throw(InvalidParameter, "Program error: Query by duid "
1758 "requires duid to be specified");
1759 }
1760
1761 // Let's see if there's such a lease at all.
1763 p.iaid, p.subnet_id);
1764 if (!lease6) {
1765 setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1766 return (0);
1767 }
1768 break;
1769 }
1770 default: {
1771 isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1772 break;
1773 }
1774 }
1775
1776 if (LeaseMgrFactory::instance().deleteLease(lease6)) {
1777 setSuccessResponse(handle, "IPv6 lease deleted.");
1779 } else {
1780 setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1781 }
1782
1783 // Queue an NCR to remove DNS if configured and the lease has it.
1784 if (p.updateDDNS) {
1785 queueNCR(CHG_REMOVE, lease6);
1786 }
1787
1788 } catch (const std::exception& ex) {
1790 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1791 .arg(ex.what());
1792 setErrorResponse(handle, ex.what());
1793 return (1);
1794 }
1795
1797 .arg(lease6->addr_.toText());
1798 return (0);
1799}
1800
1801int
1803 try {
1804 extractCommand(handle);
1805
1806 // We need the lease to be specified.
1807 if (!cmd_args_) {
1808 isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
1809 }
1810
1811 // Get the parameters specified by the user first.
1813 Lease4Ptr lease4;
1814 Lease4Parser parser;
1815 bool force_create = false;
1816
1817 // The parser does sanity checks (if the address is in scope, if
1818 // subnet-id is valid, etc)
1819 lease4 = parser.parse(config, cmd_args_, force_create);
1820 bool added = false;
1821 if (!MultiThreadingMgr::instance().getMode()) {
1822 // Not multi-threading.
1823 added = addOrUpdate4(lease4, force_create);
1824 } else {
1825 // Multi-threading, try to lock first to avoid a race.
1826 ResourceHandler4 resource_handler;
1827 if (resource_handler.tryLock4(lease4->addr_)) {
1828 added = addOrUpdate4(lease4, force_create);
1829 } else {
1831 "ResourceBusy: IP address:" << lease4->addr_
1832 << " could not be updated.");
1833 }
1834 }
1835
1836 if (added) {
1837 setSuccessResponse(handle, "IPv4 lease added.");
1838 } else {
1839 setSuccessResponse(handle, "IPv4 lease updated.");
1840 }
1843 .arg(lease4->addr_.toText());
1844
1845 } catch (const LeaseCmdsConflict& ex) {
1847 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1848 .arg(ex.what());
1850 return (0);
1851
1852 } catch (const std::exception& ex) {
1854 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1855 .arg(ex.what());
1856 setErrorResponse(handle, ex.what());
1857 return (1);
1858 }
1859
1860 return (0);
1861}
1862
1863int
1865 try {
1866 extractCommand(handle);
1867
1868 // We need the lease to be specified.
1869 if (!cmd_args_) {
1870 isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
1871 }
1872
1873 // Get the parameters specified by the user first.
1875 Lease6Ptr lease6;
1876 Lease6Parser parser;
1877 bool force_create = false;
1878
1879 // The parser does sanity checks (if the address is in scope, if
1880 // subnet-id is valid, etc)
1881 lease6 = parser.parse(config, cmd_args_, force_create);
1882 bool added = false;
1883 if (!MultiThreadingMgr::instance().getMode()) {
1884 // Not multi-threading.
1885 added = addOrUpdate6(lease6, force_create);
1886 } else {
1887 // Multi-threading, try to lock first to avoid a race.
1888 ResourceHandler resource_handler;
1889 if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
1890 added = addOrUpdate6(lease6, force_create);
1891 } else {
1893 "ResourceBusy: IP address:" << lease6->addr_
1894 << " could not be updated.");
1895 }
1896 }
1897
1898 if (added) {
1899 setSuccessResponse(handle, "IPv6 lease added.");
1900 } else {
1901 setSuccessResponse(handle, "IPv6 lease updated.");
1902 }
1905 .arg(lease6->addr_.toText());
1906
1907 } catch (const LeaseCmdsConflict& ex) {
1909 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1910 .arg(ex.what());
1912 return (0);
1913
1914 } catch (const std::exception& ex) {
1916 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
1917 .arg(ex.what());
1918 setErrorResponse(handle, ex.what());
1919 return (1);
1920 }
1921
1922 return (0);
1923}
1924
1925int
1927 try {
1928 extractCommand(handle);
1929
1930 SimpleParser parser;
1931 SubnetID id = 0;
1932
1933 size_t num = 0; // number of leases deleted
1934 stringstream ids; // a text with subnet-ids being wiped
1935
1936 // The subnet-id parameter is now optional.
1937 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
1938 id = parser.getUint32(cmd_args_, "subnet-id");
1939 }
1940
1941 if (id) {
1942 // Wipe a single subnet.
1944 ids << " " << id;
1945
1946 auto assigned_observation = StatsMgr::instance().getObservation(
1947 StatsMgr::generateName("subnet", id, "assigned-addresses"));
1948
1949 int64_t previous_assigned = 0;
1950
1951 if (assigned_observation) {
1952 previous_assigned = assigned_observation->getInteger().first;
1953 }
1954
1955 auto declined_observation = StatsMgr::instance().getObservation(
1956 StatsMgr::generateName("subnet", id, "declined-addresses"));
1957
1958 int64_t previous_declined = 0;
1959
1960 if (declined_observation) {
1961 previous_declined = declined_observation->getInteger().first;
1962 }
1963
1965 StatsMgr::generateName("subnet", id, "assigned-addresses"),
1966 static_cast<int64_t>(0));
1967
1969 StatsMgr::generateName("subnet", id, "declined-addresses"),
1970 static_cast<int64_t>(0));
1971
1972 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(id);
1973 if (sub) {
1974 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
1975 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
1976 StatsMgr::generateName("pool", pool->getID(),
1977 "assigned-addresses")));
1978 if (!StatsMgr::instance().getObservation(name_aa)) {
1979 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
1980 }
1981
1982 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
1983 StatsMgr::generateName("pool", pool->getID(),
1984 "declined-addresses")));
1985 if (!StatsMgr::instance().getObservation(name_da)) {
1986 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
1987 }
1988 }
1989 }
1990
1991 StatsMgr::instance().addValue("assigned-addresses", -previous_assigned);
1992
1993 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
1994 } else {
1995 // Wipe them all!
1997 ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
1998 const Subnet4Collection* subs = subnets->getAll();
1999
2000 // Go over all subnets and wipe leases in each of them.
2001 for (auto const& sub : *subs) {
2002 num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
2003 ids << " " << sub->getID();
2005 StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
2006 static_cast<int64_t>(0));
2007
2009 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2010 static_cast<int64_t>(0));
2011
2012 for (auto const& pool : sub->getPools(Lease::TYPE_V4)) {
2013 const std::string& name_aa(StatsMgr::generateName("subnet", sub->getID(),
2014 StatsMgr::generateName("pool", pool->getID(),
2015 "assigned-addresses")));
2016 if (!StatsMgr::instance().getObservation(name_aa)) {
2017 StatsMgr::instance().setValue(name_aa, static_cast<int64_t>(0));
2018 }
2019
2020 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2021 StatsMgr::generateName("pool", pool->getID(),
2022 "declined-addresses")));
2023 if (!StatsMgr::instance().getObservation(name_da)) {
2024 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2025 }
2026 }
2027 }
2028
2029 StatsMgr::instance().setValue("assigned-addresses", static_cast<int64_t>(0));
2030
2031 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2032 }
2033
2034 stringstream tmp;
2035 tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
2037 : CONTROL_RESULT_EMPTY, tmp.str());
2038 setResponse(handle, response);
2039 } catch (const std::exception& ex) {
2041 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2042 .arg(ex.what());
2043 setErrorResponse(handle, ex.what());
2044 return (1);
2045 }
2046
2048 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2049 return (0);
2050}
2051
2052int
2054 try {
2055 extractCommand(handle);
2056
2057 SimpleParser parser;
2058 SubnetID id = 0;
2059
2060 size_t num = 0; // number of leases deleted
2061 stringstream ids; // a text with subnet-ids being wiped
2062
2067
2068 // The subnet-id parameter is now optional.
2069 if (cmd_args_ && cmd_args_->contains("subnet-id")) {
2070 id = parser.getUint32(cmd_args_, "subnet-id");
2071 }
2072
2073 if (id) {
2074 // Wipe a single subnet.
2076 ids << " " << id;
2077
2078 auto assigned_na_observation = StatsMgr::instance().getObservation(
2079 StatsMgr::generateName("subnet", id, "assigned-nas"));
2080
2081 int64_t previous_assigned_na = 0;
2082
2083 if (assigned_na_observation) {
2084 previous_assigned_na = assigned_na_observation->getInteger().first;
2085 }
2086
2087 auto assigned_pd_observation = StatsMgr::instance().getObservation(
2088 StatsMgr::generateName("subnet", id, "assigned-pds"));
2089
2090 int64_t previous_assigned_pd = 0;
2091
2092 if (assigned_pd_observation) {
2093 previous_assigned_pd = assigned_pd_observation->getInteger().first;
2094 }
2095
2096 auto declined_observation = StatsMgr::instance().getObservation(
2097 StatsMgr::generateName("subnet", id, "declined-addresses"));
2098
2099 int64_t previous_declined = 0;
2100
2101 if (declined_observation) {
2102 previous_declined = declined_observation->getInteger().first;
2103 }
2104
2106 StatsMgr::generateName("subnet", id, "assigned-nas" ),
2107 static_cast<int64_t>(0));
2108
2110 StatsMgr::generateName("subnet", id, "assigned-pds"),
2111 static_cast<int64_t>(0));
2112
2114 StatsMgr::generateName("subnet", id, "declined-addresses"),
2115 static_cast<int64_t>(0));
2116
2118 StatsMgr::generateName("subnet", id, "registered-nas"),
2119 static_cast<int64_t>(0));
2120
2121 auto const& sub = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(id);
2122 if (sub) {
2123 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2124 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2125 StatsMgr::generateName("pool", pool->getID(),
2126 "assigned-nas")));
2127 if (!StatsMgr::instance().getObservation(name_anas)) {
2128 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2129 }
2130
2131 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2132 StatsMgr::generateName("pool", pool->getID(),
2133 "declined-addresses")));
2134 if (!StatsMgr::instance().getObservation(name_da)) {
2135 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2136 }
2137 }
2138
2139 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2140 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2141 StatsMgr::generateName("pd-pool", pool->getID(),
2142 "assigned-pds")));
2143 if (!StatsMgr::instance().getObservation(name_apds)) {
2144 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2145 }
2146 }
2147 }
2148
2149 StatsMgr::instance().addValue("assigned-nas", -previous_assigned_na);
2150
2151 StatsMgr::instance().addValue("assigned-pds", -previous_assigned_pd);
2152
2153 StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2154 } else {
2155 // Wipe them all!
2157 ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2158 const Subnet6Collection* subs = subnets->getAll();
2159
2160 // Go over all subnets and wipe leases in each of them.
2161 for (auto const& sub : *subs) {
2162 num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2163 ids << " " << sub->getID();
2165 StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2166 static_cast<int64_t>(0));
2167
2169 StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2170 static_cast<int64_t>(0));
2171
2173 StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2174 static_cast<int64_t>(0));
2175
2177 StatsMgr::generateName("subnet", sub->getID(), "registered-nas"),
2178 static_cast<int64_t>(0));
2179
2180 for (auto const& pool : sub->getPools(Lease::TYPE_NA)) {
2181 const std::string& name_anas(StatsMgr::generateName("subnet", sub->getID(),
2182 StatsMgr::generateName("pool", pool->getID(),
2183 "assigned-nas")));
2184 if (!StatsMgr::instance().getObservation(name_anas)) {
2185 StatsMgr::instance().setValue(name_anas, static_cast<int64_t>(0));
2186 }
2187
2188 const std::string& name_da(StatsMgr::generateName("subnet", sub->getID(),
2189 StatsMgr::generateName("pool", pool->getID(),
2190 "declined-addresses")));
2191 if (!StatsMgr::instance().getObservation(name_da)) {
2192 StatsMgr::instance().setValue(name_da, static_cast<int64_t>(0));
2193 }
2194 }
2195
2196 for (auto const& pool : sub->getPools(Lease::TYPE_PD)) {
2197 const std::string& name_apds(StatsMgr::generateName("subnet", sub->getID(),
2198 StatsMgr::generateName("pd-pool", pool->getID(),
2199 "assigned-pds")));
2200 if (!StatsMgr::instance().getObservation(name_apds)) {
2201 StatsMgr::instance().setValue(name_apds, static_cast<int64_t>(0));
2202 }
2203 }
2204 }
2205
2206 StatsMgr::instance().setValue("assigned-nas", static_cast<int64_t>(0));
2207
2208 StatsMgr::instance().setValue("assigned-pds", static_cast<int64_t>(0));
2209
2210 StatsMgr::instance().setValue("declined-addresses", static_cast<int64_t>(0));
2211 }
2212
2213 stringstream tmp;
2214 tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2216 : CONTROL_RESULT_EMPTY, tmp.str());
2217 setResponse(handle, response);
2218 } catch (const std::exception& ex) {
2220 .arg(cmd_args_ ? cmd_args_->str() : "<no args>")
2221 .arg(ex.what());
2222 setErrorResponse(handle, ex.what());
2223 return (1);
2224 }
2225
2227 .arg(cmd_args_ ? cmd_args_->str() : "<no args>");
2228 return (0);
2229}
2230
2233 Lease6Ptr lease6;
2234
2235 switch (parameters.query_type) {
2236 case Parameters::TYPE_ADDR: {
2237 // If address was specified explicitly, let's use it as is.
2238
2239 // Let's see if there's such a lease at all.
2240 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2241 parameters.addr);
2242 if (!lease6) {
2243 lease6.reset(new Lease6());
2244 lease6->addr_ = parameters.addr;
2245 }
2246 break;
2247 }
2249 isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2250 break;
2251 }
2252 case Parameters::TYPE_DUID: {
2253 if (!parameters.duid) {
2254 isc_throw(InvalidParameter, "Program error: Query by duid "
2255 "requires duid to be specified");
2256 }
2257
2258 // Let's see if there's such a lease at all.
2259 lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2260 *parameters.duid,
2261 parameters.iaid,
2262 parameters.subnet_id);
2263 break;
2264 }
2265 default:
2266 isc_throw(InvalidOperation, "Unknown query type: "
2267 << static_cast<int>(parameters.query_type));
2268 }
2269
2270 return (lease6);
2271}
2272
2275 short family) const {
2276 ConstElementPtr param = params->get(name);
2277 if (!param) {
2278 isc_throw(BadValue, "'" << name << "' parameter is missing.");
2279 }
2280
2281 if (param->getType() != Element::string) {
2282 isc_throw(BadValue, "'" << name << "' is not a string.");
2283 }
2284
2285 IOAddress addr(0);
2286 try {
2287 addr = IOAddress(param->stringValue());
2288 } catch (const std::exception& ex) {
2289 isc_throw(BadValue, "'" << param->stringValue()
2290 << "' is not a valid IP address.");
2291 }
2292
2293 if (addr.getFamily() != family) {
2294 isc_throw(BadValue, "Invalid "
2295 << (family == AF_INET6 ? "IPv6" : "IPv4")
2296 << " address specified: " << param->stringValue());
2297 }
2298
2299 return (addr);
2300}
2301
2302int
2304 std::stringstream ss;
2305 int resp_code = CONTROL_RESULT_ERROR;
2306
2307 try {
2308 extractCommand(handle);
2309
2310 // Get the target lease address. Invalid value will throw.
2311 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2312
2313 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2314 ss << "DDNS updating is not enabled";
2315 resp_code = CONTROL_RESULT_CONFLICT;
2316 } else {
2317 // Find the lease.
2319 if (!lease) {
2320 ss << "No lease found for: " << addr.toText();
2321 resp_code = CONTROL_RESULT_EMPTY;
2322 } else if (lease->hostname_.empty()) {
2323 ss << "Lease for: " << addr.toText()
2324 << ", has no hostname, nothing to update";
2325 resp_code = CONTROL_RESULT_CONFLICT;
2326 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2327 ss << "Neither forward nor reverse updates enabled for lease for: "
2328 << addr.toText();
2329 resp_code = CONTROL_RESULT_CONFLICT;
2330 } else {
2331 // We have a lease with a hostname and updates in at least
2332 // one direction enabled. Queue an NCR for it.
2333 queueNCR(CHG_ADD, lease);
2334 ss << "NCR generated for: " << addr.toText()
2335 << ", hostname: " << lease->hostname_;
2336 setSuccessResponse(handle, ss.str());
2338 return (0);
2339 }
2340 }
2341 } catch (const std::exception& ex) {
2342 ss << ex.what();
2343 }
2344
2346 setErrorResponse(handle, ss.str(), resp_code);
2347 return (resp_code == CONTROL_RESULT_EMPTY || resp_code == CONTROL_RESULT_CONFLICT ? 0 : 1);
2348}
2349
2350int
2352 std::stringstream ss;
2353 int resp_code = CONTROL_RESULT_ERROR;
2354
2355 try {
2356 extractCommand(handle);
2357
2358 // Get the target lease address. Invalid value will throw.
2359 IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2360
2361 if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2362 ss << "DDNS updating is not enabled";
2363 resp_code = CONTROL_RESULT_CONFLICT;
2364 } else {
2365 // Find the lease.
2367 if (!lease) {
2368 ss << "No lease found for: " << addr.toText();
2369 resp_code = CONTROL_RESULT_EMPTY;
2370 } else if (lease->hostname_.empty()) {
2371 ss << "Lease for: " << addr.toText()
2372 << ", has no hostname, nothing to update";
2373 resp_code = CONTROL_RESULT_CONFLICT;
2374 } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2375 ss << "Neither forward nor reverse updates enabled for lease for: "
2376 << addr.toText();
2377 resp_code = CONTROL_RESULT_CONFLICT;
2378 } else {
2379 // We have a lease with a hostname and updates in at least
2380 // one direction enabled. Queue an NCR for it.
2381 queueNCR(CHG_ADD, lease);
2382 ss << "NCR generated for: " << addr.toText()
2383 << ", hostname: " << lease->hostname_;
2384 setSuccessResponse(handle, ss.str());
2386 return (0);
2387 }
2388 }
2389 } catch (const std::exception& ex) {
2390 ss << ex.what();
2391 }
2392
2394 setErrorResponse(handle, ss.str(), resp_code);
2395 return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2396}
2397
2400 const IOAddress& lease_address,
2401 const DuidPtr& duid,
2402 const int control_result,
2403 const std::string& error_message) const {
2404 auto failed_lease_map = Element::createMap();
2405 failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2406
2407 if (!lease_address.isV6Zero()) {
2408 failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2409
2410 } else if (duid) {
2411 failed_lease_map->set("duid", Element::create(duid->toText()));
2412 }
2413
2414 // Associate the result with the lease.
2415 failed_lease_map->set("result", Element::create(control_result));
2416 failed_lease_map->set("error-message", Element::create(error_message));
2417
2418 return (failed_lease_map);
2419}
2420
2421int
2423 bool v4 = true;
2424 try {
2425 extractCommand(handle);
2426 v4 = (cmd_name_ == "lease4-write");
2427
2428 if (!cmd_args_) {
2429 isc_throw(isc::BadValue, "no parameters specified for the command");
2430 }
2431
2432 ConstElementPtr file = cmd_args_->get("filename");
2433 if (!file) {
2434 isc_throw(BadValue, "'filename' parameter not specified");
2435 }
2436 if (file->getType() != Element::string) {
2437 isc_throw(BadValue, "'filename' parameter must be a string");
2438 }
2439
2440 std::string filename;
2441 try {
2442 filename = CfgMgr::instance().validatePath(file->stringValue());
2443 } catch (const SecurityWarn& ex) {
2445 .arg(ex.what());
2446 filename = file->stringValue();
2447 } catch (const std::exception& ex) {
2448 isc_throw(BadValue, "'filename' parameter is invalid: " << ex.what());
2449 }
2450
2451 if (v4) {
2453 } else {
2455 }
2456
2457 ostringstream s;
2458 s << (v4 ? "IPv4" : "IPv6")
2459 << " lease database into '"
2460 << filename << "'.";
2462 setResponse(handle, response);
2463 } catch (const std::exception& ex) {
2464 setErrorResponse(handle, ex.what());
2465 return (CONTROL_RESULT_ERROR);
2466 }
2467
2468 return (0);
2469}
2470
2471void
2474 uint32_t offer_lifetime;
2475 callout_handle.getArgument("offer_lifetime", offer_lifetime);
2476 if (!offer_lifetime) {
2477 // Offers leases are not being persisted, nothing to do.
2478 return;
2479 }
2480
2481 // Get the remaining arguments we need.
2482 Pkt4Ptr query;
2483 Pkt4Ptr response;
2484 Lease4CollectionPtr leases;
2485
2486 callout_handle.getArgument("query4", query);
2487 callout_handle.getArgument("response4", response);
2488 callout_handle.getArgument("leases4", leases);
2489
2490 if (!leases || leases->empty() || !((*leases)[0])) {
2491 isc_throw(Unexpected, "lease4Offer - no lease!");
2492 }
2493
2494 Lease4Ptr lease = (*leases)[0];
2495 try {
2496 if (mgr->evaluateVariables(query, response, lease)) {
2498 }
2499 } catch (const NoSuchLease&) {
2500 isc_throw(LeaseCmdsConflict, "failed to update"
2501 " the lease with address " << lease->addr_ <<
2502 " either because the lease has been"
2503 " deleted or it has changed in the database");
2504 } catch (const std::exception& ex) {
2505 isc_throw(Unexpected, "evaluating binding variables failed for: "
2506 << query->getLabel() << ", :" << ex.what());
2507 }
2508}
2509
2510void
2513 Pkt4Ptr query;
2514 Pkt4Ptr response;
2515 Lease4CollectionPtr leases;
2516
2517 // Get the necessary arguments.
2518 callout_handle.getArgument("query4", query);
2519 callout_handle.getArgument("response4", response);
2520 callout_handle.getArgument("leases4", leases);
2521
2522 if (!leases) {
2523 isc_throw(Unexpected, "leases4Committed - leases is null");
2524 }
2525
2526 // In some cases we may have no lease, e.g. DHCPNAK,
2527 // or no response e.g. DHCPRELEASE.
2528 if (leases->empty() || !response || (response->getType() != DHCPACK)) {
2529 return;
2530 }
2531
2532 Lease4Ptr lease = (*leases)[0];
2533 if (!lease) {
2534 isc_throw(Unexpected, "leases4Committed - lease is null");
2535 }
2536
2537 try {
2538 if (mgr->evaluateVariables(query, response, lease)) {
2540 }
2541 } catch (const NoSuchLease&) {
2542 isc_throw(LeaseCmdsConflict, "failed to update"
2543 " the lease with address " << lease->addr_ <<
2544 " either because the lease has been"
2545 " deleted or it has changed in the database");
2546 } catch (const std::exception& ex) {
2547 isc_throw(Unexpected, "evaluating binding variables failed for: "
2548 << query->getLabel() << ", :" << ex.what());
2549 }
2550}
2551
2552void
2555 Pkt6Ptr query;
2556 Pkt6Ptr response;
2557 Lease6CollectionPtr leases;
2558
2559 // Get the necessary arguments.
2560 callout_handle.getArgument("query6", query);
2561 callout_handle.getArgument("response6", response);
2562 callout_handle.getArgument("leases6", leases);
2563
2564 if (!leases) {
2565 isc_throw(Unexpected, "leases6Committed - leases is null");
2566 }
2567
2568 // In some cases we may have no active leases or no response.
2569 if (leases->empty() || !response) {
2570 return;
2571 }
2572
2573 int attempted = 0;
2574 int failed = 0;
2575 for (auto lease : *leases) {
2576 try {
2577 if (!lease) {
2578 isc_throw(Unexpected, "leases6Committed - lease is null");
2579 }
2580
2586 // Only update a lease if its active.
2587 if (lease->valid_lft_) {
2588 ++attempted;
2589 if (mgr->evaluateVariables(query, response, lease)) {
2591 }
2592 }
2593 } catch (const NoSuchLease&) {
2594 ++failed;
2596 .arg(lease->addr_.toText())
2597 .arg(query->getLabel());
2598 } catch (const std::exception& ex) {
2599 ++failed;
2601 .arg(query->getLabel())
2602 .arg(lease->addr_.toText())
2603 .arg(ex.what());
2604 }
2605 }
2606
2607 if (failed) {
2608 isc_throw(Unexpected, failed << " out of " << attempted
2609 << " leases failed to update for "
2610 << query->getLabel());
2611 }
2612}
2613
2614int
2616 return (impl_->leaseAddHandler(handle));
2617}
2618
2619int
2621 return (impl_->lease6BulkApplyHandler(handle));
2622}
2623
2624int
2626 return (impl_->leaseGetHandler(handle));
2627}
2628
2629int
2631 return (impl_->leaseGetAllHandler(handle));
2632}
2633
2634int
2636 return (impl_->leaseGetPageHandler(handle));
2637}
2638
2639int
2641 return (impl_->leaseGetByHwAddressHandler(handle));
2642}
2643
2644int
2646 return (impl_->leaseGetByClientIdHandler(handle));
2647}
2648
2649int
2651 return (impl_->leaseGetByDuidHandler(handle));
2652}
2653
2654int
2656 return (impl_->leaseGetByStateHandler(handle));
2657}
2658
2659int
2661 return (impl_->leaseGetByHostnameHandler(handle));
2662}
2663
2664int
2666 return (impl_->lease4DelHandler(handle));
2667}
2668
2669int
2671 return (impl_->lease6DelHandler(handle));
2672}
2673
2674int
2676 return (impl_->lease4UpdateHandler(handle));
2677}
2678
2679int
2681 return (impl_->lease6UpdateHandler(handle));
2682}
2683
2684int
2687 return (impl_->lease4WipeHandler(handle));
2688}
2689
2690int
2693 return (impl_->lease6WipeHandler(handle));
2694}
2695
2696int
2698 return (impl_->lease4ResendDdnsHandler(handle));
2699}
2700
2701int
2703 return (impl_->lease6ResendDdnsHandler(handle));
2704}
2705
2706int
2708 return (impl_->leaseWriteHandler(handle));
2709}
2710
2712}
2713
2714
2715void
2718 impl_->lease4Offer(callout_handle, mgr);
2719}
2720
2721void
2724 impl_->leases4Committed(callout_handle, mgr);
2725}
2726
2727void
2730 impl_->leases6Committed(callout_handle, mgr);
2731}
2732
2733} // end of namespace lease_cmds
2734} // 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())
Create a NullElement.
Definition data.cc:299
@ map
Definition data.h:160
@ integer
Definition data.h:153
@ boolean
Definition data.h:155
@ list
Definition data.h:159
@ string
Definition data.h:157
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:349
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 DHCP data.
Definition cfgmgr.cc:40
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Definition duid.cc:73
Holds DUID (DHCPv6 Unique Identifier).
Definition duid.h:142
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual size_t wipeLeases6(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
static void updateStatsOnAdd(const Lease4Ptr &lease)
Update in-memory stats when adding a v4 lease.
virtual Lease4Collection getLeases4(SubnetID subnet_id) const =0
Returns all IPv4 leases for the particular subnet identifier.
virtual void writeLeases6(const std::string &filename)=0
Write V6 leases to a file.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
static void updateStatsOnUpdate(const Lease4Ptr &existing, const Lease4Ptr &lease)
Update in-memory stats when updating a v4 lease.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual size_t wipeLeases4(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual void writeLeases4(const std::string &filename)=0
Write V4 leases to a file.
static void updateStatsOnDelete(const Lease4Ptr &lease)
Update in-memory stats when deleting a v4 lease.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
Wraps value holding size of the page with leases.
Definition lease_mgr.h: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.
ElementPtr createFailedLeaseMap(const Lease::Type &lease_type, const IOAddress &lease_address, const DuidPtr &duid, const int control_result, const std::string &error_message) const
Returns a map holding brief information about a lease which failed to be deleted, updated or added.
int leaseGetByStateHandler(hooks::CalloutHandle &handle)
lease4-get-by-state and lease6-get-by-state commands handler
static bool addOrUpdate6(Lease6Ptr lease, bool force_create)
Add or update lease.
int lease6BulkApplyHandler(CalloutHandle &handle)
lease6-bulk-apply command handler
int leaseGetByDuidHandler(hooks::CalloutHandle &handle)
lease6-get-by-duid command handler
int lease6UpdateHandler(CalloutHandle &handle)
lease6-update handler
int leaseGetPageHandler(hooks::CalloutHandle &handle)
lease4-get-page, lease6-get-page commands handler
Lease6Ptr getIPv6LeaseForDelete(const Parameters &parameters) const
Convenience function fetching IPv6 address to be used to delete a lease.
int leaseGetByHostnameHandler(hooks::CalloutHandle &handle)
lease4-get-by-hostname and lease6-get-by-hostname commands handler
int lease6DelHandler(CalloutHandle &handle)
lease6-del command handler
int leaseGetByHwAddressHandler(hooks::CalloutHandle &handle)
lease4-get-by-hw-address, lease6-get-by-hw-address command handler
static ConstElementPtr getExtendedInfo6(const Lease6Ptr &lease)
Get DHCPv6 extended info.
int leaseGetHandler(CalloutHandle &handle)
lease4-get, lease6-get command handler
static bool addOrUpdate4(Lease4Ptr lease, bool force_create)
Add or update lease.
static void leases4Committed(CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases4_committed hookpoint handler.
int lease6WipeHandler(CalloutHandle &handle)
lease6-wipe handler
int leaseGetByClientIdHandler(hooks::CalloutHandle &handle)
lease4-get-by-client-id command handler
int lease6ResendDdnsHandler(CalloutHandle &handle)
lease6-resend-ddns handler
int leaseAddHandler(CalloutHandle &handle)
lease4-add, lease6-add command handler
int lease4ResendDdnsHandler(CalloutHandle &handle)
lease4-resend-ddns handler
Parameters getParameters(bool v6, const ConstElementPtr &args)
Extracts parameters required for reservation-get and reservation-del.
static void leases6Committed(CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases6_committed hookpoint handler.
int lease4UpdateHandler(CalloutHandle &handle)
lease4-update handler
int lease4WipeHandler(CalloutHandle &handle)
lease4-wipe handler
int leaseGetAllHandler(CalloutHandle &handle)
lease4-get-all, lease6-get-all commands handler
int leaseWriteHandler(CalloutHandle &handle)
lease4-write handler, lease6-write handler
int lease4ResendDdnsHandler(hooks::CalloutHandle &handle)
lease4-resend-ddns command handler
int leaseGetByStateHandler(hooks::CalloutHandle &handle)
lease4-get-by-state and lease6-get-by-state commands handler
int lease6WipeHandler(hooks::CalloutHandle &handle)
lease6-wipe handler
int leaseGetPageHandler(hooks::CalloutHandle &handle)
lease4-get-page, lease6-get-page commands handler
int lease6DelHandler(hooks::CalloutHandle &handle)
lease6-del command handler
int leaseGetAllHandler(hooks::CalloutHandle &handle)
lease4-get-all, lease6-get-all commands handler
int leaseGetByHostnameHandler(hooks::CalloutHandle &handle)
lease4-get-by-hostname and lease6-get-by-hostname commands handler
void leases4Committed(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases4_committed hookpoint handler.
int lease4DelHandler(hooks::CalloutHandle &handle)
lease4-del command handler
int leaseWriteHandler(hooks::CalloutHandle &handle)
lease4-write handler, lease6-write handler
int leaseAddHandler(hooks::CalloutHandle &handle)
lease4-add, lease6-add command handler
int leaseGetByClientIdHandler(hooks::CalloutHandle &handle)
lease4-get-by-client-id command handler
void lease4Offer(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
lease4_offer hookpoint handler.
int lease4UpdateHandler(hooks::CalloutHandle &handle)
lease4-update handler
int leaseGetHandler(hooks::CalloutHandle &handle)
lease4-get, lease6-get command handler
int leaseGetByHwAddressHandler(hooks::CalloutHandle &handle)
lease4-get-by-hw-address, lease6-get-by-hw-address command handler
int lease6UpdateHandler(hooks::CalloutHandle &handle)
lease6-update handler
void leases6Committed(hooks::CalloutHandle &callout_handle, BindingVariableMgrPtr mgr)
leases6_committed hookpoint handler.
int leaseGetByDuidHandler(hooks::CalloutHandle &handle)
lease6-get-by-duid command handler
int lease6BulkApplyHandler(hooks::CalloutHandle &handle)
lease6-bulk-apply command handler
int lease4WipeHandler(hooks::CalloutHandle &handle)
lease4-wipe handler
int lease6ResendDdnsHandler(hooks::CalloutHandle &handle)
lease6-resend-ddns command handler
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
A generic exception that is thrown if a parameter given violates security check but enforcement is la...
Definition filesystem.h:22
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
const isc::log::MessageID LEASE_CMDS_DEL4
const isc::log::MessageID LEASE_CMDS_WIPE4_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE4_FAILED
const isc::log::MessageID LEASE_CMDS_WIPE6_FAILED
const isc::log::MessageID LEASE_CMDS_UPDATE6_CONFLICT
const isc::log::MessageID LEASE_CMDS_UPDATE4_CONFLICT
const isc::log::MessageID LEASE_CMDS_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:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
Definition lease.h: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< 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:934
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:154
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet4Collection
A collection of Subnet4 objects.
Definition subnet.h:863
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition duid.h:216
@ 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
static constexpr uint32_t STATE_DEFAULT
A lease in the default state.
Definition lease.h:69
static constexpr uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Definition lease.h:75
static constexpr uint32_t STATE_DECLINED
Declined lease.
Definition lease.h:72
static constexpr uint32_t STATE_REGISTERED
Registered self-generated lease.
Definition lease.h:81
static std::string basicStatesToText(const uint32_t state)
Returns name(s) of the basic lease state(s).
Definition lease.cc:89
static constexpr uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
Definition lease.h:78
static void syncCurrentExpirationTime(const Lease &from, Lease &to)
Sync lease current expiration time with new value from another lease, so that additional operations c...
Definition lease.cc:316
Type
Type of lease or pool.
Definition lease.h:46
@ 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 std::string typeToText(Type type)
returns text representation of a lease type
Definition lease.cc:56