Kea  2.1.7-git
lease_cmds.cc
Go to the documentation of this file.
1 // Copyright (C) 2017-2021 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>
8 #include <config/command_mgr.h>
9 #include <config/cmds_impl.h>
10 #include <cc/command_interpreter.h>
11 #include <cc/data.h>
12 #include <asiolink/io_address.h>
13 #include <database/db_exceptions.h>
14 #include <dhcpsrv/cfgmgr.h>
16 #include <dhcpsrv/lease_mgr.h>
18 #include <dhcpsrv/ncr_generator.h>
20 #include <dhcpsrv/subnet_id.h>
21 #include <dhcpsrv/sanity_checker.h>
22 #include <dhcp/duid.h>
23 #include <hooks/hooks.h>
24 #include <exceptions/exceptions.h>
25 #include <lease_cmds.h>
26 #include <lease_parser.h>
27 #include <lease_cmds_log.h>
28 #include <stats/stats_mgr.h>
29 #include <util/encode/hex.h>
31 #include <util/strutil.h>
32 
33 #include <boost/scoped_ptr.hpp>
34 #include <boost/algorithm/string.hpp>
35 #include <string>
36 #include <sstream>
37 
38 using namespace isc::dhcp;
39 using namespace isc::data;
40 using namespace isc::dhcp_ddns;
41 using namespace isc::config;
42 using namespace isc::asiolink;
43 using namespace isc::hooks;
44 using namespace isc::stats;
45 using namespace isc::util;
46 using namespace std;
47 
48 namespace isc {
49 namespace lease_cmds {
50 
52 class LeaseCmdsImpl : private CmdsImpl {
53 public:
54 
56  class Parameters {
57  public:
58 
60  typedef enum {
64  TYPE_CLIENT_ID
65  } Type;
66 
69 
72 
75 
78 
81 
91  static Type txtToType(const std::string& txt) {
92  if (txt == "address") {
93  return (Parameters::TYPE_ADDR);
94  } else if (txt == "hw-address") {
95  return (Parameters::TYPE_HWADDR);
96  } else if (txt == "duid") {
97  return (Parameters::TYPE_DUID);
98  } else if (txt == "client-id") {
99  return (Parameters::TYPE_CLIENT_ID);
100  } else {
101  isc_throw(BadValue, "Incorrect identifier type: "
102  << txt << ", the only supported values are: "
103  "address, hw-address, duid");
104  }
105  }
106 
109 
112 
114  uint32_t iaid;
115 
118 
121  : subnet_id(0), addr("::"), query_type(TYPE_ADDR),
122  lease_type(Lease::TYPE_NA), iaid(0), updateDDNS(false) {
123  }
124  };
125 
126 public:
127 
136  int
137  leaseAddHandler(CalloutHandle& handle);
138 
148  int
149  lease6BulkApplyHandler(CalloutHandle& handle);
150 
159  int
160  leaseGetHandler(CalloutHandle& handle);
161 
173  int
174  leaseGetAllHandler(CalloutHandle& handle);
175 
191  int
192  leaseGetPageHandler(hooks::CalloutHandle& handle);
193 
203  int
204  leaseGetByHwAddressHandler(hooks::CalloutHandle& handle);
205 
215  int
216  leaseGetByClientIdHandler(hooks::CalloutHandle& handle);
217 
227  int
228  leaseGetByDuidHandler(hooks::CalloutHandle& handle);
229 
240  int
241  leaseGetByHostnameHandler(hooks::CalloutHandle& handle);
242 
251  int
252  lease4DelHandler(CalloutHandle& handle);
253 
262  int
263  lease6DelHandler(CalloutHandle& handle);
264 
273  int
274  lease4UpdateHandler(CalloutHandle& handle);
275 
284  int
285  lease6UpdateHandler(CalloutHandle& handle);
286 
295  int
296  lease4WipeHandler(CalloutHandle& handle);
297 
306  int
307  lease6WipeHandler(CalloutHandle& handle);
308 
317  int lease4ResendDdnsHandler(CalloutHandle& handle);
318 
327  int lease6ResendDdnsHandler(CalloutHandle& handle);
328 
340  Parameters getParameters(bool v6, const ConstElementPtr& args);
341 
359  Lease6Ptr getIPv6LeaseForDelete(const Parameters& parameters) const;
360 
375  ElementPtr createFailedLeaseMap(const Lease::Type& lease_type,
376  const IOAddress& lease_address,
377  const DuidPtr& duid,
378  const int control_result,
379  const std::string& error_message) const;
380 
391  IOAddress getAddressParam(ConstElementPtr params, const std::string name,
392  short family = AF_INET) const;
393 
397  static void updateStatsOnAdd(const Lease4Ptr& lease);
398 
402  static void updateStatsOnAdd(const Lease6Ptr& lease);
403 
408  static void updateStatsOnUpdate(const Lease4Ptr& existing,
409  const Lease4Ptr& lease);
410 
415  static void updateStatsOnUpdate(const Lease6Ptr& existing,
416  const Lease6Ptr& lease);
417 
421  static void updateStatsOnDelete(const Lease4Ptr& lease);
422 
426  static void updateStatsOnDelete(const Lease6Ptr& lease);
427 
436  static bool addOrUpdate4(Lease4Ptr lease, bool force_create);
437 
446  static bool addOrUpdate6(Lease6Ptr lease, bool force_create);
447 };
448 
449 void
450 LeaseCmdsImpl::updateStatsOnAdd(const Lease4Ptr& lease) {
451  if (!lease->stateExpiredReclaimed()) {
452  StatsMgr::instance().addValue(
453  StatsMgr::generateName("subnet", lease->subnet_id_,
454  "assigned-addresses"),
455  int64_t(1));
456  if (lease->stateDeclined()) {
457  StatsMgr::instance().addValue("declined-addresses", int64_t(1));
458 
459  StatsMgr::instance().addValue(
460  StatsMgr::generateName("subnet", lease->subnet_id_,
461  "declined-addresses"),
462  int64_t(1));
463  }
464  }
465 }
466 
467 void
468 LeaseCmdsImpl::updateStatsOnAdd(const Lease6Ptr& lease) {
469  if (!lease->stateExpiredReclaimed()) {
470  StatsMgr::instance().addValue(
471  StatsMgr::generateName("subnet", lease->subnet_id_,
472  lease->type_ == Lease::TYPE_NA ?
473  "assigned-nas" : "assigned-pds"),
474  int64_t(1));
475  if (lease->stateDeclined()) {
476  StatsMgr::instance().addValue("declined-addresses", int64_t(1));
477 
478  StatsMgr::instance().addValue(
479  StatsMgr::generateName("subnet", lease->subnet_id_,
480  "declined-addresses"),
481  int64_t(1));
482  }
483  }
484 }
485 
486 void
487 LeaseCmdsImpl::updateStatsOnUpdate(const Lease4Ptr& existing,
488  const Lease4Ptr& lease) {
489  if (!existing->stateExpiredReclaimed()) {
490  // old lease is non expired-reclaimed
491  if (existing->subnet_id_ != lease->subnet_id_) {
492  StatsMgr::instance().addValue(
493  StatsMgr::generateName("subnet", existing->subnet_id_,
494  "assigned-addresses"),
495  int64_t(-1));
496  }
497  if (existing->stateDeclined()) {
498  // old lease is declined
499  StatsMgr::instance().addValue("declined-addresses", int64_t(-1));
500 
501  StatsMgr::instance().addValue(
502  StatsMgr::generateName("subnet", existing->subnet_id_,
503  "declined-addresses"),
504  int64_t(-1));
505  }
506  if (!lease->stateExpiredReclaimed()) {
507  // new lease is non expired-reclaimed
508  if (existing->subnet_id_ != lease->subnet_id_) {
509  StatsMgr::instance().addValue(
510  StatsMgr::generateName("subnet", lease->subnet_id_,
511  "assigned-addresses"),
512  int64_t(1));
513  }
514  if (lease->stateDeclined()) {
515  // new lease is declined
516  StatsMgr::instance().addValue("declined-addresses", int64_t(1));
517 
518  StatsMgr::instance().addValue(
519  StatsMgr::generateName("subnet", lease->subnet_id_,
520  "declined-addresses"),
521  int64_t(1));
522  }
523  }
524  } else {
525  // old lease is expired-reclaimed
526  if (!lease->stateExpiredReclaimed()) {
527  // new lease is non expired-reclaimed
528  StatsMgr::instance().addValue(
529  StatsMgr::generateName("subnet", lease->subnet_id_,
530  "assigned-addresses"),
531  int64_t(1));
532  if (lease->stateDeclined()) {
533  // new lease is declined
534  StatsMgr::instance().addValue("declined-addresses", int64_t(1));
535 
536  StatsMgr::instance().addValue(
537  StatsMgr::generateName("subnet", lease->subnet_id_,
538  "declined-addresses"),
539  int64_t(1));
540  }
541  }
542  }
543 }
544 
545 void
546 LeaseCmdsImpl::updateStatsOnUpdate(const Lease6Ptr& existing,
547  const Lease6Ptr& lease) {
548  if (!existing->stateExpiredReclaimed()) {
549  // old lease is non expired-reclaimed
550  if (existing->subnet_id_ != lease->subnet_id_) {
551  StatsMgr::instance().addValue(
552  StatsMgr::generateName("subnet", existing->subnet_id_,
553  lease->type_ == Lease::TYPE_NA ?
554  "assigned-nas" : "assigned-pds"),
555  int64_t(-1));
556  }
557  if (existing->stateDeclined()) {
558  // old lease is declined
559  StatsMgr::instance().addValue("declined-addresses", int64_t(-1));
560 
561  StatsMgr::instance().addValue(
562  StatsMgr::generateName("subnet", existing->subnet_id_,
563  "declined-addresses"),
564  int64_t(-1));
565  }
566  if (!lease->stateExpiredReclaimed()) {
567  // new lease is non expired-reclaimed
568  if (existing->subnet_id_ != lease->subnet_id_) {
569  StatsMgr::instance().addValue(
570  StatsMgr::generateName("subnet", lease->subnet_id_,
571  lease->type_ == Lease::TYPE_NA ?
572  "assigned-nas" : "assigned-pds"),
573  int64_t(1));
574  }
575  if (lease->stateDeclined()) {
576  // new lease is declined
577  StatsMgr::instance().addValue("declined-addresses", int64_t(1));
578 
579  StatsMgr::instance().addValue(
580  StatsMgr::generateName("subnet", lease->subnet_id_,
581  "declined-addresses"),
582  int64_t(1));
583  }
584  }
585  } else {
586  // old lease is expired-reclaimed
587  if (!lease->stateExpiredReclaimed()) {
588  // new lease is non expired-reclaimed
589  StatsMgr::instance().addValue(
590  StatsMgr::generateName("subnet", lease->subnet_id_,
591  lease->type_ == Lease::TYPE_NA ?
592  "assigned-nas" : "assigned-pds"),
593  int64_t(1));
594  if (lease->stateDeclined()) {
595  // new lease is declined
596  StatsMgr::instance().addValue("declined-addresses", int64_t(1));
597 
598  StatsMgr::instance().addValue(
599  StatsMgr::generateName("subnet", lease->subnet_id_,
600  "declined-addresses"),
601  int64_t(1));
602  }
603  }
604  }
605 }
606 
607 void
608 LeaseCmdsImpl::updateStatsOnDelete(const Lease4Ptr& lease) {
609  if (!lease->stateExpiredReclaimed()) {
610  StatsMgr::instance().addValue(
611  StatsMgr::generateName("subnet", lease->subnet_id_,
612  "assigned-addresses"),
613  int64_t(-1));
614  if (lease->stateDeclined()) {
615  StatsMgr::instance().addValue("declined-addresses", int64_t(-1));
616 
617  StatsMgr::instance().addValue(
618  StatsMgr::generateName("subnet", lease->subnet_id_,
619  "declined-addresses"),
620  int64_t(-1));
621  }
622  }
623 }
624 
625 void
626 LeaseCmdsImpl::updateStatsOnDelete(const Lease6Ptr& lease) {
627  if (!lease->stateExpiredReclaimed()) {
628  StatsMgr::instance().addValue(
629  StatsMgr::generateName("subnet", lease->subnet_id_,
630  lease->type_ == Lease::TYPE_NA ?
631  "assigned-nas" : "assigned-pds"),
632  int64_t(-1));
633  if (lease->stateDeclined()) {
634  StatsMgr::instance().addValue("declined-addresses", int64_t(-1));
635 
636  StatsMgr::instance().addValue(
637  StatsMgr::generateName("subnet", lease->subnet_id_,
638  "declined-addresses"),
639  int64_t(-1));
640  }
641  }
642 }
643 
644 bool
645 LeaseCmdsImpl::addOrUpdate4(Lease4Ptr lease, bool force_create) {
646  Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(lease->addr_);
647  if (force_create && !existing) {
648  // lease does not exist
649  if (!LeaseMgrFactory::instance().addLease(lease)) {
651  "lost race between calls to get and add");
652  }
653  LeaseCmdsImpl::updateStatsOnAdd(lease);
654  return (true);
655  }
656  if (existing) {
657  // Update lease current expiration time with value received from the
658  // database. Some database backends reject operations on the lease if
659  // the current expiration time value does not match what is stored.
660  Lease::syncCurrentExpirationTime(*existing, *lease);
661  }
662  try {
664  } catch (const NoSuchLease&) {
665  isc_throw(InvalidOperation, "failed to update the lease with address "
666  << lease->addr_ << " either because the lease has been "
667  "deleted or it has changed in the database, in both cases a "
668  "retry might succeed");
669  }
670 
671  LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
672  return (false);
673 }
674 
675 bool
676 LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) {
677  Lease6Ptr existing =
678  LeaseMgrFactory::instance().getLease6(lease->type_, lease->addr_);
679  if (force_create && !existing) {
680  // lease does not exist
681  if (!LeaseMgrFactory::instance().addLease(lease)) {
683  "lost race between calls to get and add");
684  }
685  LeaseCmdsImpl::updateStatsOnAdd(lease);
686  return (true);
687  }
688  if (existing) {
689  // Update lease current expiration time with value received from the
690  // database. Some database backends reject operations on the lease if
691  // the current expiration time value does not match what is stored.
692  Lease::syncCurrentExpirationTime(*existing, *lease);
693  }
694  try {
696  } catch (const NoSuchLease&) {
697  isc_throw(InvalidOperation, "failed to update the lease with address "
698  << lease->addr_ << " either because the lease has been "
699  "deleted or it has changed in the database, in both cases a "
700  "retry might succeed");
701  }
702 
703  LeaseCmdsImpl::updateStatsOnUpdate(existing, lease);
704  return (false);
705 }
706 
707 int
708 LeaseCmdsImpl::leaseAddHandler(CalloutHandle& handle) {
709  // Arbitrary defaulting to DHCPv4 or with other words extractCommand
710  // below is not expected to throw...
711  bool v4 = true;
712  string txt = "malformed command";
713 
714  stringstream resp;
715  try {
716  extractCommand(handle);
717  v4 = (cmd_name_ == "lease4-add");
718 
719  txt = "(missing parameters)";
720  if (!cmd_args_) {
721  isc_throw(isc::BadValue, "no parameters specified for the command");
722  }
723 
724  txt = cmd_args_->str();
725 
727 
728  Lease4Ptr lease4;
729  Lease6Ptr lease6;
730  // This parameter is ignored for the commands adding the lease.
731  bool force_create = false;
732  if (v4) {
733  Lease4Parser parser;
734  lease4 = parser.parse(config, cmd_args_, force_create);
735  if (lease4) {
736  bool success;
737  if (!MultiThreadingMgr::instance().getMode()) {
738  // Not multi-threading.
739  success = LeaseMgrFactory::instance().addLease(lease4);
740  } else {
741  // Multi-threading, try to lock first to avoid a race.
742  ResourceHandler4 resource_handler;
743  if (resource_handler.tryLock4(lease4->addr_)) {
744  success = LeaseMgrFactory::instance().addLease(lease4);
745  } else {
747  "ResourceBusy: IP address:" << lease4->addr_
748  << " could not be added.");
749  }
750  }
751 
752  if (!success) {
753  isc_throw(db::DuplicateEntry, "IPv4 lease already exists.");
754  }
755 
756  LeaseCmdsImpl::updateStatsOnAdd(lease4);
757  resp << "Lease for address " << lease4->addr_.toText()
758  << ", subnet-id " << lease4->subnet_id_ << " added.";
759  }
760  } else {
761  Lease6Parser parser;
762  lease6 = parser.parse(config, cmd_args_, force_create);
763  if (lease6) {
764  bool success;
765  if (!MultiThreadingMgr::instance().getMode()) {
766  // Not multi-threading.
767  success = LeaseMgrFactory::instance().addLease(lease6);
768  } else {
769  // Multi-threading, try to lock first to avoid a race.
770  ResourceHandler resource_handler;
771  if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
772  success = LeaseMgrFactory::instance().addLease(lease6);
773  } else {
775  "ResourceBusy: IP address:" << lease6->addr_
776  << " could not be added.");
777  }
778  }
779 
780  if (!success) {
781  isc_throw(db::DuplicateEntry, "IPv6 lease already exists.");
782  }
783 
784  LeaseCmdsImpl::updateStatsOnAdd(lease6);
785  if (lease6->type_ == Lease::TYPE_NA) {
786  resp << "Lease for address " << lease6->addr_.toText()
787  << ", subnet-id " << lease6->subnet_id_ << " added.";
788  } else {
789  resp << "Lease for prefix " << lease6->addr_.toText()
790  << "/" << static_cast<int>(lease6->prefixlen_)
791  << ", subnet-id " << lease6->subnet_id_ << " added.";
792  }
793  }
794  }
795 
796  } catch (const std::exception& ex) {
798  .arg(txt)
799  .arg(ex.what());
800  setErrorResponse(handle, ex.what());
801  return (1);
802  }
803 
805  v4 ? LEASE_CMDS_ADD4 : LEASE_CMDS_ADD6).arg(txt);
806  setSuccessResponse(handle, resp.str());
807  return (0);
808 }
809 
811 LeaseCmdsImpl::getParameters(bool v6, const ConstElementPtr& params) {
812  Parameters x;
813 
814  if (!params || params->getType() != Element::map) {
815  isc_throw(BadValue, "Parameters missing or are not a map.");
816  }
817 
818  if (params->contains("update-ddns")) {
819  ConstElementPtr tmp = params->get("update-ddns");
820  if (tmp->getType() != Element::boolean) {
821  isc_throw(BadValue, "'update-ddns' is not a boolean");
822  } else {
823  x.updateDDNS = tmp->boolValue();
824  }
825  }
826 
827  // We support several sets of parameters for leaseX-get/lease-del:
828  // lease-get(type, address)
829  // lease-get(type, subnet-id, identifier-type, identifier)
830 
831  if (params->contains("type")) {
832  string t = params->get("type")->stringValue();
833  if (t == "IA_NA" || t == "0") {
835  } else if (t == "IA_TA" || t == "1") {
837  } else if (t == "IA_PD" || t == "2") {
839  } else if (t == "V4" || t == "3") {
841  } else {
842  isc_throw(BadValue, "Invalid lease type specified: "
843  << t << ", only supported values are: IA_NA, IA_TA,"
844  << " IA_PD and V4");
845  }
846  }
847 
848  ConstElementPtr tmp = params->get("ip-address");
849  if (tmp) {
850  if (tmp->getType() != Element::string) {
851  isc_throw(BadValue, "'ip-address' is not a string.");
852  }
853 
854  x.addr = IOAddress(tmp->stringValue());
855 
856  if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
857  stringstream txt;
858  txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
859  << " address specified: " << tmp->stringValue();
860  isc_throw(BadValue, txt.str());
861  }
862 
863  x.query_type = Parameters::TYPE_ADDR;
864  return (x);
865  }
866 
867  tmp = params->get("subnet-id");
868  if (!tmp) {
869  isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
870  }
871  if (tmp->getType() != Element::integer) {
872  isc_throw(BadValue, "'subnet-id' parameter is not integer.");
873  }
874  x.subnet_id = tmp->intValue();
875 
876  if (params->contains("iaid")) {
877  x.iaid = params->get("iaid")->intValue();
878  }
879 
880  // No address specified. Ok, so it must be identifier based query.
881  // "identifier-type": "duid",
882  // "identifier": "aa:bb:cc:dd:ee:..."
883 
884  ConstElementPtr type = params->get("identifier-type");
885  ConstElementPtr ident = params->get("identifier");
886  if (!type || type->getType() != Element::string) {
887  isc_throw(BadValue, "No 'ip-address' provided"
888  " and 'identifier-type' is either missing or not a string.");
889  }
890  if (!ident || ident->getType() != Element::string) {
891  isc_throw(BadValue, "No 'ip-address' provided"
892  " and 'identifier' is either missing or not a string.");
893  }
894 
895  // Got the parameters. Let's see if their values make sense.
896  // Try to convert identifier-type
897  x.query_type = Parameters::txtToType(type->stringValue());
898 
899  switch (x.query_type) {
900  case Parameters::TYPE_HWADDR: {
901  HWAddr hw = HWAddr::fromText(ident->stringValue());
902  x.hwaddr = HWAddrPtr(new HWAddr(hw));
903  break;
904  }
905  case Parameters::TYPE_CLIENT_ID: {
906  x.client_id = ClientId::fromText(ident->stringValue());
907  break;
908  }
909  case Parameters::TYPE_DUID: {
910  DUID duid = DUID::fromText(ident->stringValue());
911  x.duid = DuidPtr(new DUID(duid));
912  break;
913  }
914  case Parameters::TYPE_ADDR: {
915  // We should never get here. The address clause should have been caught
916  // earlier.
917  return (x);
918  }
919  default: {
920  isc_throw(BadValue, "Identifier type " << type->stringValue() <<
921  " is not supported.");
922  }
923  }
924 
925  return (x);
926 }
927 
928 int
929 LeaseCmdsImpl::leaseGetHandler(CalloutHandle& handle) {
930  Parameters p;
931  Lease4Ptr lease4;
932  Lease6Ptr lease6;
933  bool v4;
934  try {
935  extractCommand(handle);
936  v4 = (cmd_name_ == "lease4-get");
937 
938  p = getParameters(!v4, cmd_args_);
939  switch (p.query_type) {
940  case Parameters::TYPE_ADDR: {
941  // Query by address
942  if (v4) {
944  } else {
946  }
947  break;
948  }
949  case Parameters::TYPE_HWADDR:
950  if (v4) {
951  if (!p.hwaddr) {
952  isc_throw(InvalidParameter, "Program error: Query by hw-address "
953  "requires hwaddr to be specified");
954  }
955 
957  } else {
958  isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
959  }
960  break;
961 
962  case Parameters::TYPE_DUID:
963  if (!v4) {
964  if (!p.duid) {
965  isc_throw(InvalidParameter, "Program error: Query by duid "
966  "requires duid to be specified");
967  }
968 
970  p.iaid, p.subnet_id);
971  } else {
972  isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
973  }
974  break;
975 
976  case Parameters::TYPE_CLIENT_ID:
977  if (v4) {
978  if (!p.client_id) {
979  isc_throw(InvalidParameter, "Program error: Query by client-id "
980  "requires client-id to be specified");
981  }
982 
984  } else {
985  isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
986  }
987  break;
988 
989  default: {
990  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
991  break;
992  }
993  }
994  } catch (const std::exception& ex) {
995  setErrorResponse(handle, ex.what());
996  return (1);
997  }
998 
999  ElementPtr lease_json;
1000  if (v4 && lease4) {
1001  lease_json = lease4->toElement();
1003  "IPv4 lease found.", lease_json);
1004  setResponse(handle, response);
1005  } else if (!v4 && lease6) {
1006  lease_json = lease6->toElement();
1008  "IPv6 lease found.", lease_json);
1009  setResponse(handle, response);
1010  } else {
1011  // If we got here, the lease has not been found.
1012  setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
1013  }
1014 
1015  return (0);
1016 }
1017 
1018 int
1019 LeaseCmdsImpl::leaseGetAllHandler(CalloutHandle& handle) {
1020  bool v4 = true;
1021  try {
1022  extractCommand(handle);
1023  v4 = (cmd_name_ == "lease4-get-all");
1024 
1025  ElementPtr leases_json = Element::createList();
1026 
1027  // The argument may contain a list of subnets for which leases should
1028  // be returned.
1029  if (cmd_args_) {
1030  ConstElementPtr subnets = cmd_args_->get("subnets");
1031  if (!subnets) {
1032  isc_throw(BadValue, "'subnets' parameter not specified");
1033  }
1034  if (subnets->getType() != Element::list) {
1035  isc_throw(BadValue, "'subnets' parameter must be a list");
1036  }
1037 
1038  const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
1039  for (auto subnet_id = subnet_ids.begin();
1040  subnet_id != subnet_ids.end();
1041  ++subnet_id) {
1042  if ((*subnet_id)->getType() != Element::integer) {
1043  isc_throw(BadValue, "listed subnet identifiers must be numbers");
1044  }
1045 
1046  if (v4) {
1047  Lease4Collection leases =
1048  LeaseMgrFactory::instance().getLeases4((*subnet_id)->intValue());
1049  for (auto lease : leases) {
1050  ElementPtr lease_json = lease->toElement();
1051  leases_json->add(lease_json);
1052  }
1053  } else {
1054  Lease6Collection leases =
1055  LeaseMgrFactory::instance().getLeases6((*subnet_id)->intValue());
1056  for (auto lease : leases) {
1057  ElementPtr lease_json = lease->toElement();
1058  leases_json->add(lease_json);
1059  }
1060  }
1061  }
1062 
1063  } else {
1064  // There is no 'subnets' argument so let's return all leases.
1065  if (v4) {
1067  for (auto lease : leases) {
1068  ElementPtr lease_json = lease->toElement();
1069  leases_json->add(lease_json);
1070  }
1071  } else {
1073  for (auto lease : leases) {
1074  ElementPtr lease_json = lease->toElement();
1075  leases_json->add(lease_json);
1076  }
1077  }
1078  }
1079 
1080  std::ostringstream s;
1081  s << leases_json->size()
1082  << " IPv" << (v4 ? "4" : "6")
1083  << " lease(s) found.";
1084  ElementPtr args = Element::createMap();
1085  args->set("leases", leases_json);
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 (0);
1099 }
1100 
1101 int
1102 LeaseCmdsImpl::leaseGetPageHandler(CalloutHandle& handle) {
1103  bool v4 = true;
1104  try {
1105  extractCommand(handle);
1106  v4 = (cmd_name_ == "lease4-get-page");
1107 
1108  // arguments must always be present
1109  if (!cmd_args_) {
1110  isc_throw(BadValue, "no parameters specified for the " << cmd_name_
1111  << " command");
1112  }
1113 
1114  // The 'from' argument denotes from which lease we should start the
1115  // results page. The results page excludes this lease.
1116  ConstElementPtr from = cmd_args_->get("from");
1117  if (!from) {
1118  isc_throw(BadValue, "'from' parameter not specified");
1119  }
1120 
1121  // The 'from' argument is a string. It may contain a 'start' keyword or
1122  // an IP address.
1123  if (from->getType() != Element::string) {
1124  isc_throw(BadValue, "'from' parameter must be a string");
1125  }
1126 
1127  boost::scoped_ptr<IOAddress> from_address;
1128  try {
1129  if (from->stringValue() == "start") {
1130  from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1131 
1132  } else {
1133  // Conversion of a string to an IP address may throw.
1134  from_address.reset(new IOAddress(from->stringValue()));
1135  }
1136 
1137  } catch (...) {
1138  isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1139  "a valid IPv" << (v4 ? "4" : "6") << " address");
1140  }
1141 
1142  // It must be either IPv4 address for lease4-get-page or IPv6 address for
1143  // lease6-get-page.
1144  if (v4 && (!from_address->isV4())) {
1145  isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1146  << " is not an IPv4 address");
1147 
1148  } else if (!v4 && from_address->isV4()) {
1149  isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1150  << " is not an IPv6 address");
1151  }
1152 
1153  // The 'limit' is a desired page size. It must always be present.
1154  ConstElementPtr page_limit = cmd_args_->get("limit");
1155  if (!page_limit) {
1156  isc_throw(BadValue, "'limit' parameter not specified");
1157  }
1158 
1159  // The 'limit' must be a number.
1160  if (page_limit->getType() != Element::integer) {
1161  isc_throw(BadValue, "'limit' parameter must be a number");
1162  }
1163 
1164  // Retrieve the desired page size.
1165  size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
1166 
1167  ElementPtr leases_json = Element::createList();
1168 
1169  if (v4) {
1170  // Get page of IPv4 leases.
1171  Lease4Collection leases =
1172  LeaseMgrFactory::instance().getLeases4(*from_address,
1173  LeasePageSize(page_limit_value));
1174 
1175  // Convert leases into JSON list.
1176  for (auto lease : leases) {
1177  ElementPtr lease_json = lease->toElement();
1178  leases_json->add(lease_json);
1179  }
1180 
1181  } else {
1182  // Get page of IPv6 leases.
1183  Lease6Collection leases =
1184  LeaseMgrFactory::instance().getLeases6(*from_address,
1185  LeasePageSize(page_limit_value));
1186  // Convert leases into JSON list.
1187  for (auto lease : leases) {
1188  ElementPtr lease_json = lease->toElement();
1189  leases_json->add(lease_json);
1190  }
1191  }
1192 
1193  // Prepare textual status.
1194  std::ostringstream s;
1195  s << leases_json->size()
1196  << " IPv" << (v4 ? "4" : "6")
1197  << " lease(s) found.";
1198  ElementPtr args = Element::createMap();
1199 
1200  // Put gathered data into arguments map.
1201  args->set("leases", leases_json);
1202  args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1203 
1204  // Create the response.
1205  ConstElementPtr response =
1206  createAnswer(leases_json->size() > 0 ?
1209  s.str(), args);
1210  setResponse(handle, response);
1211 
1212  } catch (const std::exception& ex) {
1213  setErrorResponse(handle, ex.what());
1214  return (CONTROL_RESULT_ERROR);
1215  }
1216 
1217  return (CONTROL_RESULT_SUCCESS);
1218 }
1219 
1220 int
1221 LeaseCmdsImpl::leaseGetByHwAddressHandler(CalloutHandle& handle) {
1222  try {
1223  extractCommand(handle);
1224 
1225  // arguments must always be present
1226  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1227  isc_throw(BadValue, "Command arguments missing or a not a map.");
1228  }
1229 
1230  // the hw-address parameter is mandatory.
1231  ConstElementPtr hw_address = cmd_args_->get("hw-address");
1232  if (!hw_address) {
1233  isc_throw(BadValue, "'hw-address' parameter not specified");
1234  }
1235 
1236  // The 'hw-address' argument is a string.
1237  if (hw_address->getType() != Element::string) {
1238  isc_throw(BadValue, "'hw-address' parameter must be a string");
1239  }
1240 
1241  HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
1242 
1243  Lease4Collection leases =
1245  ElementPtr leases_json = Element::createList();
1246  for (auto lease : leases) {
1247  ElementPtr lease_json = lease->toElement();
1248  leases_json->add(lease_json);
1249  }
1250 
1251  std::ostringstream s;
1252  s << leases_json->size() << " IPv4 lease(s) found.";
1253  ElementPtr args = Element::createMap();
1254  args->set("leases", leases_json);
1255  ConstElementPtr response =
1256  createAnswer(leases_json->size() > 0 ?
1259  s.str(), args);
1260  setResponse(handle, response);
1261 
1262  } catch (const std::exception& ex) {
1263  setErrorResponse(handle, ex.what());
1264  return (CONTROL_RESULT_ERROR);
1265  }
1266 
1267  return (0);
1268 }
1269 
1270 int
1271 LeaseCmdsImpl::leaseGetByClientIdHandler(CalloutHandle& handle) {
1272  try {
1273  extractCommand(handle);
1274 
1275  // arguments must always be present
1276  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1277  isc_throw(BadValue, "Command arguments missing or a not a map.");
1278  }
1279 
1280  // the client-id parameter is mandatory.
1281  ConstElementPtr client_id = cmd_args_->get("client-id");
1282  if (!client_id) {
1283  isc_throw(BadValue, "'client-id' parameter not specified");
1284  }
1285 
1286  // The 'client-id' argument is a string.
1287  if (client_id->getType() != Element::string) {
1288  isc_throw(BadValue, "'client-id' parameter must be a string");
1289  }
1290 
1291  ClientIdPtr clientid = ClientId::fromText(client_id->stringValue());
1292 
1293  Lease4Collection leases =
1294  LeaseMgrFactory::instance().getLease4(*clientid);
1295  ElementPtr leases_json = Element::createList();
1296  for (auto lease : leases) {
1297  ElementPtr lease_json = lease->toElement();
1298  leases_json->add(lease_json);
1299  }
1300 
1301  std::ostringstream s;
1302  s << leases_json->size() << " IPv4 lease(s) found.";
1303  ElementPtr args = Element::createMap();
1304  args->set("leases", leases_json);
1305  ConstElementPtr response =
1306  createAnswer(leases_json->size() > 0 ?
1309  s.str(), args);
1310  setResponse(handle, response);
1311 
1312  } catch (const std::exception& ex) {
1313  setErrorResponse(handle, ex.what());
1314  return (CONTROL_RESULT_ERROR);
1315  }
1316 
1317  return (0);
1318 }
1319 
1320 int
1321 LeaseCmdsImpl::leaseGetByDuidHandler(CalloutHandle& handle) {
1322  try {
1323  extractCommand(handle);
1324 
1325  // arguments must always be present
1326  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1327  isc_throw(BadValue, "Command arguments missing or a not a map.");
1328  }
1329 
1330  // the duid parameter is mandatory.
1331  ConstElementPtr duid = cmd_args_->get("duid");
1332  if (!duid) {
1333  isc_throw(BadValue, "'duid' parameter not specified");
1334  }
1335 
1336  // The 'duid' argument is a string.
1337  if (duid->getType() != Element::string) {
1338  isc_throw(BadValue, "'duid' parameter must be a string");
1339  }
1340 
1341  DUID duid_ = DUID::fromText(duid->stringValue());
1342 
1343  Lease6Collection leases =
1345  ElementPtr leases_json = Element::createList();
1346  for (auto lease : leases) {
1347  ElementPtr lease_json = lease->toElement();
1348  leases_json->add(lease_json);
1349  }
1350 
1351  std::ostringstream s;
1352  s << leases_json->size() << " IPv6 lease(s) found.";
1353  ElementPtr args = Element::createMap();
1354  args->set("leases", leases_json);
1355  ConstElementPtr response =
1356  createAnswer(leases_json->size() > 0 ?
1359  s.str(), args);
1360  setResponse(handle, response);
1361 
1362  } catch (const std::exception& ex) {
1363  setErrorResponse(handle, ex.what());
1364  return (CONTROL_RESULT_ERROR);
1365  }
1366 
1367  return (0);
1368 }
1369 
1370 int
1371 LeaseCmdsImpl::leaseGetByHostnameHandler(CalloutHandle& handle) {
1372  bool v4;
1373  try {
1374  extractCommand(handle);
1375  v4 = (cmd_name_ == "lease4-get-by-hostname");
1376 
1377  // arguments must always be present
1378  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1379  isc_throw(BadValue, "Command arguments missing or a not a map.");
1380  }
1381 
1382  // the hostname parameter is mandatory.
1383  ConstElementPtr hostname = cmd_args_->get("hostname");
1384  if (!hostname) {
1385  isc_throw(BadValue, "'hostname' parameter not specified");
1386  }
1387 
1388  // The 'hostname' argument is a string.
1389  if (hostname->getType() != Element::string) {
1390  isc_throw(BadValue, "'hostname' parameter must be a string");
1391  }
1392 
1393  std::string hostname_ = hostname->stringValue();
1395  if (hostname_.empty()) {
1396  isc_throw(BadValue, "'hostname' parameter is empty");
1397  }
1398  boost::algorithm::to_lower(hostname_);
1399 
1400  ElementPtr leases_json = Element::createList();
1401  if (v4) {
1402  Lease4Collection leases =
1404 
1405  for (auto lease : leases) {
1406  ElementPtr lease_json = lease->toElement();
1407  leases_json->add(lease_json);
1408  }
1409  } else {
1410  Lease6Collection leases =
1412 
1413  for (auto lease : leases) {
1414  ElementPtr lease_json = lease->toElement();
1415  leases_json->add(lease_json);
1416  }
1417  }
1418 
1419  std::ostringstream s;
1420  s << leases_json->size()
1421  << " IPv" << (v4 ? "4" : "6")
1422  << " lease(s) found.";
1423  ElementPtr args = Element::createMap();
1424  args->set("leases", leases_json);
1425  ConstElementPtr response =
1426  createAnswer(leases_json->size() > 0 ?
1429  s.str(), args);
1430  setResponse(handle, response);
1431 
1432  } catch (const std::exception& ex) {
1433  setErrorResponse(handle, ex.what());
1434  return (CONTROL_RESULT_ERROR);
1435  }
1436 
1437  return (0);
1438 }
1439 
1440 int
1441 LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) {
1442  Parameters p;
1443  Lease4Ptr lease4;
1444  try {
1445  extractCommand(handle);
1446  p = getParameters(false, cmd_args_);
1447 
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  }
1458  case Parameters::TYPE_HWADDR: {
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  }
1472  case Parameters::TYPE_CLIENT_ID: {
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.");
1498  LeaseCmdsImpl::updateStatsOnDelete(lease4);
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) {
1509  setErrorResponse(handle, ex.what());
1510  return (1);
1511  }
1512 
1513  return (0);
1514 }
1515 
1516 int
1517 LeaseCmdsImpl::lease6BulkApplyHandler(CalloutHandle& handle) {
1518  try {
1519  extractCommand(handle);
1520 
1521  // Arguments are mandatory.
1522  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1523  isc_throw(BadValue, "Command arguments missing or a not a map.");
1524  }
1525 
1526  // At least one of the 'deleted-leases' or 'leases' must be present.
1527  auto deleted_leases = cmd_args_->get("deleted-leases");
1528  auto leases = cmd_args_->get("leases");
1529 
1530  if (!deleted_leases && !leases) {
1531  isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1532  " specified");
1533  }
1534 
1535  // Make sure that 'deleted-leases' is a list, if present.
1536  if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1537  isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1538  }
1539 
1540  // Make sure that 'leases' is a list, if present.
1541  if (leases && (leases->getType() != Element::list)) {
1542  isc_throw(BadValue, "the 'leases' parameter must be a list");
1543  }
1544 
1545  // Parse deleted leases without deleting them from the database
1546  // yet. If any of the deleted leases or new leases appears to be
1547  // malformed we can easily rollback.
1548  std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1549  if (deleted_leases) {
1550  auto leases_list = deleted_leases->listValue();
1551 
1552  // Iterate over leases to be deleted.
1553  for (auto lease_params : leases_list) {
1554  // Parsing the lease may throw and it means that the lease
1555  // information is malformed.
1556  Parameters p = getParameters(true, lease_params);
1557  auto lease = getIPv6LeaseForDelete(p);
1558  parsed_deleted_list.push_back(std::make_pair(p, lease));
1559  }
1560  }
1561 
1562  // Parse new/updated leases without affecting the database to detect
1563  // any errors that should cause an error response.
1564  std::list<Lease6Ptr> parsed_leases_list;
1565  if (leases) {
1567 
1568  // Iterate over all leases.
1569  auto leases_list = leases->listValue();
1570  for (auto lease_params : leases_list) {
1571 
1572  Lease6Parser parser;
1573  bool force_update;
1574 
1575  // If parsing the lease fails we throw, as it indicates that the
1576  // command is malformed.
1577  Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1578  parsed_leases_list.push_back(lease6);
1579  }
1580  }
1581 
1582  // Count successful deletions and updates.
1583  size_t success_count = 0;
1584 
1585  ElementPtr failed_deleted_list;
1586  if (!parsed_deleted_list.empty()) {
1587 
1588  // Iterate over leases to be deleted.
1589  for (auto lease_params_pair : parsed_deleted_list) {
1590 
1591  // This part is outside of the try-catch because an exception
1592  // indicates that the command is malformed.
1593  Parameters p = lease_params_pair.first;
1594  auto lease = lease_params_pair.second;
1595 
1596  try {
1597  if (lease) {
1598  // This may throw if the lease couldn't be deleted for
1599  // any reason, but we still want to proceed with other
1600  // leases.
1601  if (LeaseMgrFactory::instance().deleteLease(lease)) {
1602  ++success_count;
1603  LeaseCmdsImpl::updateStatsOnDelete(lease);
1604 
1605  } else {
1606  // Lazy creation of the list of leases which failed to delete.
1607  if (!failed_deleted_list) {
1608  failed_deleted_list = Element::createList();
1609  }
1610 
1611  // If the lease doesn't exist we also want to put it
1612  // on the list of leases which failed to delete. That
1613  // corresponds to the lease6-del command which returns
1614  // an error when the lease doesn't exist.
1615  failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1616  p.addr, p.duid,
1618  "lease not found"));
1619  }
1620  }
1621 
1622  } catch (const std::exception& ex) {
1623  // Lazy creation of the list of leases which failed to delete.
1624  if (!failed_deleted_list) {
1625  failed_deleted_list = Element::createList();
1626  }
1627  failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1628  p.addr, p.duid,
1630  ex.what()));
1631  }
1632  }
1633  }
1634 
1635  // Process leases to be added or/and updated.
1636  ElementPtr failed_leases_list;
1637  if (!parsed_leases_list.empty()) {
1639 
1640  // Iterate over all leases.
1641  for (auto lease : parsed_leases_list) {
1642 
1643  try {
1644  if (!MultiThreadingMgr::instance().getMode()) {
1645  // Not multi-threading.
1646  addOrUpdate6(lease, true);
1647  } else {
1648  // Multi-threading, try to lock first to avoid a race.
1649  ResourceHandler resource_handler;
1650  if (resource_handler.tryLock(lease->type_, lease->addr_)) {
1651  addOrUpdate6(lease, true);
1652  } else {
1654  "ResourceBusy: IP address:" << lease->addr_
1655  << " could not be updated.");
1656  }
1657  }
1658 
1659  ++success_count;
1660  } catch (const std::exception& ex) {
1661  // Lazy creation of the list of leases which failed to add/update.
1662  if (!failed_leases_list) {
1663  failed_leases_list = Element::createList();
1664  }
1665  failed_leases_list->add(createFailedLeaseMap(lease->type_,
1666  lease->addr_,
1667  lease->duid_,
1669  ex.what()));
1670  }
1671  }
1672  }
1673 
1674  // Start preparing the response.
1675  ElementPtr args;
1676 
1677  if (failed_deleted_list || failed_leases_list) {
1678  // If there are any failed leases, let's include them in the response.
1679  args = Element::createMap();
1680 
1681  // failed-deleted-leases
1682  if (failed_deleted_list) {
1683  args->set("failed-deleted-leases", failed_deleted_list);
1684  }
1685 
1686  // failed-leases
1687  if (failed_leases_list) {
1688  args->set("failed-leases", failed_leases_list);
1689  }
1690  }
1691 
1692  // Send the success response and include failed leases.
1693  std::ostringstream resp_text;
1694  resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
1695  auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
1696  CONTROL_RESULT_EMPTY, resp_text.str(), args);
1697  setResponse(handle, answer);
1698 
1699  } catch (const std::exception& ex) {
1700  // Unable to parse the command and similar issues.
1701  setErrorResponse(handle, ex.what());
1702  return (CONTROL_RESULT_ERROR);
1703  }
1704 
1705  return (CONTROL_RESULT_SUCCESS);
1706 }
1707 
1708 int
1709 LeaseCmdsImpl::lease6DelHandler(CalloutHandle& handle) {
1710  Parameters p;
1711  Lease6Ptr lease6;
1713  try {
1714  extractCommand(handle);
1715  p = getParameters(true, cmd_args_);
1716 
1717  switch (p.query_type) {
1718  case Parameters::TYPE_ADDR: {
1719  // If address was specified explicitly, let's use it as is.
1720 
1721  // Let's see if there's such a lease at all.
1723  if (!lease6) {
1724  setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1725  return (0);
1726  }
1727  break;
1728  }
1729  case Parameters::TYPE_HWADDR: {
1730  isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
1731  break;
1732  }
1733  case Parameters::TYPE_DUID: {
1734  if (!p.duid) {
1735  isc_throw(InvalidParameter, "Program error: Query by duid "
1736  "requires duid to be specified");
1737  }
1738 
1739  // Let's see if there's such a lease at all.
1741  p.iaid, p.subnet_id);
1742  if (!lease6) {
1743  setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1744  return (0);
1745  }
1746  break;
1747  }
1748  default: {
1749  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1750  break;
1751  }
1752  }
1753 
1754  if (LeaseMgrFactory::instance().deleteLease(lease6)) {
1755  setSuccessResponse(handle, "IPv6 lease deleted.");
1756  LeaseCmdsImpl::updateStatsOnDelete(lease6);
1757  } else {
1758  setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1759  }
1760 
1761  // Queue an NCR to remove DNS if configured and the lease has it.
1762  if (p.updateDDNS) {
1763  queueNCR(CHG_REMOVE, lease6);
1764  }
1765 
1766  } catch (const std::exception& ex) {
1767  setErrorResponse(handle, ex.what());
1768  return (1);
1769  }
1770 
1771  return (0);
1772 }
1773 
1774 int
1775 LeaseCmdsImpl::lease4UpdateHandler(CalloutHandle& handle) {
1776  try {
1777  extractCommand(handle);
1778 
1779  // We need the lease to be specified.
1780  if (!cmd_args_) {
1781  isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
1782  }
1783 
1784  // Get the parameters specified by the user first.
1786  Lease4Ptr lease4;
1787  Lease4Parser parser;
1788  bool force_create = false;
1789 
1790  // The parser does sanity checks (if the address is in scope, if
1791  // subnet-id is valid, etc)
1792  lease4 = parser.parse(config, cmd_args_, force_create);
1793  bool added = false;
1794  if (!MultiThreadingMgr::instance().getMode()) {
1795  // Not multi-threading.
1796  added = addOrUpdate4(lease4, force_create);
1797  } else {
1798  // Multi-threading, try to lock first to avoid a race.
1799  ResourceHandler4 resource_handler;
1800  if (resource_handler.tryLock4(lease4->addr_)) {
1801  added = addOrUpdate4(lease4, force_create);
1802  } else {
1804  "ResourceBusy: IP address:" << lease4->addr_
1805  << " could not be updated.");
1806  }
1807  }
1808 
1809  if (added) {
1810  setSuccessResponse(handle, "IPv4 lease added.");
1811  } else {
1812  setSuccessResponse(handle, "IPv4 lease updated.");
1813  }
1814  } catch (const std::exception& ex) {
1815  setErrorResponse(handle, ex.what());
1816  return (1);
1817  }
1818 
1819  return (0);
1820 }
1821 
1822 int
1823 LeaseCmdsImpl::lease6UpdateHandler(CalloutHandle& handle) {
1824  try {
1825  extractCommand(handle);
1826 
1827  // We need the lease to be specified.
1828  if (!cmd_args_) {
1829  isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
1830  }
1831 
1832  // Get the parameters specified by the user first.
1834  Lease6Ptr lease6;
1835  Lease6Parser parser;
1836  bool force_create = false;
1837 
1838  // The parser does sanity checks (if the address is in scope, if
1839  // subnet-id is valid, etc)
1840  lease6 = parser.parse(config, cmd_args_, force_create);
1841  bool added = false;
1842  if (!MultiThreadingMgr::instance().getMode()) {
1843  // Not multi-threading.
1844  added = addOrUpdate6(lease6, force_create);
1845  } else {
1846  // Multi-threading, try to lock first to avoid a race.
1847  ResourceHandler resource_handler;
1848  if (resource_handler.tryLock(lease6->type_, lease6->addr_)) {
1849  added = addOrUpdate6(lease6, force_create);
1850  } else {
1852  "ResourceBusy: IP address:" << lease6->addr_
1853  << " could not be updated.");
1854  }
1855  }
1856 
1857  if (added) {
1858  setSuccessResponse(handle, "IPv6 lease added.");
1859  } else {
1860  setSuccessResponse(handle, "IPv6 lease updated.");
1861  }
1862  } catch (const std::exception& ex) {
1863  setErrorResponse(handle, ex.what());
1864  return (1);
1865  }
1866 
1867  return (0);
1868 }
1869 
1870 int
1871 LeaseCmdsImpl::lease4WipeHandler(CalloutHandle& handle) {
1872  try {
1873  extractCommand(handle);
1874 
1875  SimpleParser parser;
1876  SubnetID id = 0;
1877 
1878  size_t num = 0; // number of leases deleted
1879  stringstream ids; // a text with subnet-ids being wiped
1880 
1881  // The subnet-id parameter is now optional.
1882  if (cmd_args_ && cmd_args_->contains("subnet-id")) {
1883  id = parser.getUint32(cmd_args_, "subnet-id");
1884  }
1885 
1886  if (id) {
1887  // Wipe a single subnet.
1889  ids << " " << id;
1890 
1891  auto observation = StatsMgr::instance().getObservation(
1892  StatsMgr::generateName("subnet", id, "declined-addresses"));
1893 
1894  int64_t previous_declined = 0;
1895 
1896  if (observation) {
1897  previous_declined = observation->getInteger().first;
1898  }
1899 
1900  StatsMgr::instance().setValue(
1901  StatsMgr::generateName("subnet", id, "assigned-addresses"),
1902  int64_t(0));
1903 
1904  StatsMgr::instance().setValue(
1905  StatsMgr::generateName("subnet", id, "declined-addresses"),
1906  int64_t(0));
1907 
1908  StatsMgr::instance().addValue("declined-addresses", -previous_declined);
1909  } else {
1910  // Wipe them all!
1912  ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
1913  const Subnet4Collection * subs = subnets->getAll();
1914 
1915  // Go over all subnets and wipe leases in each of them.
1916  for (auto sub : *subs) {
1917  num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
1918  ids << " " << sub->getID();
1919  StatsMgr::instance().setValue(
1920  StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
1921  int64_t(0));
1922 
1923  StatsMgr::instance().setValue(
1924  StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
1925  int64_t(0));
1926  }
1927 
1928  StatsMgr::instance().setValue("declined-addresses", int64_t(0));
1929  }
1930 
1931  stringstream tmp;
1932  tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
1934  : CONTROL_RESULT_EMPTY, tmp.str());
1935  setResponse(handle, response);
1936  } catch (const std::exception& ex) {
1937  setErrorResponse(handle, ex.what());
1938  return (1);
1939  }
1940 
1941  return (0);
1942 }
1943 
1944 int
1945 LeaseCmdsImpl::lease6WipeHandler(CalloutHandle& handle) {
1946  try {
1947  extractCommand(handle);
1948 
1949  SimpleParser parser;
1950  SubnetID id = 0;
1951 
1952  size_t num = 0; // number of leases deleted
1953  stringstream ids; // a text with subnet-ids being wiped
1954 
1960 
1961  // The subnet-id parameter is now optional.
1962  if (cmd_args_ && cmd_args_->contains("subnet-id")) {
1963  id = parser.getUint32(cmd_args_, "subnet-id");
1964  }
1965 
1966  if (id) {
1967  // Wipe a single subnet.
1969  ids << " " << id;
1970 
1971  auto observation = StatsMgr::instance().getObservation(
1972  StatsMgr::generateName("subnet", id, "declined-addresses"));
1973 
1974  int64_t previous_declined = 0;
1975 
1976  if (observation) {
1977  previous_declined = observation->getInteger().first;
1978  }
1979 
1980  StatsMgr::instance().setValue(
1981  StatsMgr::generateName("subnet", id, "assigned-nas" ),
1982  int64_t(0));
1983 
1984  StatsMgr::instance().setValue(
1985  StatsMgr::generateName("subnet", id, "assigned-pds"),
1986  int64_t(0));
1987 
1988  StatsMgr::instance().setValue(
1989  StatsMgr::generateName("subnet", id, "declined-addresses"),
1990  int64_t(0));
1991 
1992  StatsMgr::instance().addValue("declined-addresses", -previous_declined);
1993  } else {
1994  // Wipe them all!
1996  ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
1997  const Subnet6Collection * subs = subnets->getAll();
1998 
1999  // Go over all subnets and wipe leases in each of them.
2000  for (auto sub : *subs) {
2001  num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2002  ids << " " << sub->getID();
2003  StatsMgr::instance().setValue(
2004  StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2005  int64_t(0));
2006 
2007  StatsMgr::instance().setValue(
2008  StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2009  int64_t(0));
2010 
2011  StatsMgr::instance().setValue(
2012  StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2013  int64_t(0));
2014  }
2015 
2016  StatsMgr::instance().setValue("declined-addresses", int64_t(0));
2017  }
2018 
2019  stringstream tmp;
2020  tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2022  : CONTROL_RESULT_EMPTY, tmp.str());
2023  setResponse(handle, response);
2024  } catch (const std::exception& ex) {
2025  setErrorResponse(handle, ex.what());
2026  return (1);
2027  }
2028 
2029  return (0);
2030 }
2031 
2032 Lease6Ptr
2033 LeaseCmdsImpl::getIPv6LeaseForDelete(const Parameters& parameters) const {
2034  Lease6Ptr lease6;
2035 
2036  switch (parameters.query_type) {
2037  case Parameters::TYPE_ADDR: {
2038  // If address was specified explicitly, let's use it as is.
2039 
2040  // Let's see if there's such a lease at all.
2041  lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2042  parameters.addr);
2043  if (!lease6) {
2044  lease6.reset(new Lease6());
2045  lease6->addr_ = parameters.addr;
2046  }
2047  break;
2048  }
2049  case Parameters::TYPE_HWADDR: {
2050  isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2051  break;
2052  }
2053  case Parameters::TYPE_DUID: {
2054  if (!parameters.duid) {
2055  isc_throw(InvalidParameter, "Program error: Query by duid "
2056  "requires duid to be specified");
2057  }
2058 
2059  // Let's see if there's such a lease at all.
2060  lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2061  *parameters.duid,
2062  parameters.iaid,
2063  parameters.subnet_id);
2064  break;
2065  }
2066  default:
2067  isc_throw(InvalidOperation, "Unknown query type: "
2068  << static_cast<int>(parameters.query_type));
2069  }
2070 
2071  return (lease6);
2072 }
2073 
2074 IOAddress
2075 LeaseCmdsImpl::getAddressParam(ConstElementPtr params, const std::string name,
2076  short family) const {
2077  ConstElementPtr param = params->get(name);
2078  if (!param) {
2079  isc_throw(BadValue, "'" << name << "' parameter is missing.");
2080  }
2081 
2082  if (param->getType() != Element::string) {
2083  isc_throw(BadValue, "'" << name << "' is not a string.");
2084  }
2085 
2086  IOAddress addr(0);
2087  try {
2088  addr = IOAddress(param->stringValue());
2089  } catch (const std::exception& ex) {
2090  isc_throw(BadValue, "'" << param->stringValue()
2091  << "' is not a valid IP address.");
2092  }
2093 
2094  if (addr.getFamily() != family) {
2095  isc_throw(BadValue, "Invalid "
2096  << (family == AF_INET6 ? "IPv6" : "IPv4")
2097  << " address specified: " << param->stringValue());
2098  }
2099 
2100  return (addr);
2101 }
2102 
2103 int
2104 LeaseCmdsImpl::lease4ResendDdnsHandler(CalloutHandle& handle) {
2105  std::stringstream ss;
2106  int resp_code = CONTROL_RESULT_ERROR;
2107 
2108  try {
2109  extractCommand(handle);
2110 
2111  // Get the target lease address. Invalid value will throw.
2112  IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2113 
2114  if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2115  ss << "DDNS updating is not enabled";
2116  } else {
2117  // Find the lease.
2119  if (!lease) {
2120  ss << "No lease found for: " << addr.toText();
2121  resp_code = CONTROL_RESULT_EMPTY;
2122  } else if (lease->hostname_.empty()) {
2123  ss << "Lease for: " << addr.toText()
2124  << ", has no hostname, nothing to update";
2125  } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2126  ss << "Neither forward nor reverse updates enabled for lease for: "
2127  << addr.toText();
2128  } else {
2129  // We have a lease with a hostname and updates in at least
2130  // one direction enabled. Queue an NCR for it.
2131  queueNCR(CHG_ADD, lease);
2132  ss << "NCR generated for: " << addr.toText()
2133  << ", hostname: " << lease->hostname_;
2134  setSuccessResponse(handle, ss.str());
2136  return (0);
2137  }
2138  }
2139  } catch (const std::exception& ex) {
2140  ss << ex.what();
2141  }
2142 
2144  setErrorResponse(handle, ss.str(), resp_code);
2145  return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2146 }
2147 
2148 int
2149 LeaseCmdsImpl::lease6ResendDdnsHandler(CalloutHandle& handle) {
2150  std::stringstream ss;
2151  int resp_code = CONTROL_RESULT_ERROR;
2152 
2153  try {
2154  extractCommand(handle);
2155 
2156  // Get the target lease address. Invalid value will throw.
2157  IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2158 
2159  if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2160  ss << "DDNS updating is not enabled";
2161  } else {
2162  // Find the lease.
2164  if (!lease) {
2165  ss << "No lease found for: " << addr.toText();
2166  resp_code = CONTROL_RESULT_EMPTY;
2167  } else if (lease->hostname_.empty()) {
2168  ss << "Lease for: " << addr.toText()
2169  << ", has no hostname, nothing to update";
2170  } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2171  ss << "Neither forward nor reverse updates enabled for lease for: "
2172  << addr.toText();
2173  } else {
2174  // We have a lease with a hostname and updates in at least
2175  // one direction enabled. Queue an NCR for it.
2176  queueNCR(CHG_ADD, lease);
2177  ss << "NCR generated for: " << addr.toText()
2178  << ", hostname: " << lease->hostname_;
2179  setSuccessResponse(handle, ss.str());
2181  return (0);
2182  }
2183  }
2184  } catch (const std::exception& ex) {
2185  ss << ex.what();
2186  }
2187 
2189  setErrorResponse(handle, ss.str(), resp_code);
2190  return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2191 }
2192 
2193 ElementPtr
2194 LeaseCmdsImpl::createFailedLeaseMap(const Lease::Type& lease_type,
2195  const IOAddress& lease_address,
2196  const DuidPtr& duid,
2197  const int control_result,
2198  const std::string& error_message) const {
2199  auto failed_lease_map = Element::createMap();
2200  failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2201 
2202  if (!lease_address.isV6Zero()) {
2203  failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2204 
2205  } else if (duid) {
2206  failed_lease_map->set("duid", Element::create(duid->toText()));
2207  }
2208 
2209  // Associate the result with the lease.
2210  failed_lease_map->set("result", Element::create(control_result));
2211  failed_lease_map->set("error-message", Element::create(error_message));
2212 
2213  return (failed_lease_map);
2214 }
2215 
2216 int
2217 LeaseCmds::leaseAddHandler(CalloutHandle& handle) {
2218  return (impl_->leaseAddHandler(handle));
2219 }
2220 
2221 int
2222 LeaseCmds::lease6BulkApplyHandler(CalloutHandle& handle) {
2223  return (impl_->lease6BulkApplyHandler(handle));
2224 }
2225 
2226 int
2227 LeaseCmds::leaseGetHandler(CalloutHandle& handle) {
2228  return (impl_->leaseGetHandler(handle));
2229 }
2230 
2231 int
2232 LeaseCmds::leaseGetAllHandler(hooks::CalloutHandle& handle) {
2233  return (impl_->leaseGetAllHandler(handle));
2234 }
2235 
2236 int
2237 LeaseCmds::leaseGetPageHandler(hooks::CalloutHandle& handle) {
2238  return (impl_->leaseGetPageHandler(handle));
2239 }
2240 
2241 int
2242 LeaseCmds::leaseGetByHwAddressHandler(hooks::CalloutHandle& handle) {
2243  return (impl_->leaseGetByHwAddressHandler(handle));
2244 }
2245 
2246 int
2247 LeaseCmds::leaseGetByClientIdHandler(hooks::CalloutHandle& handle) {
2248  return (impl_->leaseGetByClientIdHandler(handle));
2249 }
2250 
2251 int
2252 LeaseCmds::leaseGetByDuidHandler(hooks::CalloutHandle& handle) {
2253  return (impl_->leaseGetByDuidHandler(handle));
2254 }
2255 
2256 int
2257 LeaseCmds::leaseGetByHostnameHandler(hooks::CalloutHandle& handle) {
2258  return (impl_->leaseGetByHostnameHandler(handle));
2259 }
2260 
2261 int
2262 LeaseCmds::lease4DelHandler(CalloutHandle& handle) {
2263  return (impl_->lease4DelHandler(handle));
2264 }
2265 
2266 int
2267 LeaseCmds::lease6DelHandler(CalloutHandle& handle) {
2268  return (impl_->lease6DelHandler(handle));
2269 }
2270 
2271 int
2272 LeaseCmds::lease4UpdateHandler(CalloutHandle& handle) {
2273  return (impl_->lease4UpdateHandler(handle));
2274 }
2275 
2276 int
2277 LeaseCmds::lease6UpdateHandler(CalloutHandle& handle) {
2278  return (impl_->lease6UpdateHandler(handle));
2279 }
2280 
2281 int
2282 LeaseCmds::lease4WipeHandler(CalloutHandle& handle) {
2284  return (impl_->lease4WipeHandler(handle));
2285 }
2286 
2287 int
2288 LeaseCmds::lease6WipeHandler(CalloutHandle& handle) {
2290  return (impl_->lease6WipeHandler(handle));
2291 }
2292 
2293 int
2294 LeaseCmds::lease4ResendDdnsHandler(CalloutHandle& handle) {
2295  return (impl_->lease4ResendDdnsHandler(handle));
2296 }
2297 
2298 int
2299 LeaseCmds::lease6ResendDdnsHandler(CalloutHandle& handle) {
2300  return (impl_->lease6ResendDdnsHandler(handle));
2301 }
2302 
2303 LeaseCmds::LeaseCmds()
2304  :impl_(new LeaseCmdsImpl()) {
2305 }
2306 
2307 } // end of namespace lease_cmds
2308 } // end of namespace isc
RAII class creating a critical section.
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
const isc::log::MessageID LEASE_CMDS_ADD6_FAILED
const isc::log::MessageID LEASE_CMDS_ADD4_FAILED
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Definition: duid.cc:132
Parser for Lease4 structure.
Definition: lease_parser.h:35
HWAddrPtr hwaddr
Specifies hardware address (used when query_type is TYPE_HWADDR)
Definition: lease_cmds.cc:74
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
virtual size_t wipeLeases4(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:52
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.
An abstract API for lease database.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
Attempt to update lease that was not there.
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6_FAILED
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:482
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4
Resource race avoidance RAII handler for DHCPv4.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:48
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
STL namespace.
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition: duid.cc:62
Type query_type
specifies parameter types
Definition: lease_cmds.cc:108
SubnetID subnet_id
Specifies subnet-id (always used)
Definition: lease_cmds.cc:68
const isc::log::MessageID LEASE_CMDS_ADD4
boost::shared_ptr< const CfgSubnets4 > ConstCfgSubnets4Ptr
Const pointer.
Definition: cfg_subnets4.h:336
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
Resource race avoidance RAII handler.
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
isc::log::Logger lease_cmds_logger("lease-cmds-hooks")
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
boost::shared_ptr< const SrvConfig > ConstSrvConfigPtr
Const pointer to the SrvConfig.
Definition: srv_config.h:1168
Definition: edns.h:19
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED
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:291
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:893
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:278
Per-packet callout handle.
Wrapper class around reservation command handlers.
Definition: lease_cmds.cc:52
Thrown by lock users when a resource lock cannot be obtained.
boost::shared_ptr< const CfgSubnets6 > ConstCfgSubnets6Ptr
Const pointer.
Definition: cfg_subnets6.h:334
Parser for Lease6 structure.
Definition: lease_parser.h:76
IPv4 lease.
Definition: lease.h:49
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:498
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:635
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual Lease4Collection getLeases4(SubnetID subnet_id) const =0
Returns all IPv4 leases for the particular subnet identifier.
IOAddress addr
Specifies IPv4/v6 address (used when query_type is TYPE_ADDR)
Definition: lease_cmds.cc:71
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition: duid.h:103
the lease contains temporary IPv6 address
Definition: lease.h:47
Type
specifies type of query (by IP addr, by hwaddr, by DUID)
Definition: lease_cmds.cc:60
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
the lease contains non-temporary IPv6 address
Definition: lease.h:46
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:964
Lease::Type lease_type
Lease type (NA,TA or PD) used for v6 leases.
Definition: lease_cmds.cc:111
query by IP address (either v4 or v6)
Definition: lease_cmds.cc:61
Defines the logger used by the top-level component of kea-lfc.
This file contains several functions and constants that are used for handling commands and responses ...
bool updateDDNS
Indicates whether or not DNS should be updated.
Definition: lease_cmds.cc:117
Base class that command handler implementers may use for common tasks.
Definition: cmds_impl.h:21
a common structure for IPv4 and IPv6 leases
Definition: lease.h:30
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:70
Type
Type of lease or pool.
Definition: lease.h:45
A generic exception that is thrown if a function is called in a prohibited way.
Parameters specified for lease commands.
Definition: lease_cmds.cc:56
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
static Type txtToType(const std::string &txt)
Attempts to covert text to one of specified types.
Definition: lease_cmds.cc:91
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
query by hardware address (v4 only)
Definition: lease_cmds.cc:62
virtual size_t wipeLeases6(const SubnetID &subnet_id)=0
Virtual method which removes specified leases.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
const isc::log::MessageID LEASE_CMDS_ADD6
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
isc::dhcp::DuidPtr duid
Specifies identifier value (used when query_type is TYPE_DUID)
Definition: lease_cmds.cc:77
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:44
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.
Definition: lease_parser.cc:26
static LeaseMgr & 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.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:487
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
Database duplicate entry error.
Definition: db_exceptions.h:30
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
isc::dhcp::ClientIdPtr client_id
Specifies identifier value (used when query_type is TYPE_CLIENT_ID)
Definition: lease_cmds.cc:80
uint32_t iaid
IAID identifier used for v6 leases.
Definition: lease_cmds.cc:114
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.