Kea  1.9.9-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 
736  if (lease4) {
737  bool success;
738  if (MultiThreadingMgr::instance().getMode() &&
739  !MultiThreadingMgr::instance().isInCriticalSection()) {
740  bool use_cs = false;
741  {
742  // Try to avoid a race.
743  ResourceHandler4 resource_handler;
744  use_cs = !resource_handler.tryLock4(lease4->addr_);
745  if (!use_cs) {
746  success = LeaseMgrFactory::instance().addLease(lease4);
747  }
748  }
749  if (use_cs) {
750  // Failed to avoid the race.
752  success = LeaseMgrFactory::instance().addLease(lease4);
753  }
754  } else {
755  // No multi-threading.
756  success = LeaseMgrFactory::instance().addLease(lease4);
757  }
758  if (!success) {
759  isc_throw(db::DuplicateEntry, "IPv4 lease already exists.");
760  }
761  LeaseCmdsImpl::updateStatsOnAdd(lease4);
762  resp << "Lease for address " << lease4->addr_.toText()
763  << ", subnet-id " << lease4->subnet_id_ << " added.";
764  }
765 
766  } else {
767  Lease6Parser parser;
768  lease6 = parser.parse(config, cmd_args_, force_create);
769 
770  if (lease6) {
771  bool success;
772  if (MultiThreadingMgr::instance().getMode() &&
773  !MultiThreadingMgr::instance().isInCriticalSection()) {
774  bool use_cs = false;
775  {
776  // Try to avoid a race.
777  ResourceHandler resource_handler;
778  use_cs = !resource_handler.tryLock(lease6->type_,
779  lease6->addr_);
780  if (!use_cs) {
781  success = LeaseMgrFactory::instance().addLease(lease6);
782  }
783  }
784  if (use_cs) {
785  // Failed to avoid the race.
787  success = LeaseMgrFactory::instance().addLease(lease6);
788  }
789  } else {
790  // No multi-threading.
791  success = LeaseMgrFactory::instance().addLease(lease6);
792  }
793  if (!success) {
794  isc_throw(db::DuplicateEntry, "IPv6 lease already exists.");
795  }
796  LeaseCmdsImpl::updateStatsOnAdd(lease6);
797  if (lease6->type_ == Lease::TYPE_NA) {
798  resp << "Lease for address " << lease6->addr_.toText()
799  << ", subnet-id " << lease6->subnet_id_ << " added.";
800  } else {
801  resp << "Lease for prefix " << lease6->addr_.toText()
802  << "/" << static_cast<int>(lease6->prefixlen_)
803  << ", subnet-id " << lease6->subnet_id_ << " added.";
804  }
805  }
806  }
807 
808  } catch (const std::exception& ex) {
810  .arg(txt)
811  .arg(ex.what());
812  setErrorResponse(handle, ex.what());
813  return (1);
814  }
815 
817  v4 ? LEASE_CMDS_ADD4 : LEASE_CMDS_ADD6).arg(txt);
818  setSuccessResponse(handle, resp.str());
819  return (0);
820 }
821 
823 LeaseCmdsImpl::getParameters(bool v6, const ConstElementPtr& params) {
824  Parameters x;
825 
826  if (!params || params->getType() != Element::map) {
827  isc_throw(BadValue, "Parameters missing or are not a map.");
828  }
829 
830  if (params->contains("update-ddns")) {
831  ConstElementPtr tmp = params->get("update-ddns");
832  if (tmp->getType() != Element::boolean) {
833  isc_throw(BadValue, "'update-ddns' is not a boolean");
834  } else {
835  x.updateDDNS = tmp->boolValue();
836  }
837  }
838 
839  // We support several sets of parameters for leaseX-get/lease-del:
840  // lease-get(type, address)
841  // lease-get(type, subnet-id, identifier-type, identifier)
842 
843  if (params->contains("type")) {
844  string t = params->get("type")->stringValue();
845  if (t == "IA_NA" || t == "0") {
847  } else if (t == "IA_TA" || t == "1") {
849  } else if (t == "IA_PD" || t == "2") {
851  } else if (t == "V4" || t == "3") {
853  } else {
854  isc_throw(BadValue, "Invalid lease type specified: "
855  << t << ", only supported values are: IA_NA, IA_TA,"
856  << " IA_PD and V4");
857  }
858  }
859 
860  ConstElementPtr tmp = params->get("ip-address");
861  if (tmp) {
862  if (tmp->getType() != Element::string) {
863  isc_throw(BadValue, "'ip-address' is not a string.");
864  }
865 
866  x.addr = IOAddress(tmp->stringValue());
867 
868  if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
869  stringstream txt;
870  txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
871  << " address specified: " << tmp->stringValue();
872  isc_throw(BadValue, txt.str());
873  }
874 
875  x.query_type = Parameters::TYPE_ADDR;
876  return (x);
877  }
878 
879  tmp = params->get("subnet-id");
880  if (!tmp) {
881  isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
882  }
883  if (tmp->getType() != Element::integer) {
884  isc_throw(BadValue, "'subnet-id' parameter is not integer.");
885  }
886  x.subnet_id = tmp->intValue();
887 
888  if (params->contains("iaid")) {
889  x.iaid = params->get("iaid")->intValue();
890  }
891 
892  // No address specified. Ok, so it must be identifier based query.
893  // "identifier-type": "duid",
894  // "identifier": "aa:bb:cc:dd:ee:..."
895 
896  ConstElementPtr type = params->get("identifier-type");
897  ConstElementPtr ident = params->get("identifier");
898  if (!type || type->getType() != Element::string) {
899  isc_throw(BadValue, "No 'ip-address' provided"
900  " and 'identifier-type' is either missing or not a string.");
901  }
902  if (!ident || ident->getType() != Element::string) {
903  isc_throw(BadValue, "No 'ip-address' provided"
904  " and 'identifier' is either missing or not a string.");
905  }
906 
907  // Got the parameters. Let's see if their values make sense.
908  // Try to convert identifier-type
909  x.query_type = Parameters::txtToType(type->stringValue());
910 
911  switch (x.query_type) {
912  case Parameters::TYPE_HWADDR: {
913  HWAddr hw = HWAddr::fromText(ident->stringValue());
914  x.hwaddr = HWAddrPtr(new HWAddr(hw));
915  break;
916  }
917  case Parameters::TYPE_CLIENT_ID: {
918  x.client_id = ClientId::fromText(ident->stringValue());
919  break;
920  }
921  case Parameters::TYPE_DUID: {
922  DUID duid = DUID::fromText(ident->stringValue());
923  x.duid = DuidPtr(new DUID(duid));
924  break;
925  }
926  case Parameters::TYPE_ADDR: {
927  // We should never get here. The address clause should have been caught
928  // earlier.
929  return (x);
930  }
931  default: {
932  isc_throw(BadValue, "Identifier type " << type->stringValue() <<
933  " is not supported.");
934  }
935  }
936 
937  return (x);
938 }
939 
940 int
941 LeaseCmdsImpl::leaseGetHandler(CalloutHandle& handle) {
942  Parameters p;
943  Lease4Ptr lease4;
944  Lease6Ptr lease6;
945  bool v4;
946  try {
947  extractCommand(handle);
948  v4 = (cmd_name_ == "lease4-get");
949 
950  p = getParameters(!v4, cmd_args_);
951  switch (p.query_type) {
952  case Parameters::TYPE_ADDR: {
953  // Query by address
954  if (v4) {
956  } else {
958  }
959  break;
960  }
961  case Parameters::TYPE_HWADDR:
962  if (v4) {
963  if (!p.hwaddr) {
964  isc_throw(InvalidParameter, "Program error: Query by hw-address "
965  "requires hwaddr to be specified");
966  }
967 
969  } else {
970  isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
971  }
972  break;
973 
974  case Parameters::TYPE_DUID:
975  if (!v4) {
976  if (!p.duid) {
977  isc_throw(InvalidParameter, "Program error: Query by duid "
978  "requires duid to be specified");
979  }
980 
982  p.iaid, p.subnet_id);
983  } else {
984  isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
985  }
986  break;
987 
988  case Parameters::TYPE_CLIENT_ID:
989  if (v4) {
990  if (!p.client_id) {
991  isc_throw(InvalidParameter, "Program error: Query by client-id "
992  "requires client-id to be specified");
993  }
994 
996  } else {
997  isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
998  }
999  break;
1000 
1001  default: {
1002  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1003  break;
1004  }
1005  }
1006  } catch (const std::exception& ex) {
1007  setErrorResponse(handle, ex.what());
1008  return (1);
1009  }
1010 
1011  ElementPtr lease_json;
1012  if (v4 && lease4) {
1013  lease_json = lease4->toElement();
1015  "IPv4 lease found.", lease_json);
1016  setResponse(handle, response);
1017  } else if (!v4 && lease6) {
1018  lease_json = lease6->toElement();
1020  "IPv6 lease found.", lease_json);
1021  setResponse(handle, response);
1022  } else {
1023  // If we got here, the lease has not been found.
1024  setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
1025  }
1026 
1027  return (0);
1028 }
1029 
1030 int
1031 LeaseCmdsImpl::leaseGetAllHandler(CalloutHandle& handle) {
1032  bool v4 = true;
1033  try {
1034  extractCommand(handle);
1035  v4 = (cmd_name_ == "lease4-get-all");
1036 
1037  ElementPtr leases_json = Element::createList();
1038 
1039  // The argument may contain a list of subnets for which leases should
1040  // be returned.
1041  if (cmd_args_) {
1042  ConstElementPtr subnets = cmd_args_->get("subnets");
1043  if (!subnets) {
1044  isc_throw(BadValue, "'subnets' parameter not specified");
1045  }
1046  if (subnets->getType() != Element::list) {
1047  isc_throw(BadValue, "'subnets' parameter must be a list");
1048  }
1049 
1050  const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
1051  for (auto subnet_id = subnet_ids.begin();
1052  subnet_id != subnet_ids.end();
1053  ++subnet_id) {
1054  if ((*subnet_id)->getType() != Element::integer) {
1055  isc_throw(BadValue, "listed subnet identifiers must be numbers");
1056  }
1057 
1058  if (v4) {
1059  Lease4Collection leases =
1060  LeaseMgrFactory::instance().getLeases4((*subnet_id)->intValue());
1061  for (auto lease : leases) {
1062  ElementPtr lease_json = lease->toElement();
1063  leases_json->add(lease_json);
1064  }
1065  } else {
1066  Lease6Collection leases =
1067  LeaseMgrFactory::instance().getLeases6((*subnet_id)->intValue());
1068  for (auto lease : leases) {
1069  ElementPtr lease_json = lease->toElement();
1070  leases_json->add(lease_json);
1071  }
1072  }
1073  }
1074 
1075  } else {
1076  // There is no 'subnets' argument so let's return all leases.
1077  if (v4) {
1079  for (auto lease : leases) {
1080  ElementPtr lease_json = lease->toElement();
1081  leases_json->add(lease_json);
1082  }
1083  } else {
1085  for (auto lease : leases) {
1086  ElementPtr lease_json = lease->toElement();
1087  leases_json->add(lease_json);
1088  }
1089  }
1090  }
1091 
1092  std::ostringstream s;
1093  s << leases_json->size()
1094  << " IPv" << (v4 ? "4" : "6")
1095  << " lease(s) found.";
1096  ElementPtr args = Element::createMap();
1097  args->set("leases", leases_json);
1098  ConstElementPtr response =
1099  createAnswer(leases_json->size() > 0 ?
1102  s.str(), args);
1103  setResponse(handle, response);
1104 
1105  } catch (const std::exception& ex) {
1106  setErrorResponse(handle, ex.what());
1107  return (CONTROL_RESULT_ERROR);
1108  }
1109 
1110  return (0);
1111 }
1112 
1113 int
1114 LeaseCmdsImpl::leaseGetPageHandler(CalloutHandle& handle) {
1115  bool v4 = true;
1116  try {
1117  extractCommand(handle);
1118  v4 = (cmd_name_ == "lease4-get-page");
1119 
1120  // arguments must always be present
1121  if (!cmd_args_) {
1122  isc_throw(BadValue, "no parameters specified for the " << cmd_name_
1123  << " command");
1124  }
1125 
1126  // The 'from' argument denotes from which lease we should start the
1127  // results page. The results page excludes this lease.
1128  ConstElementPtr from = cmd_args_->get("from");
1129  if (!from) {
1130  isc_throw(BadValue, "'from' parameter not specified");
1131  }
1132 
1133  // The 'from' argument is a string. It may contain a 'start' keyword or
1134  // an IP address.
1135  if (from->getType() != Element::string) {
1136  isc_throw(BadValue, "'from' parameter must be a string");
1137  }
1138 
1139  boost::scoped_ptr<IOAddress> from_address;
1140  try {
1141  if (from->stringValue() == "start") {
1142  from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
1143 
1144  } else {
1145  // Conversion of a string to an IP address may throw.
1146  from_address.reset(new IOAddress(from->stringValue()));
1147  }
1148 
1149  } catch (...) {
1150  isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
1151  "a valid IPv" << (v4 ? "4" : "6") << " address");
1152  }
1153 
1154  // It must be either IPv4 address for lease4-get-page or IPv6 address for
1155  // lease6-get-page.
1156  if (v4 && (!from_address->isV4())) {
1157  isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1158  << " is not an IPv4 address");
1159 
1160  } else if (!v4 && from_address->isV4()) {
1161  isc_throw(BadValue, "'from' parameter value " << from_address->toText()
1162  << " is not an IPv6 address");
1163  }
1164 
1165  // The 'limit' is a desired page size. It must always be present.
1166  ConstElementPtr page_limit = cmd_args_->get("limit");
1167  if (!page_limit) {
1168  isc_throw(BadValue, "'limit' parameter not specified");
1169  }
1170 
1171  // The 'limit' must be a number.
1172  if (page_limit->getType() != Element::integer) {
1173  isc_throw(BadValue, "'limit' parameter must be a number");
1174  }
1175 
1176  // Retrieve the desired page size.
1177  size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
1178 
1179  ElementPtr leases_json = Element::createList();
1180 
1181  if (v4) {
1182  // Get page of IPv4 leases.
1183  Lease4Collection leases =
1184  LeaseMgrFactory::instance().getLeases4(*from_address,
1185  LeasePageSize(page_limit_value));
1186 
1187  // Convert leases into JSON list.
1188  for (auto lease : leases) {
1189  ElementPtr lease_json = lease->toElement();
1190  leases_json->add(lease_json);
1191  }
1192 
1193  } else {
1194  // Get page of IPv6 leases.
1195  Lease6Collection leases =
1196  LeaseMgrFactory::instance().getLeases6(*from_address,
1197  LeasePageSize(page_limit_value));
1198  // Convert leases into JSON list.
1199  for (auto lease : leases) {
1200  ElementPtr lease_json = lease->toElement();
1201  leases_json->add(lease_json);
1202  }
1203  }
1204 
1205  // Prepare textual status.
1206  std::ostringstream s;
1207  s << leases_json->size()
1208  << " IPv" << (v4 ? "4" : "6")
1209  << " lease(s) found.";
1210  ElementPtr args = Element::createMap();
1211 
1212  // Put gathered data into arguments map.
1213  args->set("leases", leases_json);
1214  args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
1215 
1216  // Create the response.
1217  ConstElementPtr response =
1218  createAnswer(leases_json->size() > 0 ?
1221  s.str(), args);
1222  setResponse(handle, response);
1223 
1224  } catch (const std::exception& ex) {
1225  setErrorResponse(handle, ex.what());
1226  return (CONTROL_RESULT_ERROR);
1227  }
1228 
1229  return (CONTROL_RESULT_SUCCESS);
1230 }
1231 
1232 int
1233 LeaseCmdsImpl::leaseGetByHwAddressHandler(CalloutHandle& handle) {
1234  try {
1235  extractCommand(handle);
1236 
1237  // arguments must always be present
1238  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1239  isc_throw(BadValue, "Command arguments missing or a not a map.");
1240  }
1241 
1242  // the hw-address parameter is mandatory.
1243  ConstElementPtr hw_address = cmd_args_->get("hw-address");
1244  if (!hw_address) {
1245  isc_throw(BadValue, "'hw-address' parameter not specified");
1246  }
1247 
1248  // The 'hw-address' argument is a string.
1249  if (hw_address->getType() != Element::string) {
1250  isc_throw(BadValue, "'hw-address' parameter must be a string");
1251  }
1252 
1253  HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue());
1254 
1255  Lease4Collection leases =
1257  ElementPtr leases_json = Element::createList();
1258  for (auto lease : leases) {
1259  ElementPtr lease_json = lease->toElement();
1260  leases_json->add(lease_json);
1261  }
1262 
1263  std::ostringstream s;
1264  s << leases_json->size() << " IPv4 lease(s) found.";
1265  ElementPtr args = Element::createMap();
1266  args->set("leases", leases_json);
1267  ConstElementPtr response =
1268  createAnswer(leases_json->size() > 0 ?
1271  s.str(), args);
1272  setResponse(handle, response);
1273 
1274  } catch (const std::exception& ex) {
1275  setErrorResponse(handle, ex.what());
1276  return (CONTROL_RESULT_ERROR);
1277  }
1278 
1279  return (0);
1280 }
1281 
1282 int
1283 LeaseCmdsImpl::leaseGetByClientIdHandler(CalloutHandle& handle) {
1284  try {
1285  extractCommand(handle);
1286 
1287  // arguments must always be present
1288  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1289  isc_throw(BadValue, "Command arguments missing or a not a map.");
1290  }
1291 
1292  // the client-id parameter is mandatory.
1293  ConstElementPtr client_id = cmd_args_->get("client-id");
1294  if (!client_id) {
1295  isc_throw(BadValue, "'client-id' parameter not specified");
1296  }
1297 
1298  // The 'client-id' argument is a string.
1299  if (client_id->getType() != Element::string) {
1300  isc_throw(BadValue, "'client-id' parameter must be a string");
1301  }
1302 
1303  ClientIdPtr clientid = ClientId::fromText(client_id->stringValue());
1304 
1305  Lease4Collection leases =
1306  LeaseMgrFactory::instance().getLease4(*clientid);
1307  ElementPtr leases_json = Element::createList();
1308  for (auto lease : leases) {
1309  ElementPtr lease_json = lease->toElement();
1310  leases_json->add(lease_json);
1311  }
1312 
1313  std::ostringstream s;
1314  s << leases_json->size() << " IPv4 lease(s) found.";
1315  ElementPtr args = Element::createMap();
1316  args->set("leases", leases_json);
1317  ConstElementPtr response =
1318  createAnswer(leases_json->size() > 0 ?
1321  s.str(), args);
1322  setResponse(handle, response);
1323 
1324  } catch (const std::exception& ex) {
1325  setErrorResponse(handle, ex.what());
1326  return (CONTROL_RESULT_ERROR);
1327  }
1328 
1329  return (0);
1330 }
1331 
1332 int
1333 LeaseCmdsImpl::leaseGetByDuidHandler(CalloutHandle& handle) {
1334  try {
1335  extractCommand(handle);
1336 
1337  // arguments must always be present
1338  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1339  isc_throw(BadValue, "Command arguments missing or a not a map.");
1340  }
1341 
1342  // the duid parameter is mandatory.
1343  ConstElementPtr duid = cmd_args_->get("duid");
1344  if (!duid) {
1345  isc_throw(BadValue, "'duid' parameter not specified");
1346  }
1347 
1348  // The 'duid' argument is a string.
1349  if (duid->getType() != Element::string) {
1350  isc_throw(BadValue, "'duid' parameter must be a string");
1351  }
1352 
1353  DUID duid_ = DUID::fromText(duid->stringValue());
1354 
1355  Lease6Collection leases =
1357  ElementPtr leases_json = Element::createList();
1358  for (auto lease : leases) {
1359  ElementPtr lease_json = lease->toElement();
1360  leases_json->add(lease_json);
1361  }
1362 
1363  std::ostringstream s;
1364  s << leases_json->size() << " IPv6 lease(s) found.";
1365  ElementPtr args = Element::createMap();
1366  args->set("leases", leases_json);
1367  ConstElementPtr response =
1368  createAnswer(leases_json->size() > 0 ?
1371  s.str(), args);
1372  setResponse(handle, response);
1373 
1374  } catch (const std::exception& ex) {
1375  setErrorResponse(handle, ex.what());
1376  return (CONTROL_RESULT_ERROR);
1377  }
1378 
1379  return (0);
1380 }
1381 
1382 int
1383 LeaseCmdsImpl::leaseGetByHostnameHandler(CalloutHandle& handle) {
1384  bool v4;
1385  try {
1386  extractCommand(handle);
1387  v4 = (cmd_name_ == "lease4-get-by-hostname");
1388 
1389  // arguments must always be present
1390  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1391  isc_throw(BadValue, "Command arguments missing or a not a map.");
1392  }
1393 
1394  // the hostname parameter is mandatory.
1395  ConstElementPtr hostname = cmd_args_->get("hostname");
1396  if (!hostname) {
1397  isc_throw(BadValue, "'hostname' parameter not specified");
1398  }
1399 
1400  // The 'hostname' argument is a string.
1401  if (hostname->getType() != Element::string) {
1402  isc_throw(BadValue, "'hostname' parameter must be a string");
1403  }
1404 
1405  std::string hostname_ = hostname->stringValue();
1407  if (hostname_.empty()) {
1408  isc_throw(BadValue, "'hostname' parameter is empty");
1409  }
1410  boost::algorithm::to_lower(hostname_);
1411 
1412  ElementPtr leases_json = Element::createList();
1413  if (v4) {
1414  Lease4Collection leases =
1416 
1417  for (auto lease : leases) {
1418  ElementPtr lease_json = lease->toElement();
1419  leases_json->add(lease_json);
1420  }
1421  } else {
1422  Lease6Collection leases =
1424 
1425  for (auto lease : leases) {
1426  ElementPtr lease_json = lease->toElement();
1427  leases_json->add(lease_json);
1428  }
1429  }
1430 
1431  std::ostringstream s;
1432  s << leases_json->size()
1433  << " IPv" << (v4 ? "4" : "6")
1434  << " lease(s) found.";
1435  ElementPtr args = Element::createMap();
1436  args->set("leases", leases_json);
1437  ConstElementPtr response =
1438  createAnswer(leases_json->size() > 0 ?
1441  s.str(), args);
1442  setResponse(handle, response);
1443 
1444  } catch (const std::exception& ex) {
1445  setErrorResponse(handle, ex.what());
1446  return (CONTROL_RESULT_ERROR);
1447  }
1448 
1449  return (0);
1450 }
1451 
1452 int
1453 LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) {
1454  Parameters p;
1455  Lease4Ptr lease4;
1456  try {
1457  extractCommand(handle);
1458  p = getParameters(false, cmd_args_);
1459 
1460  switch (p.query_type) {
1461  case Parameters::TYPE_ADDR: {
1462  // If address was specified explicitly, let's use it as is.
1464  if (!lease4) {
1465  setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1466  return (0);
1467  }
1468  break;
1469  }
1470  case Parameters::TYPE_HWADDR: {
1471  if (!p.hwaddr) {
1472  isc_throw(InvalidParameter, "Program error: Query by hw-address "
1473  "requires hwaddr to be specified");
1474  }
1475 
1476  // Let's see if there's such a lease at all.
1478  if (!lease4) {
1479  setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1480  return (0);
1481  }
1482  break;
1483  }
1484  case Parameters::TYPE_CLIENT_ID: {
1485  if (!p.client_id) {
1486  isc_throw(InvalidParameter, "Program error: Query by client-id "
1487  "requires client-id to be specified");
1488  }
1489 
1490  // Let's see if there's such a lease at all.
1492  if (!lease4) {
1493  setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1494  return (0);
1495  }
1496  break;
1497  }
1498  case Parameters::TYPE_DUID: {
1499  isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
1500  break;
1501  }
1502  default: {
1503  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1504  break;
1505  }
1506  }
1507 
1508  if (LeaseMgrFactory::instance().deleteLease(lease4)) {
1509  setSuccessResponse(handle, "IPv4 lease deleted.");
1510  LeaseCmdsImpl::updateStatsOnDelete(lease4);
1511  } else {
1512  setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
1513  }
1514 
1515  // Queue an NCR to remove DNS if configured and the lease has it.
1516  if (p.updateDDNS) {
1517  queueNCR(CHG_REMOVE, lease4);
1518  }
1519 
1520  } catch (const std::exception& ex) {
1521  setErrorResponse(handle, ex.what());
1522  return (1);
1523  }
1524 
1525  return (0);
1526 }
1527 
1528 int
1529 LeaseCmdsImpl::lease6BulkApplyHandler(CalloutHandle& handle) {
1530  try {
1531  extractCommand(handle);
1532 
1533  // Arguments are mandatory.
1534  if (!cmd_args_ || (cmd_args_->getType() != Element::map)) {
1535  isc_throw(BadValue, "Command arguments missing or a not a map.");
1536  }
1537 
1538  // At least one of the 'deleted-leases' or 'leases' must be present.
1539  auto deleted_leases = cmd_args_->get("deleted-leases");
1540  auto leases = cmd_args_->get("leases");
1541 
1542  if (!deleted_leases && !leases) {
1543  isc_throw(BadValue, "neither 'deleted-leases' nor 'leases' parameter"
1544  " specified");
1545  }
1546 
1547  // Make sure that 'deleted-leases' is a list, if present.
1548  if (deleted_leases && (deleted_leases->getType() != Element::list)) {
1549  isc_throw(BadValue, "the 'deleted-leases' parameter must be a list");
1550  }
1551 
1552  // Make sure that 'leases' is a list, if present.
1553  if (leases && (leases->getType() != Element::list)) {
1554  isc_throw(BadValue, "the 'leases' parameter must be a list");
1555  }
1556 
1557  // Parse deleted leases without deleting them from the database
1558  // yet. If any of the deleted leases or new leases appears to be
1559  // malformed we can easily rollback.
1560  std::list<std::pair<Parameters, Lease6Ptr> > parsed_deleted_list;
1561  if (deleted_leases) {
1562  auto leases_list = deleted_leases->listValue();
1563 
1564  // Iterate over leases to be deleted.
1565  for (auto lease_params : leases_list) {
1566  // Parsing the lease may throw and it means that the lease
1567  // information is malformed.
1568  Parameters p = getParameters(true, lease_params);
1569  auto lease = getIPv6LeaseForDelete(p);
1570  parsed_deleted_list.push_back(std::make_pair(p, lease));
1571  }
1572  }
1573 
1574  // Parse new/updated leases without affecting the database to detect
1575  // any errors that should cause an error response.
1576  std::list<Lease6Ptr> parsed_leases_list;
1577  if (leases) {
1579 
1580  // Iterate over all leases.
1581  auto leases_list = leases->listValue();
1582  for (auto lease_params : leases_list) {
1583 
1584  Lease6Parser parser;
1585  bool force_update;
1586 
1587  // If parsing the lease fails we throw, as it indicates that the
1588  // command is malformed.
1589  Lease6Ptr lease6 = parser.parse(config, lease_params, force_update);
1590  parsed_leases_list.push_back(lease6);
1591  }
1592  }
1593 
1594  // Count successful deletions and updates.
1595  size_t success_count = 0;
1596 
1597  ElementPtr failed_deleted_list;
1598  if (!parsed_deleted_list.empty()) {
1599 
1600  // Iterate over leases to be deleted.
1601  for (auto lease_params_pair : parsed_deleted_list) {
1602 
1603  // This part is outside of the try-catch because an exception
1604  // indicates that the command is malformed.
1605  Parameters p = lease_params_pair.first;
1606  auto lease = lease_params_pair.second;
1607 
1608  try {
1609  if (lease) {
1610  // This may throw if the lease couldn't be deleted for
1611  // any reason, but we still want to proceed with other
1612  // leases.
1613  if (LeaseMgrFactory::instance().deleteLease(lease)) {
1614  ++success_count;
1615  LeaseCmdsImpl::updateStatsOnDelete(lease);
1616 
1617  } else {
1618  // Lazy creation of the list of leases which failed to delete.
1619  if (!failed_deleted_list) {
1620  failed_deleted_list = Element::createList();
1621  }
1622 
1623  // If the lease doesn't exist we also want to put it
1624  // on the list of leases which failed to delete. That
1625  // corresponds to the lease6-del command which returns
1626  // an error when the lease doesn't exist.
1627  failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1628  p.addr, p.duid,
1630  "lease not found"));
1631  }
1632  }
1633 
1634  } catch (const std::exception& ex) {
1635  // Lazy creation of the list of leases which failed to delete.
1636  if (!failed_deleted_list) {
1637  failed_deleted_list = Element::createList();
1638  }
1639  failed_deleted_list->add(createFailedLeaseMap(p.lease_type,
1640  p.addr, p.duid,
1642  ex.what()));
1643  }
1644  }
1645  }
1646 
1647  // Process leases to be added or/and updated.
1648  ElementPtr failed_leases_list;
1649  if (!parsed_leases_list.empty()) {
1651 
1652  // Iterate over all leases.
1653  for (auto lease : parsed_leases_list) {
1654 
1655  try {
1656  if (MultiThreadingMgr::instance().getMode() &&
1657  !MultiThreadingMgr::instance().isInCriticalSection()) {
1658  bool use_cs = false;
1659  {
1660  // Try to avoid a race.
1661  ResourceHandler resource_handler;
1662  use_cs = !resource_handler.tryLock(lease->type_,
1663  lease->addr_);
1664  if (!use_cs) {
1665  addOrUpdate6(lease, true);
1666  }
1667  }
1668  if (use_cs) {
1669  // Failed to avoid the race.
1671  addOrUpdate6(lease, true);
1672  }
1673  } else {
1674  // No multi-threading.
1675  addOrUpdate6(lease, true);
1676  }
1677 
1678  ++success_count;
1679 
1680  } catch (const std::exception& ex) {
1681  // Lazy creation of the list of leases which failed to add/update.
1682  if (!failed_leases_list) {
1683  failed_leases_list = Element::createList();
1684  }
1685  failed_leases_list->add(createFailedLeaseMap(lease->type_,
1686  lease->addr_,
1687  lease->duid_,
1689  ex.what()));
1690  }
1691  }
1692  }
1693 
1694  // Start preparing the response.
1695  ElementPtr args;
1696 
1697  if (failed_deleted_list || failed_leases_list) {
1698  // If there are any failed leases, let's include them in the response.
1699  args = Element::createMap();
1700 
1701  // failed-deleted-leases
1702  if (failed_deleted_list) {
1703  args->set("failed-deleted-leases", failed_deleted_list);
1704  }
1705 
1706  // failed-leases
1707  if (failed_leases_list) {
1708  args->set("failed-deleted-leases", failed_leases_list);
1709  }
1710  }
1711 
1712  // Send the success response and include failed leases.
1713  std::ostringstream resp_text;
1714  resp_text << "Bulk apply of " << success_count << " IPv6 leases completed.";
1715  auto answer = createAnswer(success_count > 0 ? CONTROL_RESULT_SUCCESS :
1716  CONTROL_RESULT_EMPTY, resp_text.str(), args);
1717  setResponse(handle, answer);
1718 
1719  } catch (const std::exception& ex) {
1720  // Unable to parse the command and similar issues.
1721  setErrorResponse(handle, ex.what());
1722  return (CONTROL_RESULT_ERROR);
1723  }
1724 
1725  return (CONTROL_RESULT_SUCCESS);
1726 }
1727 
1728 int
1729 LeaseCmdsImpl::lease6DelHandler(CalloutHandle& handle) {
1730  Parameters p;
1731  Lease6Ptr lease6;
1733  try {
1734  extractCommand(handle);
1735  p = getParameters(true, cmd_args_);
1736 
1737  switch (p.query_type) {
1738  case Parameters::TYPE_ADDR: {
1739  // If address was specified explicitly, let's use it as is.
1740 
1741  // Let's see if there's such a lease at all.
1743  if (!lease6) {
1744  setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1745  return (0);
1746  }
1747  break;
1748  }
1749  case Parameters::TYPE_HWADDR: {
1750  isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
1751  break;
1752  }
1753  case Parameters::TYPE_DUID: {
1754  if (!p.duid) {
1755  isc_throw(InvalidParameter, "Program error: Query by duid "
1756  "requires duid to be specified");
1757  }
1758 
1759  // Let's see if there's such a lease at all.
1761  p.iaid, p.subnet_id);
1762  if (!lease6) {
1763  setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1764  return (0);
1765  }
1766  break;
1767  }
1768  default: {
1769  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
1770  break;
1771  }
1772  }
1773 
1774  if (LeaseMgrFactory::instance().deleteLease(lease6)) {
1775  setSuccessResponse(handle, "IPv6 lease deleted.");
1776  LeaseCmdsImpl::updateStatsOnDelete(lease6);
1777  } else {
1778  setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
1779  }
1780 
1781  // Queue an NCR to remove DNS if configured and the lease has it.
1782  if (p.updateDDNS) {
1783  queueNCR(CHG_REMOVE, lease6);
1784  }
1785 
1786  } catch (const std::exception& ex) {
1787  setErrorResponse(handle, ex.what());
1788  return (1);
1789  }
1790 
1791  return (0);
1792 }
1793 
1794 int
1795 LeaseCmdsImpl::lease4UpdateHandler(CalloutHandle& handle) {
1796  try {
1797  extractCommand(handle);
1798 
1799  // We need the lease to be specified.
1800  if (!cmd_args_) {
1801  isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
1802  }
1803 
1804  // Get the parameters specified by the user first.
1806  Lease4Ptr lease4;
1807  Lease4Parser parser;
1808  bool force_create = false;
1809 
1810  // The parser does sanity checks (if the address is in scope, if
1811  // subnet-id is valid, etc)
1812  lease4 = parser.parse(config, cmd_args_, force_create);
1813  bool added = false;
1814  if (MultiThreadingMgr::instance().getMode() &&
1815  !MultiThreadingMgr::instance().isInCriticalSection()) {
1816  bool use_cs = false;
1817  {
1818  // Try to avoid a race.
1819  ResourceHandler4 resource_handler;
1820  use_cs = !resource_handler.tryLock4(lease4->addr_);
1821  if (!use_cs) {
1822  added = addOrUpdate4(lease4, force_create);
1823  }
1824  }
1825  if (use_cs) {
1826  // Failed to avoid the race.
1828  added = addOrUpdate4(lease4, force_create);
1829  }
1830  } else {
1831  // No multi-threading.
1832  added = addOrUpdate4(lease4, force_create);
1833  }
1834  if (added) {
1835  setSuccessResponse(handle, "IPv4 lease added.");
1836  } else {
1837  setSuccessResponse(handle, "IPv4 lease updated.");
1838  }
1839  } catch (const std::exception& ex) {
1840  setErrorResponse(handle, ex.what());
1841  return (1);
1842  }
1843 
1844  return (0);
1845 }
1846 
1847 int
1848 LeaseCmdsImpl::lease6UpdateHandler(CalloutHandle& handle) {
1849  try {
1850  extractCommand(handle);
1851 
1852  // We need the lease to be specified.
1853  if (!cmd_args_) {
1854  isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
1855  }
1856 
1857  // Get the parameters specified by the user first.
1859  Lease6Ptr lease6;
1860  Lease6Parser parser;
1861  bool force_create = false;
1862 
1863  // The parser does sanity checks (if the address is in scope, if
1864  // subnet-id is valid, etc)
1865  lease6 = parser.parse(config, cmd_args_, force_create);
1866  bool added;
1867  if (MultiThreadingMgr::instance().getMode() &&
1868  !MultiThreadingMgr::instance().isInCriticalSection()) {
1869  bool use_cs = false;
1870  {
1871  // Try to avoid a race.
1872  ResourceHandler resource_handler;
1873  use_cs = !resource_handler.tryLock(lease6->type_,
1874  lease6->addr_);
1875  if (!use_cs) {
1876  added = addOrUpdate6(lease6, force_create);
1877  }
1878  }
1879  if (use_cs) {
1880  // Failed to avoid the race.
1882  added = addOrUpdate6(lease6, force_create);
1883  }
1884  } else {
1885  // No multi-threading.
1886  added = addOrUpdate6(lease6, force_create);
1887  }
1888  if (added) {
1889  setSuccessResponse(handle, "IPv6 lease added.");
1890  } else {
1891  setSuccessResponse(handle, "IPv6 lease updated.");
1892  }
1893  } catch (const std::exception& ex) {
1894  setErrorResponse(handle, ex.what());
1895  return (1);
1896  }
1897 
1898  return (0);
1899 }
1900 
1901 int
1902 LeaseCmdsImpl::lease4WipeHandler(CalloutHandle& handle) {
1903  try {
1904  extractCommand(handle);
1905 
1906  SimpleParser parser;
1907  SubnetID id = 0;
1908 
1909  size_t num = 0; // number of leases deleted
1910  stringstream ids; // a text with subnet-ids being wiped
1911 
1912  // The subnet-id parameter is now optional.
1913  if (cmd_args_ && cmd_args_->contains("subnet-id")) {
1914  id = parser.getUint32(cmd_args_, "subnet-id");
1915  }
1916 
1917  if (id) {
1918  // Wipe a single subnet.
1920  ids << " " << id;
1921 
1922  auto observation = StatsMgr::instance().getObservation(
1923  StatsMgr::generateName("subnet", id, "declined-addresses"));
1924 
1925  int64_t previous_declined = 0;
1926 
1927  if (observation) {
1928  previous_declined = observation->getInteger().first;
1929  }
1930 
1931  StatsMgr::instance().setValue(
1932  StatsMgr::generateName("subnet", id, "assigned-addresses"),
1933  int64_t(0));
1934 
1935  StatsMgr::instance().setValue(
1936  StatsMgr::generateName("subnet", id, "declined-addresses"),
1937  int64_t(0));
1938 
1939  StatsMgr::instance().addValue("declined-addresses", -previous_declined);
1940  } else {
1941  // Wipe them all!
1943  ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
1944  const Subnet4Collection * subs = subnets->getAll();
1945 
1946  // Go over all subnets and wipe leases in each of them.
1947  for (auto sub : *subs) {
1948  num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
1949  ids << " " << sub->getID();
1950  StatsMgr::instance().setValue(
1951  StatsMgr::generateName("subnet", sub->getID(), "assigned-addresses"),
1952  int64_t(0));
1953 
1954  StatsMgr::instance().setValue(
1955  StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
1956  int64_t(0));
1957  }
1958 
1959  StatsMgr::instance().setValue("declined-addresses", int64_t(0));
1960  }
1961 
1962  stringstream tmp;
1963  tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
1965  : CONTROL_RESULT_EMPTY, tmp.str());
1966  setResponse(handle, response);
1967  } catch (const std::exception& ex) {
1968  setErrorResponse(handle, ex.what());
1969  return (1);
1970  }
1971 
1972  return (0);
1973 }
1974 
1975 int
1976 LeaseCmdsImpl::lease6WipeHandler(CalloutHandle& handle) {
1977  try {
1978  extractCommand(handle);
1979 
1980  SimpleParser parser;
1981  SubnetID id = 0;
1982 
1983  size_t num = 0; // number of leases deleted
1984  stringstream ids; // a text with subnet-ids being wiped
1985 
1991 
1992  // The subnet-id parameter is now optional.
1993  if (cmd_args_ && cmd_args_->contains("subnet-id")) {
1994  id = parser.getUint32(cmd_args_, "subnet-id");
1995  }
1996 
1997  if (id) {
1998  // Wipe a single subnet.
2000  ids << " " << id;
2001 
2002  auto observation = StatsMgr::instance().getObservation(
2003  StatsMgr::generateName("subnet", id, "declined-addresses"));
2004 
2005  int64_t previous_declined = 0;
2006 
2007  if (observation) {
2008  previous_declined = observation->getInteger().first;
2009  }
2010 
2011  StatsMgr::instance().setValue(
2012  StatsMgr::generateName("subnet", id, "assigned-nas" ),
2013  int64_t(0));
2014 
2015  StatsMgr::instance().setValue(
2016  StatsMgr::generateName("subnet", id, "assigned-pds"),
2017  int64_t(0));
2018 
2019  StatsMgr::instance().setValue(
2020  StatsMgr::generateName("subnet", id, "declined-addresses"),
2021  int64_t(0));
2022 
2023  StatsMgr::instance().addValue("declined-addresses", -previous_declined);
2024  } else {
2025  // Wipe them all!
2027  ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
2028  const Subnet6Collection * subs = subnets->getAll();
2029 
2030  // Go over all subnets and wipe leases in each of them.
2031  for (auto sub : *subs) {
2032  num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
2033  ids << " " << sub->getID();
2034  StatsMgr::instance().setValue(
2035  StatsMgr::generateName("subnet", sub->getID(), "assigned-nas" ),
2036  int64_t(0));
2037 
2038  StatsMgr::instance().setValue(
2039  StatsMgr::generateName("subnet", sub->getID(), "assigned-pds"),
2040  int64_t(0));
2041 
2042  StatsMgr::instance().setValue(
2043  StatsMgr::generateName("subnet", sub->getID(), "declined-addresses"),
2044  int64_t(0));
2045  }
2046 
2047  StatsMgr::instance().setValue("declined-addresses", int64_t(0));
2048  }
2049 
2050  stringstream tmp;
2051  tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
2053  : CONTROL_RESULT_EMPTY, tmp.str());
2054  setResponse(handle, response);
2055  } catch (const std::exception& ex) {
2056  setErrorResponse(handle, ex.what());
2057  return (1);
2058  }
2059 
2060  return (0);
2061 }
2062 
2063 Lease6Ptr
2064 LeaseCmdsImpl::getIPv6LeaseForDelete(const Parameters& parameters) const {
2065  Lease6Ptr lease6;
2066 
2067  switch (parameters.query_type) {
2068  case Parameters::TYPE_ADDR: {
2069  // If address was specified explicitly, let's use it as is.
2070 
2071  // Let's see if there's such a lease at all.
2072  lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2073  parameters.addr);
2074  if (!lease6) {
2075  lease6.reset(new Lease6());
2076  lease6->addr_ = parameters.addr;
2077  }
2078  break;
2079  }
2080  case Parameters::TYPE_HWADDR: {
2081  isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
2082  break;
2083  }
2084  case Parameters::TYPE_DUID: {
2085  if (!parameters.duid) {
2086  isc_throw(InvalidParameter, "Program error: Query by duid "
2087  "requires duid to be specified");
2088  }
2089 
2090  // Let's see if there's such a lease at all.
2091  lease6 = LeaseMgrFactory::instance().getLease6(parameters.lease_type,
2092  *parameters.duid,
2093  parameters.iaid,
2094  parameters.subnet_id);
2095  break;
2096  }
2097  default:
2098  isc_throw(InvalidOperation, "Unknown query type: "
2099  << static_cast<int>(parameters.query_type));
2100  }
2101 
2102  return (lease6);
2103 }
2104 
2105 IOAddress
2106 LeaseCmdsImpl::getAddressParam(ConstElementPtr params, const std::string name,
2107  short family) const {
2108  ConstElementPtr param = params->get(name);
2109  if (!param) {
2110  isc_throw(BadValue, "'" << name << "' parameter is missing.");
2111  }
2112 
2113  if (param->getType() != Element::string) {
2114  isc_throw(BadValue, "'" << name << "' is not a string.");
2115  }
2116 
2117  IOAddress addr(0);
2118  try {
2119  addr = IOAddress(param->stringValue());
2120  } catch (const std::exception& ex) {
2121  isc_throw(BadValue, "'" << param->stringValue()
2122  << "' is not a valid IP address.");
2123  }
2124 
2125  if (addr.getFamily() != family) {
2126  isc_throw(BadValue, "Invalid "
2127  << (family == AF_INET6 ? "IPv6" : "IPv4")
2128  << " address specified: " << param->stringValue());
2129  }
2130 
2131  return (addr);
2132 }
2133 
2134 int
2135 LeaseCmdsImpl::lease4ResendDdnsHandler(CalloutHandle& handle) {
2136  std::stringstream ss;
2137  int resp_code = CONTROL_RESULT_ERROR;
2138 
2139  try {
2140  extractCommand(handle);
2141 
2142  // Get the target lease address. Invalid value will throw.
2143  IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
2144 
2145  if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2146  ss << "DDNS updating is not enabled";
2147  } else {
2148  // Find the lease.
2150  if (!lease) {
2151  ss << "No lease found for: " << addr.toText();
2152  resp_code = CONTROL_RESULT_EMPTY;
2153  } else if (lease->hostname_.empty()) {
2154  ss << "Lease for: " << addr.toText()
2155  << ", has no hostname, nothing to update";
2156  } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2157  ss << "Neither forward nor reverse updates enabled for lease for: "
2158  << addr.toText();
2159  } else {
2160  // We have a lease with a hostname and updates in at least
2161  // one direction enabled. Queue an NCR for it.
2162  queueNCR(CHG_ADD, lease);
2163  ss << "NCR generated for: " << addr.toText()
2164  << ", hostname: " << lease->hostname_;
2165  setSuccessResponse(handle, ss.str());
2167  return (0);
2168  }
2169  }
2170  } catch (const std::exception& ex) {
2171  ss << ex.what();
2172  }
2173 
2175  setErrorResponse(handle, ss.str(), resp_code);
2176  return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2177 }
2178 
2179 int
2180 LeaseCmdsImpl::lease6ResendDdnsHandler(CalloutHandle& handle) {
2181  std::stringstream ss;
2182  int resp_code = CONTROL_RESULT_ERROR;
2183 
2184  try {
2185  extractCommand(handle);
2186 
2187  // Get the target lease address. Invalid value will throw.
2188  IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
2189 
2190  if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
2191  ss << "DDNS updating is not enabled";
2192  } else {
2193  // Find the lease.
2195  if (!lease) {
2196  ss << "No lease found for: " << addr.toText();
2197  resp_code = CONTROL_RESULT_EMPTY;
2198  } else if (lease->hostname_.empty()) {
2199  ss << "Lease for: " << addr.toText()
2200  << ", has no hostname, nothing to update";
2201  } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
2202  ss << "Neither forward nor reverse updates enabled for lease for: "
2203  << addr.toText();
2204  } else {
2205  // We have a lease with a hostname and updates in at least
2206  // one direction enabled. Queue an NCR for it.
2207  queueNCR(CHG_ADD, lease);
2208  ss << "NCR generated for: " << addr.toText()
2209  << ", hostname: " << lease->hostname_;
2210  setSuccessResponse(handle, ss.str());
2212  return (0);
2213  }
2214  }
2215  } catch (const std::exception& ex) {
2216  ss << ex.what();
2217  }
2218 
2220  setErrorResponse(handle, ss.str(), resp_code);
2221  return (resp_code == CONTROL_RESULT_EMPTY ? 0 : 1);
2222 }
2223 
2224 ElementPtr
2225 LeaseCmdsImpl::createFailedLeaseMap(const Lease::Type& lease_type,
2226  const IOAddress& lease_address,
2227  const DuidPtr& duid,
2228  const int control_result,
2229  const std::string& error_message) const {
2230  auto failed_lease_map = Element::createMap();
2231  failed_lease_map->set("type", Element::create(Lease::typeToText(lease_type)));
2232 
2233  if (!lease_address.isV6Zero()) {
2234  failed_lease_map->set("ip-address", Element::create(lease_address.toText()));
2235 
2236  } else if (duid) {
2237  failed_lease_map->set("duid", Element::create(duid->toText()));
2238  }
2239 
2240  // Associate the result with the lease.
2241  failed_lease_map->set("result", Element::create(control_result));
2242  failed_lease_map->set("error-message", Element::create(error_message));
2243 
2244  return (failed_lease_map);
2245 }
2246 
2247 // Do lease changes in a critical section.
2248 
2249 int
2250 LeaseCmds::leaseAddHandler(CalloutHandle& handle) {
2251  return (impl_->leaseAddHandler(handle));
2252 }
2253 
2254 int
2255 LeaseCmds::lease6BulkApplyHandler(CalloutHandle& handle) {
2256  return (impl_->lease6BulkApplyHandler(handle));
2257 }
2258 
2259 int
2260 LeaseCmds::leaseGetHandler(CalloutHandle& handle) {
2261  return (impl_->leaseGetHandler(handle));
2262 }
2263 
2264 int
2265 LeaseCmds::leaseGetAllHandler(hooks::CalloutHandle& handle) {
2266  return (impl_->leaseGetAllHandler(handle));
2267 }
2268 
2269 int
2270 LeaseCmds::leaseGetPageHandler(hooks::CalloutHandle& handle) {
2271  return (impl_->leaseGetPageHandler(handle));
2272 }
2273 
2274 int
2275 LeaseCmds::leaseGetByHwAddressHandler(hooks::CalloutHandle& handle) {
2276  return (impl_->leaseGetByHwAddressHandler(handle));
2277 }
2278 
2279 int
2280 LeaseCmds::leaseGetByClientIdHandler(hooks::CalloutHandle& handle) {
2281  return (impl_->leaseGetByClientIdHandler(handle));
2282 }
2283 
2284 int
2285 LeaseCmds::leaseGetByDuidHandler(hooks::CalloutHandle& handle) {
2286  return (impl_->leaseGetByDuidHandler(handle));
2287 }
2288 
2289 int
2290 LeaseCmds::leaseGetByHostnameHandler(hooks::CalloutHandle& handle) {
2291  return (impl_->leaseGetByHostnameHandler(handle));
2292 }
2293 
2294 int
2295 LeaseCmds::lease4DelHandler(CalloutHandle& handle) {
2296  return (impl_->lease4DelHandler(handle));
2297 }
2298 
2299 int
2300 LeaseCmds::lease6DelHandler(CalloutHandle& handle) {
2301  return (impl_->lease6DelHandler(handle));
2302 }
2303 
2304 int
2305 LeaseCmds::lease4UpdateHandler(CalloutHandle& handle) {
2306  return (impl_->lease4UpdateHandler(handle));
2307 }
2308 
2309 int
2310 LeaseCmds::lease6UpdateHandler(CalloutHandle& handle) {
2311  return (impl_->lease6UpdateHandler(handle));
2312 }
2313 
2314 int
2315 LeaseCmds::lease4WipeHandler(CalloutHandle& handle) {
2317  return (impl_->lease4WipeHandler(handle));
2318 }
2319 
2320 int
2321 LeaseCmds::lease6WipeHandler(CalloutHandle& handle) {
2323  return (impl_->lease6WipeHandler(handle));
2324 }
2325 
2326 int
2327 LeaseCmds::lease4ResendDdnsHandler(CalloutHandle& handle) {
2328  return (impl_->lease4ResendDdnsHandler(handle));
2329 }
2330 
2331 int
2332 LeaseCmds::lease6ResendDdnsHandler(CalloutHandle& handle) {
2333  return (impl_->lease6ResendDdnsHandler(handle));
2334 }
2335 
2336 LeaseCmds::LeaseCmds()
2337  :impl_(new LeaseCmdsImpl()) {
2338 }
2339 
2340 } // end of namespace lease_cmds
2341 } // 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:487
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:53
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
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:335
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:1039
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:288
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:867
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:283
Per-packet callout handle.
Wrapper class around reservation command handlers.
Definition: lease_cmds.cc:52
boost::shared_ptr< const CfgSubnets6 > ConstCfgSubnets6Ptr
Const pointer.
Definition: cfg_subnets6.h:333
Parser for Lease6 structure.
Definition: lease_parser.h:76
IPv4 lease.
Definition: lease.h:54
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:503
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:640
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:52
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:51
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:914
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-dhcp-ddns.
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:35
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:50
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:43
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:492
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
Database duplicate entry error.
Definition: db_exceptions.h:42
const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.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.