Kea  1.5.0
lease_cmds.cc
Go to the documentation of this file.
1 // Copyright (C) 2017-2018 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 <dhcpsrv/cfgmgr.h>
14 #include <dhcpsrv/lease_mgr.h>
16 #include <dhcpsrv/subnet_id.h>
17 #include <dhcpsrv/sanity_checker.h>
18 #include <dhcp/duid.h>
19 #include <hooks/hooks.h>
20 #include <exceptions/exceptions.h>
21 #include <lease_cmds.h>
22 #include <lease_parser.h>
23 #include <lease_cmds_log.h>
24 #include <util/encode/hex.h>
25 #include <util/strutil.h>
26 
27 #include <boost/bind.hpp>
28 #include <boost/scoped_ptr.hpp>
29 #include <string>
30 #include <sstream>
31 
32 using namespace isc::dhcp;
33 using namespace isc::data;
34 using namespace isc::config;
35 using namespace isc::asiolink;
36 using namespace isc::hooks;
37 using namespace std;
38 
39 namespace isc {
40 namespace lease_cmds {
41 
43 class LeaseCmdsImpl : private CmdsImpl {
44 public:
45 
47  class Parameters {
48  public:
49 
51  typedef enum {
55  TYPE_CLIENT_ID
56  } Type;
57 
60 
63 
66 
69 
72 
80  static Type txtToType(const std::string& txt) {
81  if (txt == "address") {
82  return (Parameters::TYPE_ADDR);
83  } else if (txt == "hw-address") {
84  return (Parameters::TYPE_HWADDR);
85  } else if (txt == "duid") {
86  return (Parameters::TYPE_DUID);
87  } else if (txt == "client-id") {
88  return (Parameters::TYPE_CLIENT_ID);
89  } else {
90  isc_throw(BadValue, "Incorrect identifier type: "
91  << txt << ", the only supported values are: "
92  "address, hw-address, duid");
93  }
94  }
95 
99 
102 
104  uint32_t iaid;
105 
108  :addr("::"), query_type(TYPE_ADDR), lease_type(Lease::TYPE_NA),
109  iaid(0) {
110  }
111  };
112 
113 public:
114 
122  int
123  leaseAddHandler(CalloutHandle& handle);
124 
132  int
133  leaseGetHandler(CalloutHandle& handle);
134 
145  int
146  leaseGetAllHandler(CalloutHandle& handle);
147 
162  int
163  leaseGetPageHandler(hooks::CalloutHandle& handle);
164 
172  int
173  lease4DelHandler(CalloutHandle& handle);
174 
182  int
183  lease6DelHandler(CalloutHandle& handle);
184 
192  int
193  lease4UpdateHandler(CalloutHandle& handle);
194 
202  int
203  lease6UpdateHandler(CalloutHandle& handle);
204 
212  int
213  lease4WipeHandler(CalloutHandle& handle);
214 
222  int
223  lease6WipeHandler(CalloutHandle& handle);
224 
234  Parameters getParameters(bool v6, const ConstElementPtr& args);
235 };
236 
237 int
238 LeaseCmdsImpl::leaseAddHandler(CalloutHandle& handle) {
239  // Arbitrary defaulting to DHCPv4 or with other words extractCommand
240  // below is not expected to throw...
241  bool v4 = true;
242  string txt = "malformed command";
243 
244  stringstream resp;
245  try {
246  extractCommand(handle);
247  v4 = (cmd_name_ == "lease4-add");
248 
249  txt = "(missing parameters)";
250  if (!cmd_args_) {
251  isc_throw(isc::BadValue, "no parameters specified for the command");
252  }
253 
254  txt = cmd_args_->str();
255 
257 
258  Lease4Ptr lease4;
259  Lease6Ptr lease6;
260  // This parameter is ignored for the commands adding the lease.
261  bool force_create = false;
262  if (v4) {
263  Lease4Parser parser;
264  lease4 = parser.parse(config, cmd_args_, force_create);
265 
266  if (lease4) {
268  resp << "Lease for address " << lease4->addr_.toText()
269  << ", subnet-id " << lease4->subnet_id_ << " added.";
270  }
271 
272  } else {
273  Lease6Parser parser;
274  lease6 = parser.parse(config, cmd_args_, force_create);
275 
276  if (lease6) {
278  if (lease6->type_ == Lease::TYPE_NA) {
279  resp << "Lease for address " << lease6->addr_.toText()
280  << ", subnet-id " << lease6->subnet_id_ << " added.";
281  } else {
282  resp << "Lease for prefix " << lease6->addr_.toText()
283  << "/" << static_cast<int>(lease6->prefixlen_)
284  << ", subnet-id " << lease6->subnet_id_ << " added.";
285  }
286  }
287  }
288 
289  } catch (const std::exception& ex) {
290  LOG_ERROR(lease_cmds_logger, v4 ? LEASE_CMDS_ADD4_FAILED : LEASE_CMDS_ADD6_FAILED)
291  .arg(txt)
292  .arg(ex.what());
293  setErrorResponse(handle, ex.what());
294  return (1);
295  }
296 
298  v4 ? LEASE_CMDS_ADD4 : LEASE_CMDS_ADD6).arg(txt);
299  setSuccessResponse(handle, resp.str());
300  return (0);
301 }
302 
304 LeaseCmdsImpl::getParameters(bool v6, const ConstElementPtr& params) {
305  Parameters x;
306 
307  if (!params || params->getType() != Element::map) {
308  isc_throw(BadValue, "Parameters missing or are not a map.");
309  }
310 
311  // We support several sets of parameters for leaseX-get/lease-del:
312  // lease-get(type, address)
313  // lease-get(type, subnet-id, identifier-type, identifier)
314 
315  if (params->contains("type")) {
316  string t = params->get("type")->stringValue();
317  if (t == "IA_NA" || t == "0") {
319  } else if (t == "IA_TA" || t == "1") {
321  } else if (t == "IA_PD" || t == "2") {
323  } else if (t == "V4" || t == "3") {
325  } else {
326  isc_throw(BadValue, "Invalid lease type specified: "
327  << t << ", only supported values are: IA_NA, IA_TA,"
328  << " IA_PD and V4");
329  }
330  }
331 
332  ConstElementPtr tmp = params->get("ip-address");
333  if (tmp) {
334  if (tmp->getType() != Element::string) {
335  isc_throw(BadValue, "'ip-address' is not a string.");
336  }
337 
338  x.addr = IOAddress(tmp->stringValue());
339 
340  if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
341  stringstream txt;
342  txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
343  << " address specified: " << tmp->stringValue();
344  isc_throw(BadValue, txt.str());
345  }
346 
347  x.query_type = Parameters::TYPE_ADDR;
348  return (x);
349  }
350 
351  tmp = params->get("subnet-id");
352  if (!tmp) {
353  isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
354  }
355  if (tmp->getType() != Element::integer) {
356  isc_throw(BadValue, "'subnet-id' parameter is not integer.");
357  }
358  x.subnet_id = tmp->intValue();
359 
360  if (params->contains("iaid")) {
361  x.iaid = params->get("iaid")->intValue();
362  }
363 
364  // No address specified. Ok, so it must be identifier based query.
365  // "identifier-type": "duid",
366  // "identifier": "aa:bb:cc:dd:ee:..."
367 
368  ConstElementPtr type = params->get("identifier-type");
369  ConstElementPtr ident = params->get("identifier");
370  if (!type || type->getType() != Element::string) {
371  isc_throw(BadValue, "No 'ip-address' provided"
372  " and 'identifier-type' is either missing or not a string.");
373  }
374  if (!ident || ident->getType() != Element::string) {
375  isc_throw(BadValue, "No 'ip-address' provided"
376  " and 'identifier' is either missing or not a string.");
377  }
378 
379  // Got the parameters. Let's see if their values make sense.
380  // Try to convert identifier-type
381  x.query_type = Parameters::txtToType(type->stringValue());
382 
383  switch (x.query_type) {
384  case Parameters::TYPE_HWADDR: {
385  HWAddr hw = HWAddr::fromText(ident->stringValue());
386  x.hwaddr = HWAddrPtr(new HWAddr(hw));
387  break;
388  }
389  case Parameters::TYPE_CLIENT_ID: {
390  x.client_id = ClientId::fromText(ident->stringValue());
391  break;
392  }
393  case Parameters::TYPE_DUID: {
394  DUID duid = DUID::fromText(ident->stringValue());
395  x.duid = DuidPtr(new DUID(duid));
396  break;
397  }
398  case Parameters::TYPE_ADDR: {
399  // We should never get here. The address clause should have been caught
400  // earlier.
401  return (x);
402  }
403  default: {
404  isc_throw(BadValue, "Identifier type " << type->stringValue() <<
405  " is not supported.");
406  }
407  }
408  return (x);
409 }
410 
411 int
412 LeaseCmdsImpl::leaseGetHandler(CalloutHandle& handle) {
413  Parameters p;
414  Lease4Ptr lease4;
415  Lease6Ptr lease6;
416  bool v4;
417  try {
418  extractCommand(handle);
419  v4 = (cmd_name_ == "lease4-get");
420 
421  p = getParameters(!v4, cmd_args_);
422  switch (p.query_type) {
423  case Parameters::TYPE_ADDR: {
424  // Query by address
425  if (v4) {
427  } else {
429  }
430  break;
431  }
432  case Parameters::TYPE_HWADDR:
433  if (v4) {
434  if (!p.hwaddr) {
435  isc_throw(InvalidParameter, "Program error: Query by hw-address "
436  "requires hwaddr to be specified");
437  }
438 
440  } else {
441  isc_throw(isc::InvalidParameter, "Query by hw-address is not allowed in v6.");
442  }
443  break;
444 
445  case Parameters::TYPE_DUID:
446  if (!v4) {
447  if (!p.duid) {
448  isc_throw(InvalidParameter, "Program error: Query by duid "
449  "requires duid to be specified");
450  }
451 
453  p.iaid, p.subnet_id);
454  } else {
455  isc_throw(InvalidParameter, "Query by duid is not allowed in v4.");
456  }
457  break;
458 
459  case Parameters::TYPE_CLIENT_ID:
460  if (v4) {
461  if (!p.client_id) {
462  isc_throw(InvalidParameter, "Program error: Query by client-id "
463  "requires client-id to be specified");
464  }
465 
467  } else {
468  isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
469  }
470  break;
471 
472  default: {
473  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
474  break;
475  }
476  }
477  } catch (const std::exception& ex) {
478  setErrorResponse(handle, ex.what());
479  return (1);
480  }
481 
482  ElementPtr lease_json;
483  if (v4 && lease4) {
484  lease_json = lease4->toElement();
486  "IPv4 lease found.", lease_json);
487  setResponse(handle, response);
488  } else if (!v4 && lease6) {
489  lease_json = lease6->toElement();
491  "IPv6 lease found.", lease_json);
492  setResponse(handle, response);
493  } else {
494  // If we got here, the lease has not been found.
495  setErrorResponse(handle, "Lease not found.", CONTROL_RESULT_EMPTY);
496  }
497 
498  return (0);
499 }
500 
501 int
502 LeaseCmdsImpl::leaseGetAllHandler(CalloutHandle& handle) {
503  bool v4 = true;
504  try {
505  extractCommand(handle);
506  v4 = (cmd_name_ == "lease4-get-all");
507 
508  ElementPtr leases_json = Element::createList();
509 
510  // The argument may contain a list of subnets for which leases should
511  // be returned.
512  if (cmd_args_) {
513  ConstElementPtr subnets = cmd_args_->get("subnets");
514  if (!subnets) {
515  isc_throw(BadValue, "'subnets' parameter not specified");
516  }
517  if (subnets->getType() != Element::list) {
518  isc_throw(BadValue, "'subnets' parameter must be a list");
519  }
520 
521  const std::vector<ElementPtr>& subnet_ids = subnets->listValue();
522  for (auto subnet_id = subnet_ids.begin();
523  subnet_id != subnet_ids.end();
524  ++subnet_id) {
525  if ((*subnet_id)->getType() != Element::integer) {
526  isc_throw(BadValue, "listed subnet identifiers must be numbers");
527  }
528 
529  if (v4) {
530  Lease4Collection leases =
531  LeaseMgrFactory::instance().getLeases4((*subnet_id)->intValue());
532  for (auto lease : leases) {
533  ElementPtr lease_json = lease->toElement();
534  leases_json->add(lease_json);
535  }
536  } else {
537  Lease6Collection leases =
538  LeaseMgrFactory::instance().getLeases6((*subnet_id)->intValue());
539  for (auto lease : leases) {
540  ElementPtr lease_json = lease->toElement();
541  leases_json->add(lease_json);
542  }
543  }
544  }
545 
546  } else {
547  // There is no 'subnets' argument so let's return all leases.
548  if (v4) {
550  for (auto lease : leases) {
551  ElementPtr lease_json = lease->toElement();
552  leases_json->add(lease_json);
553  }
554  } else {
556  for (auto lease : leases) {
557  ElementPtr lease_json = lease->toElement();
558  leases_json->add(lease_json);
559  }
560  }
561  }
562 
563  std::ostringstream s;
564  s << leases_json->size()
565  << " IPv" << (v4 ? "4" : "6")
566  << " lease(s) found.";
567  ElementPtr args = Element::createMap();
568  args->set("leases", leases_json);
569  ConstElementPtr response =
570  createAnswer(leases_json->size() > 0 ?
573  s.str(), args);
574  setResponse(handle, response);
575 
576  } catch (const std::exception& ex) {
577  setErrorResponse(handle, ex.what());
578  return (CONTROL_RESULT_ERROR);
579  }
580 
581  return (0);
582 }
583 
584 int
585 LeaseCmdsImpl::leaseGetPageHandler(CalloutHandle& handle) {
586  bool v4 = true;
587  try {
588  extractCommand(handle);
589  v4 = (cmd_name_ == "lease4-get-page");
590 
591  // arguments must always be present
592  if (!cmd_args_) {
593  isc_throw(BadValue, "no parameters specified for the " << cmd_name_
594  << " command");
595  }
596 
597  // The 'from' argument denotes from which lease we should start the
598  // results page. The results page excludes this lease.
599  ConstElementPtr from = cmd_args_->get("from");
600  if (!from) {
601  isc_throw(BadValue, "'from' parameter not specified");
602  }
603 
604  // The 'from' argument is a string. It may contain a 'start' keyword or
605  // an IP address.
606  if (from->getType() != Element::string) {
607  isc_throw(BadValue, "'from' parameter must be a string");
608  }
609 
610  boost::scoped_ptr<IOAddress> from_address;
611  try {
612  if (from->stringValue() == "start") {
613  from_address.reset(new IOAddress(v4 ? "0.0.0.0" : "::"));
614 
615  } else {
616  // Conversion of a string to an IP address may throw.
617  from_address.reset(new IOAddress(from->stringValue()));
618  }
619 
620  } catch (...) {
621  isc_throw(BadValue, "'from' parameter value is neither 'start' keyword nor "
622  "a valid IPv" << (v4 ? "4" : "6") << " address");
623  }
624 
625  // It must be either IPv4 address for lease4-get-page or IPv6 address for
626  // lease6-get-page.
627  if (v4 && (!from_address->isV4())) {
628  isc_throw(BadValue, "'from' parameter value " << from_address->toText()
629  << " is not an IPv4 address");
630 
631  } else if (!v4 && from_address->isV4()) {
632  isc_throw(BadValue, "'from' parameter value " << from_address->toText()
633  << " is not an IPv6 address");
634  }
635 
636  // The 'limit' is a desired page size. It must always be present.
637  ConstElementPtr page_limit = cmd_args_->get("limit");
638  if (!page_limit) {
639  isc_throw(BadValue, "'limit' parameter not specified");
640  }
641 
642  // The 'limit' must be a number.
643  if (page_limit->getType() != Element::integer) {
644  isc_throw(BadValue, "'limit' parameter must be a number");
645  }
646 
647  // Retrieve the desired page size.
648  size_t page_limit_value = static_cast<size_t>(page_limit->intValue());
649 
650  ElementPtr leases_json = Element::createList();
651 
652  if (v4) {
653  // Get page of IPv4 leases.
654  Lease4Collection leases =
655  LeaseMgrFactory::instance().getLeases4(*from_address,
656  LeasePageSize(page_limit_value));
657 
658  // Convert leases into JSON list.
659  for (auto lease : leases) {
660  ElementPtr lease_json = lease->toElement();
661  leases_json->add(lease_json);
662  }
663 
664  } else {
665  // Get page of IPv6 leases.
666  Lease6Collection leases =
667  LeaseMgrFactory::instance().getLeases6(*from_address,
668  LeasePageSize(page_limit_value));
669  // Convert leases into JSON list.
670  for (auto lease : leases) {
671  ElementPtr lease_json = lease->toElement();
672  leases_json->add(lease_json);
673  }
674  }
675 
676  // Prepare textual status.
677  std::ostringstream s;
678  s << leases_json->size()
679  << " IPv" << (v4 ? "4" : "6")
680  << " lease(s) found.";
681  ElementPtr args = Element::createMap();
682 
683  // Put gathered data into arguments map.
684  args->set("leases", leases_json);
685  args->set("count", Element::create(static_cast<int64_t>(leases_json->size())));
686 
687  // Create the response.
688  ConstElementPtr response =
689  createAnswer(leases_json->size() > 0 ?
692  s.str(), args);
693  setResponse(handle, response);
694 
695  } catch (std::exception& ex) {
696  setErrorResponse(handle, ex.what());
697  return (CONTROL_RESULT_ERROR);
698  }
699 
700  return (CONTROL_RESULT_SUCCESS);
701 }
702 
703 int
704 LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) {
705  Parameters p;
706  Lease4Ptr lease4;
708  try {
709  extractCommand(handle);
710  p = getParameters(false, cmd_args_);
711 
712  switch (p.query_type) {
713  case Parameters::TYPE_ADDR: {
714 
715  // If address was specified explicitly, let's use it as is.
716  addr = p.addr;
717  break;
718  }
719  case Parameters::TYPE_HWADDR:
720  if (!p.hwaddr) {
721  isc_throw(InvalidParameter, "Program error: Query by hw-address "
722  "requires hwaddr to be specified");
723  }
724 
725  // Let's see if there's such a lease at all.
727  if (!lease4) {
728  setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
729  return (0);
730  }
731 
732  // Found it, can use it as is.
733  addr = lease4->addr_;
734  break;
735 
736  case Parameters::TYPE_CLIENT_ID:
737  if (!p.client_id) {
738  isc_throw(InvalidParameter, "Program error: Query by client-id "
739  "requires client-id to be specified");
740  }
741 
742  // Let's see if there's such a lease at all.
744  if (!lease4) {
745  setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
746  return (0);
747  }
748 
749  // Found it, can use it as is.
750  addr = lease4->addr_;
751  break;
752 
753  case Parameters::TYPE_DUID:
754  isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
755  break;
756 
757  default: {
758  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
759  break;
760  }
761  }
762 
763  if (LeaseMgrFactory::instance().deleteLease(addr)) {
764  setSuccessResponse(handle, "IPv4 lease deleted.");
765  } else {
766  setErrorResponse (handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
767  }
768  } catch (const std::exception& ex) {
769  setErrorResponse(handle, ex.what());
770  return (1);
771  }
772 
773  return (0);
774 }
775 
776 int
777 LeaseCmdsImpl::lease6DelHandler(CalloutHandle& handle) {
778  Parameters p;
779  Lease6Ptr lease6;
781  try {
782  extractCommand(handle);
783  p = getParameters(true, cmd_args_);
784 
785  switch (p.query_type) {
786  case Parameters::TYPE_ADDR: {
787 
788  // If address was specified explicitly, let's use it as is.
789  addr = p.addr;
790  break;
791  }
792  case Parameters::TYPE_HWADDR:
793  isc_throw(InvalidParameter, "Delete by hw-address is not allowed in v6.");
794  break;
795 
796  case Parameters::TYPE_DUID:
797  if (!p.duid) {
798  isc_throw(InvalidParameter, "Program error: Query by duid "
799  "requires duid to be specified");
800  }
801 
802  // Let's see if there's such a lease at all.
804  p.iaid, p.subnet_id);
805  if (!lease6) {
806  setErrorResponse(handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
807  return (0);
808  }
809 
810  // Found it, can use it as is.
811  addr = lease6->addr_;
812  break;
813 
814  default: {
815  isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
816  break;
817  }
818  }
819 
820  if (LeaseMgrFactory::instance().deleteLease(addr)) {
821  setSuccessResponse(handle, "IPv6 lease deleted.");
822  } else {
823  setErrorResponse (handle, "IPv6 lease not found.", CONTROL_RESULT_EMPTY);
824  }
825  } catch (const std::exception& ex) {
826  setErrorResponse(handle, ex.what());
827  return (1);
828  }
829 
830  return (0);
831 }
832 
833 int
834 LeaseCmdsImpl::lease4UpdateHandler(CalloutHandle& handle) {
835  try {
836  extractCommand(handle);
837 
838  // We need the lease to be specified.
839  if (!cmd_args_) {
840  isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
841  }
842 
843  // Get the parameters specified by the user first.
845  Lease4Ptr lease4;
846  Lease4Parser parser;
847  bool force_create = false;
848 
849  // The parser does sanity checks (if the address is in scope, if
850  // subnet-id is valid, etc)
851  lease4 = parser.parse(config, cmd_args_, force_create);
852  if (force_create && !LeaseMgrFactory::instance().getLease4(lease4->addr_)) {
854  setSuccessResponse(handle, "IPv4 lease added.");
855 
856  } else {
858  setSuccessResponse(handle, "IPv4 lease updated.");
859  }
860  } catch (const std::exception& ex) {
861  setErrorResponse(handle, ex.what());
862  return (1);
863  }
864 
865  return (0);
866 }
867 
868 int
869 LeaseCmdsImpl::lease6UpdateHandler(CalloutHandle& handle) {
870  try {
871  extractCommand(handle);
872 
873  // We need the lease to be specified.
874  if (!cmd_args_) {
875  isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
876  }
877 
878  // Get the parameters specified by the user first.
880  Lease6Ptr lease6;
881  Lease6Parser parser;
882  bool force_create = false;
883 
884  // The parser does sanity checks (if the address is in scope, if
885  // subnet-id is valid, etc)
886  lease6 = parser.parse(config, cmd_args_, force_create);
887  if (force_create && !LeaseMgrFactory::instance().getLease6(lease6->type_,
888  lease6->addr_)) {
890  setSuccessResponse(handle, "IPv6 lease added.");
891  } else {
893  setSuccessResponse(handle, "IPv6 lease updated.");
894  }
895  } catch (const std::exception& ex) {
896  setErrorResponse(handle, ex.what());
897  return (1);
898  }
899 
900  return (0);
901 }
902 
903 int
904 LeaseCmdsImpl::lease4WipeHandler(CalloutHandle& handle) {
905  try {
906  extractCommand(handle);
907 
908  SimpleParser parser;
909  SubnetID id = 0;
910 
911  size_t num = 0; // number of leases deleted
912  stringstream ids; // a text with subnet-ids being wiped
913 
914  // The subnet-id parameter is now optional.
915  if (cmd_args_ && cmd_args_->contains("subnet-id")) {
916  id = parser.getUint32(cmd_args_, "subnet-id");
917  }
918 
919  if (id) {
920  // Wipe a single subnet
922  ids << " " << id;
923  } else {
924  // Wipe them all!
926  ConstCfgSubnets4Ptr subnets = config->getCfgSubnets4();
927  const Subnet4Collection * subs = subnets->getAll();
928 
929  // Go over all subnets and wipe leases in each of them.
930  for (auto sub : *subs) {
931  num += LeaseMgrFactory::instance().wipeLeases4(sub->getID());
932  ids << " " << sub->getID();
933  }
934  }
935 
936  stringstream tmp;
937  tmp << "Deleted " << num << " IPv4 lease(s) from subnet(s)" << ids.str();
939  : CONTROL_RESULT_EMPTY, tmp.str());
940  setResponse(handle, response);
941  } catch (const std::exception& ex) {
942  setErrorResponse(handle, ex.what());
943  return (1);
944  }
945 
946  return (0);
947 }
948 
949 int
950 LeaseCmdsImpl::lease6WipeHandler(CalloutHandle& handle) {
951  try {
952  extractCommand(handle);
953 
954  SimpleParser parser;
955  SubnetID id = 0;
956 
957  size_t num = 0; // number of leases deleted
958  stringstream ids; // a text with subnet-ids being wiped
959 
965 
966  // The subnet-id parameter is now optional.
967  if (cmd_args_ && cmd_args_->contains("subnet-id")) {
968  id = parser.getUint32(cmd_args_, "subnet-id");
969  }
970 
971  if (id) {
972  // Wipe a single subnet.
974  ids << " " << id;
975  } else {
976  // Wipe them all!
978  ConstCfgSubnets6Ptr subnets = config->getCfgSubnets6();
979  const Subnet6Collection * subs = subnets->getAll();
980 
981  // Go over all subnets and wipe leases in each of them.
982  for (auto sub : *subs) {
983  num += LeaseMgrFactory::instance().wipeLeases6(sub->getID());
984  ids << " " << sub->getID();
985  }
986  }
987 
988  stringstream tmp;
989  tmp << "Deleted " << num << " IPv6 lease(s) from subnet(s)" << ids.str();
991  : CONTROL_RESULT_EMPTY, tmp.str());
992  setResponse(handle, response);
993  } catch (const std::exception& ex) {
994  setErrorResponse(handle, ex.what());
995  return (1);
996  }
997 
998  return (0);
999 }
1000 
1001 int
1002 LeaseCmds::leaseAddHandler(CalloutHandle& handle) {
1003  return(impl_->leaseAddHandler(handle));
1004 }
1005 
1006 int
1007 LeaseCmds::leaseGetHandler(CalloutHandle& handle) {
1008  return(impl_->leaseGetHandler(handle));
1009 }
1010 
1011 int
1012 LeaseCmds::leaseGetAllHandler(hooks::CalloutHandle& handle) {
1013  return (impl_->leaseGetAllHandler(handle));
1014 }
1015 
1016 int
1017 LeaseCmds::leaseGetPageHandler(hooks::CalloutHandle& handle) {
1018  return (impl_->leaseGetPageHandler(handle));
1019 }
1020 
1021 int
1022 LeaseCmds::lease4DelHandler(CalloutHandle& handle) {
1023  return(impl_->lease4DelHandler(handle));
1024 }
1025 
1026 int
1027 LeaseCmds::lease6DelHandler(CalloutHandle& handle) {
1028  return(impl_->lease6DelHandler(handle));
1029 }
1030 
1031 int
1032 LeaseCmds::lease4UpdateHandler(CalloutHandle& handle) {
1033  return(impl_->lease4UpdateHandler(handle));
1034 }
1035 
1036 int
1037 LeaseCmds::lease6UpdateHandler(CalloutHandle& handle) {
1038  return(impl_->lease6UpdateHandler(handle));
1039 }
1040 
1041 int
1042 LeaseCmds::lease4WipeHandler(CalloutHandle& handle) {
1043  return(impl_->lease4WipeHandler(handle));
1044 }
1045 
1046 int
1047 LeaseCmds::lease6WipeHandler(CalloutHandle& handle) {
1048  return(impl_->lease6WipeHandler(handle));
1049 }
1050 
1051 LeaseCmds::LeaseCmds()
1052  :impl_(new LeaseCmdsImpl()) {
1053 }
1054 
1055 };
1056 };
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Definition: duid.cc:131
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:65
#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
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SubnetRandomAccessIndexTag > >, 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 > > >> Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:843
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
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
Definition: lease.h:455
#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:41
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:154
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition: duid.cc:61
Type query_type
specifies parameter types (true = query by address, false = query by identifier-type,...
Definition: lease_cmds.cc:98
SubnetID subnet_id
Specifies subnet-id (always used)
Definition: lease_cmds.cc:59
boost::shared_ptr< const CfgSubnets4 > ConstCfgSubnets4Ptr
Const pointer.
Definition: cfg_subnets4.h:273
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
#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")
boost::shared_ptr< const SrvConfig > ConstSrvConfigPtr
Const pointer to the SrvConfig.
Definition: srv_config.h:710
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:245
Per-packet callout handle.
Wrapper class around reservation command handlers.
Definition: lease_cmds.cc:43
boost::shared_ptr< const CfgSubnets6 > ConstCfgSubnets6Ptr
Const pointer.
Definition: cfg_subnets6.h:271
Parser for Lease6 structure.
Definition: lease_parser.h:76
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition: lease.h:604
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:62
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition: duid.h:103
the lease contains temporary IPv6 address
Definition: lease.h:40
Type
specifies type of query (by IP addr, by hwaddr, by DUID)
Definition: lease_cmds.cc:51
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:39
Lease::Type lease_type
Lease type (NA,TA or PD) used for v6 leases.
Definition: lease_cmds.cc:101
query by IP address (either v4 or v6)
Definition: lease_cmds.cc:52
Defines the logger used by the top-level component of kea-dhcp-ddns.
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SubnetRandomAccessIndexTag > >, 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 > > >> Subnet4Collection
A collection of Subnet4 objects.
Definition: subnet.h:798
This file contains several functions and constants that are used for handling commands and responses ...
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:38
A generic exception that is thrown if a function is called in a prohibited way.
Parameters specified for lease commands.
Definition: lease_cmds.cc:47
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:80
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
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.
isc::dhcp::DuidPtr duid
Specifies identifier value (used when query_type is TYPE_DUID)
Definition: lease_cmds.cc:68
Wraps value holding size of the page with leases.
Definition: lease_mgr.h:43
static LeaseMgr & instance()
Return current lease manager.
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
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:460
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
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:71
uint32_t iaid
IAID identifier used for v6 leases.
Definition: lease_cmds.cc:104