Kea 3.1.1
host_cmds.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8#include <host_cmds.h>
10#include <config/cmds_impl.h>
11#include <host_data_parser.h>
13#include <cc/simple_parser.h>
14#include <cc/data.h>
15#include <asiolink/io_address.h>
16#include <host_cmds_log.h>
17#include <dhcpsrv/cfgmgr.h>
18#include <dhcpsrv/host_mgr.h>
19#include <dhcpsrv/cfg_hosts.h>
22#include <dhcpsrv/subnet_id.h>
23#include <util/encode/encode.h>
24#include <util/str.h>
26#include <boost/algorithm/string.hpp>
27#include <boost/foreach.hpp>
28#include <string>
29#include <sstream>
30
31using namespace isc::dhcp;
32using namespace isc::data;
33using namespace isc::config;
34using namespace isc::asiolink;
35using namespace isc::hooks;
36using namespace std;
37
38namespace isc {
39namespace host_cmds {
40
42class HostCmdsImpl : private CmdsImpl {
43public:
44
47
50
60 class Parameters {
61 public:
62
65
68
71
75
77 std::vector<uint8_t> ident;
78
82
84 size_t page_limit;
85
88
90 uint64_t host_id;
91
93 std::string hostname;
94
98
106 };
107
108public:
109
117 int
119
127 int
129
138
146 int
148
156 int
158
166 int
168
176 int
178
186 int
188
196 int
198
199private:
200
209 Parameters getParameters(const ConstElementPtr& args);
210
219 Parameters getAllParameters(const ConstElementPtr& args);
220
229 Parameters getPageParameters(const ConstElementPtr& args);
230
239 Parameters getByHostnameParameters(const ConstElementPtr& args);
240
249 Parameters getByIdParameters(const ConstElementPtr& args);
250
259 Parameters getByAddressParameters(const ConstElementPtr& params);
260
265 HostMgrOperationTarget getOperationTarget(const ConstElementPtr& args);
266
278 void validateHostForSubnet4(SubnetID subnet_id, const IOAddress& address);
279
291 void validateHostForSubnet6(SubnetID subnet_id,
292 const std::vector<IOAddress>& addresses);
293
301 bool checkHost4(const ConstHostPtr& host);
302
310 bool checkHost6(const ConstHostPtr& host);
311
313 HostDataSourcePtr db_storage_;
314
316 uint16_t family_;
317};
318
320 // There are two ways we can store host reservations: either in configuration
321 // or in DB backends. The prime interface we provide - HostMgr class - does
322 // not allow storing hosts if alternate data source (DB backend) is not
323 // available. Therefore we need to check both. If available, we will store
324 // reservations in SQL data source. If not, we will *one day* be able to
325 // update the configuration, but it is not possible yet. Current configuration
326 // is retrieved as const pointer. We would need a way to clone current
327 // configuration to staging, add a host and then commit the change.
328 // We need to think this through as we don't want to go through the whole
329 // reconfiguration process when a new host is added.
330
331 // Try to get alternate storage.
332 db_storage_ = HostMgr::instance().getHostDataSource();
333
334 // Try to get the configuration storage. This will come in handy one day.
335 // cfg_storage_ = CfgMgr::instance().getCurrentCfg()->getCfgHosts();
336
337 family_ = CfgMgr::instance().getFamily();
338}
339
341 db_storage_.reset();
342}
343
344int
346 string txt = "(missing parameters)";
347 bool force_global(false);
348 try {
349 extractCommand(handle);
350 if (cmd_args_) {
351 txt = cmd_args_->str();
352 }
353
355 .arg(txt);
356
357 if (!cmd_args_) {
358 isc_throw(isc::BadValue, "no parameters specified for the command");
359 }
360
361 HostMgrOperationTarget operation_target = getOperationTarget(cmd_args_);
362 if (operation_target == HostMgrOperationTarget::UNSPECIFIED_SOURCE) {
364 }
365
366 ConstElementPtr reservation = cmd_args_->get("reservation");
367 if (!reservation) {
368 isc_throw(isc::BadValue, "reservation must be specified");
369 }
370
371 HostPtr host;
372 if (family_ == AF_INET) {
373 HostDataParser4 parser;
374 host = parser.parseWithSubnet(reservation, false);
375 force_global = checkHost4(host);
376 if (force_global) {
377 host->setIPv4SubnetID(SUBNET_ID_GLOBAL);
378 }
379 } else {
380 HostDataParser6 parser;
381 host = parser.parseWithSubnet(reservation, false);
382 force_global = checkHost6(host);
383 if (force_global) {
384 host->setIPv6SubnetID(SUBNET_ID_GLOBAL);
385 }
386 }
387
388 // If we haven't accessed db_storage_ yet, try to retrieve it.
389 if (!db_storage_) {
390 db_storage_ = HostMgr::instance().getHostDataSource();
391 }
392
393 if (!db_storage_ && operation_target == HostMgrOperationTarget::ALTERNATE_SOURCES) {
394 // If it's still not available, bail out.
395 isc_throw(isc::BadValue, "Host database not available, cannot add host.");
396 }
397
398 if (family_ == AF_INET) {
399 // Validate the IPv4 subnet id against configured subnet and also verify
400 // that the reserved IPv4 address (if non-zero) belongs to this subnet.
401 validateHostForSubnet4(host->getIPv4SubnetID(),
402 host->getIPv4Reservation());
403
404 } else {
405 // Retrieve all reserved addresses from the host. We're going to
406 // check if these addresses are in range with the specified subnet.
407 // If any of them is not in range, we will reject the command.
408 // Note that we do not validate delegated prefixes because they don't
409 // have to match the subnet prefix.
410 auto const& range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
411 std::vector<IOAddress> addresses;
412 BOOST_FOREACH(auto const& address, range) {
413 addresses.push_back(address.second.getPrefix());
414 }
415 // Validate the IPv6 subnet id against configured subnet and also
416 // verify that the reserved IPv6 addresses (if any) belong to this
417 // subnet.
418 validateHostForSubnet6(host->getIPv6SubnetID(), addresses);
419 }
420
421 HostMgr::instance().add(host, operation_target);
422 } catch (const std::exception& ex) {
424 .arg(txt)
425 .arg(ex.what());
426 setErrorResponse(handle, ex.what());
427 return (1);
428 }
429
431 .arg(txt);
432 string msg("Host added.");
433 if (force_global) {
434 msg += " subnet-id not specified, assumed global (subnet-id 0).";
435 }
436 setSuccessResponse(handle, msg);
437 return (0);
438}
439
441HostCmdsImpl::getParameters(const ConstElementPtr& params) {
442 Parameters x;
443
444 if (!params || params->getType() != Element::map) {
445 isc_throw(BadValue, "Parameters missing or are not a map.");
446 }
447
448 // We support 2 types of reservation-get:
449 // reservation-get(subnet-id, address, operation-target)
450 // reservation-get(subnet-id, identifier-type, identifier, operation-target)
451 ConstElementPtr addr = params->get("ip-address");
452 ConstElementPtr type = params->get("identifier-type");
453 ConstElementPtr ident = params->get("identifier");
454 if (params->contains("subnet-id") || (!addr && !type && !ident)) {
455 int64_t value = data::SimpleParser::getInteger(params, "subnet-id",
456 0, dhcp::SUBNET_ID_MAX);
457 x.subnet_id = static_cast<SubnetID>(value);
458 x.has_subnet_id = true;
459 } else {
460 x.has_subnet_id = false;
461 }
462
463 x.operation_target = getOperationTarget(params);
464
465 if (addr) {
466 if (addr->getType() != Element::string) {
467 isc_throw(BadValue, "'ip-address' is not a string.");
468 }
469
470 x.addr = IOAddress(addr->stringValue());
471 x.query_by_addr = true;
472 if (!x.has_subnet_id) {
473 isc_throw(BadValue, "missing parameter 'subnet-id', use "
474 "'reservation-get-by-address' with 'ip-address' set to \""
475 << addr->stringValue() << "\" to get the list of "
476 << "reservations with this address");
477 }
478 return (x);
479 }
480
481 // No address specified. Ok, so it must be identifier based query.
482 // "identifier-type": "duid",
483 // "identifier": "aa:bb:cc:dd:ee:..."
484
485 if (!type || type->getType() != Element::string) {
486 isc_throw(BadValue, "No 'ip-address' provided"
487 " and 'identifier-type' is either missing or not a string.");
488 }
489 if (!ident || ident->getType() != Element::string) {
490 isc_throw(BadValue, "No 'ip-address' provided"
491 " and 'identifier' is either missing or not a string.");
492 }
493
494 // Got the parameters. Let's see if their values make sense.
495
496 // Try to parse the identifier value first.
497 try {
498 x.ident = util::str::quotedStringToBinary(ident->stringValue());
499 if (x.ident.empty()) {
500 util::str::decodeFormattedHexString(ident->stringValue(),
501 x.ident);
502 }
503 } catch (...) {
504 // The string doesn't match any known pattern, so we have to
505 // report an error at this point.
506 isc_throw(BadValue, "Unable to parse 'identifier' value.");
507 }
508
509 if (x.ident.empty()) {
510 isc_throw(BadValue, "Unable to query for empty 'identifier'.");
511 }
512
513 // Next, try to convert identifier-type
514 try {
515 x.type = Host::getIdentifierType(type->stringValue());
516 } catch (const std::exception& ex) {
517 isc_throw(BadValue, "Value of 'identifier-type' was not recognized.");
518 }
519
520 x.query_by_addr = false;
521 if (!x.has_subnet_id) {
522 isc_throw(BadValue, "missing parameter 'subnet-id', use "
523 "'reservation-get-by-id' with 'identifier-type' set to \""
524 << type->stringValue() << "\" and 'identifier' to \""
525 << ident->stringValue() << "\" to get the list of "
526 << "reservations with this identifier");
527 }
528 return (x);
529}
530
531void
532HostCmdsImpl::validateHostForSubnet4(SubnetID subnet_id, const IOAddress& address) {
533 if (subnet_id != 0) {
534 auto cfg = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4();
535 auto subnet = cfg->getBySubnetId(subnet_id);
536 if (!subnet) {
537 isc_throw(isc::BadValue,
538 "IPv4 subnet with ID of '" << subnet_id
539 << "' is not configured");
540 }
541
542 if (!address.isV4Zero() && !address.isV6Zero()
543 && !subnet->inRange(address)) {
544 isc_throw(isc::BadValue,
545 "specified reservation '" << address
546 << "' is not matching the IPv4 subnet prefix '"
547 << subnet->toText() << "'");
548 }
549 }
550}
551
552void
553HostCmdsImpl::validateHostForSubnet6(SubnetID subnet_id,
554 const std::vector<IOAddress>& addresses) {
555 if (subnet_id != 0) {
556 auto cfg = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
557 auto subnet = cfg->getBySubnetId(subnet_id);
558 if (!subnet) {
559 isc_throw(isc::BadValue,
560 "IPv6 subnet with ID of '" << subnet_id
561 << "' is not configured");
562 }
563
564 for (auto const& address : addresses) {
565 if (!subnet->inRange(address)) {
566 isc_throw(isc::BadValue,
567 "specified reservation '" << address
568 << "' is not matching the IPv6 subnet prefix '"
569 << subnet->toText() << "'");
570 }
571 }
572 }
573}
574
575bool
576HostCmdsImpl::checkHost4(const ConstHostPtr& host) {
577 if (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) {
578 return (false);
579 }
580 const IOAddress& addr = host->getIPv4Reservation();
581 if (!addr.isV4Zero()) {
582 // Try to find a subnet hint.
583 auto subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4();
584 ConstSubnet4Ptr guarded;
585 ConstSubnet4Ptr candidate;
586 bool others = false;
587 for (auto const& subnet : *subnets->getAll()) {
588 if (!subnet->inRange(addr)) {
589 continue;
590 }
591 if (subnet->clientSupported(ClientClasses())) {
592 if (!candidate) {
593 candidate = subnet;
594 } else {
595 others = true;
596 }
597 } else if (!guarded) {
598 guarded = subnet;
599 } else {
600 others = true;
601 }
602 }
603 if (guarded && candidate) {
604 others = true;
605 }
606 if (!guarded && !candidate) {
607 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
608 << " The address '" << addr.toText()
609 << "' belongs to no configured subnet.");
610 }
611 if (candidate) {
612 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
613 << " The address '" << addr.toText()
614 << "' belongs to subnet '" << candidate->toText()
615 << "' id " << candidate->getID()
616 << (others ? " and others." : "."));
617 } else {
618 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
619 << " The address '" << addr.toText()
620 << "' belongs to guarded subnet '" << guarded->toText()
621 << "' id " << guarded->getID()
622 << (others ? " and others." : "."));
623 }
624 } else {
625 return (true);
626 }
627}
628
629bool
630HostCmdsImpl::checkHost6(const ConstHostPtr& host) {
631 if (host->getIPv6SubnetID() != SUBNET_ID_UNUSED) {
632 return (false);
633 }
634 auto const& range = host->getIPv6Reservations();
635 std::vector<IOAddress> addresses;
636 bool has_prefixes = false;
637 BOOST_FOREACH(auto const& address, range) {
638 if (address.first == IPv6Resrv::TYPE_NA) {
639 addresses.push_back(address.second.getPrefix());
640 } else {
641 has_prefixes = true;
642 }
643 }
644 if (!addresses.empty()) {
645 // Try to find a subnet hint.
646 auto subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
647 ConstSubnet6Ptr guarded;
648 ConstSubnet6Ptr candidate;
649 bool others = false;
650 for (auto const& subnet : *subnets->getAll()) {
651 bool in_range = true;
652 for (auto const& address : addresses) {
653 if (!subnet->inRange(address)) {
654 in_range = false;
655 break;
656 }
657 }
658 if (!in_range) {
659 continue;
660 }
661 if (subnet->clientSupported(ClientClasses())) {
662 if (!candidate) {
663 candidate = subnet;
664 } else {
665 others = true;
666 }
667 } else if (!guarded) {
668 guarded = subnet;
669 } else {
670 others = true;
671 }
672 }
673 if (guarded && candidate) {
674 others = true;
675 }
676 if (!guarded && !candidate) {
677 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
678 << " Reserved IPv6 addresses do not belong to a"
679 << " common configured subnet.");
680 }
681 if (candidate) {
682 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
683 << " Reserved IPv6 addresses belong to subnet '"
684 << candidate->toText() << "' id " << candidate->getID()
685 << (others ? " and others." : "."));
686 } else {
687 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
688 << " Reserved IPv6 addresses belong to guarded subnet '"
689 << guarded->toText() << "' id " << guarded->getID()
690 << (others ? " and others." : "."));
691 }
692 } else if (has_prefixes) {
693 isc_throw(isc::BadValue, "Mandatory 'subnet-id' parameter missing."
694 << " Prefixes are not attached to subnets so no hint is"
695 << " available.");
696 } else {
697 return (true);
698 }
699}
700
701int
703 string txt = "(missing parameters)";
704 Parameters p;
705 ElementPtr host_json;
706 try {
707 extractCommand(handle);
708 if (cmd_args_) {
709 txt = cmd_args_->str();
710 }
711
713 .arg(txt);
714
715 p = getParameters(cmd_args_);
716
719 }
720
721 ConstHostPtr host;
722 if (p.query_by_addr) {
723 // Query by address
724 if (p.addr.isV4()) {
726 } else {
728 }
729 } else {
730 // Query by identifier
731 if (family_ == AF_INET) {
732 host = HostMgr::instance().get4(p.subnet_id, p.type, &p.ident[0],
733 p.ident.size(), p.operation_target);
734 } else {
735 host = HostMgr::instance().get6(p.subnet_id, p.type, &p.ident[0],
736 p.ident.size(), p.operation_target);
737 }
738 }
739 if (host) {
740 SubnetID subnet_id;
741 if (family_ == AF_INET) {
742 host_json = host->toElement4();
743 subnet_id = host->getIPv4SubnetID();
744 } else {
745 host_json = host->toElement6();
746 subnet_id = host->getIPv6SubnetID();
747 }
748 host_json->set("subnet-id", Element::create(subnet_id));
749 }
750 } catch (const std::exception& ex) {
752 .arg(txt)
753 .arg(ex.what());
754 setErrorResponse(handle, ex.what());
755 return (1);
756 }
757
759 .arg(txt);
760
761 if (host_json) {
763 "Host found.", host_json);
764 setResponse(handle, response);
765 } else {
766 setErrorResponse(handle, "Host not found.", CONTROL_RESULT_EMPTY);
767 }
768
769 return (0);
770}
771
772int
774 string txt = "(missing parameters)";
775 Parameters p;
776 ElementPtr hosts_json = Element::createList();
777 try {
778 extractCommand(handle);
779 if (cmd_args_) {
780 txt = cmd_args_->str();
781 }
782
784 .arg(txt);
785
786 p = getByAddressParameters(cmd_args_);
787
790 }
791
793 if (p.has_subnet_id) {
794 if (family_ == AF_INET) {
795 validateHostForSubnet4(p.subnet_id,
798 } else {
799 validateHostForSubnet6(p.subnet_id, std::vector<IOAddress>());
801 }
802 } else {
803 if (family_ == AF_INET) {
805 } else {
807 }
808 }
809
810 // Add the subnet-id when it was not specified by the command
811 // parameters and filter out wrong universe entries.
812 SubnetID subnet_id = p.subnet_id;
813 ElementPtr host_json;
814 for (auto const& host : hosts) {
815 if (!p.has_subnet_id) {
816 if (family_ == AF_INET) {
817 subnet_id = host->getIPv4SubnetID();
818 } else {
819 subnet_id = host->getIPv6SubnetID();
820 }
821
822 if (subnet_id == SUBNET_ID_UNUSED) {
823 continue;
824 }
825 }
826
827 if (family_ == AF_INET) {
828 host_json = host->toElement4();
829 } else {
830 host_json = host->toElement6();
831 }
832
833 host_json->set("subnet-id", Element::create(subnet_id));
834 hosts_json->add(host_json);
835 }
836 } catch (const std::exception& ex) {
838 .arg(txt)
839 .arg(ex.what());
840 setErrorResponse(handle, ex.what());
841 return (1);
842 }
843
845 .arg(txt);
846
847 ostringstream msg;
848 msg << hosts_json->size()
849 << " IPv" << (family_ == AF_INET ? "4" : "6")
850 << " host(s) found.";
852 result->set("hosts", hosts_json);
853
854 ConstElementPtr response = createAnswer(hosts_json->size() > 0 ?
857 msg.str(), result);
858 setResponse(handle, response);
859
860 return (0);
861}
862
863int
865 string txt = "(missing parameters)";
866 Parameters p;
867 bool deleted;
868 try {
869 extractCommand(handle);
870 if (cmd_args_) {
871 txt = cmd_args_->str();
872 }
873
875 .arg(txt);
876
877 p = getParameters(cmd_args_);
880 }
881
882 if (p.query_by_addr) {
883 // try to delete by address
885 } else {
886 // try to delete by identifier
887 if (family_ == AF_INET) {
888 deleted = HostMgr::instance().del4(p.subnet_id, p.type,
889 &p.ident[0], p.ident.size(),
891 } else {
892 deleted = HostMgr::instance().del6(p.subnet_id, p.type,
893 &p.ident[0], p.ident.size(),
895 }
896 }
897 } catch (const std::exception& ex) {
899 .arg(txt)
900 .arg(ex.what());
901 setErrorResponse(handle, ex.what());
902 return (1);
903 }
904
906 .arg(txt);
907
908 if (deleted) {
909 setSuccessResponse(handle, "Host deleted.");
910 } else {
911 setErrorResponse(handle, "Host not deleted (not found).",
913 }
914
915 return (0);
916}
917
919HostCmdsImpl::getAllParameters(const ConstElementPtr& params) {
920 Parameters x;
921
922 if (!params || params->getType() != Element::map) {
923 isc_throw(BadValue, "Parameters missing or are not a map.");
924 }
925
926 // We support one type of reservation-get-all(subnet-id)
927 int64_t tmp = data::SimpleParser::getInteger(params, "subnet-id",
928 0, dhcp::SUBNET_ID_MAX);
929 x.subnet_id = static_cast<SubnetID>(tmp);
930 x.has_subnet_id = true;
931
932 x.operation_target = getOperationTarget(params);
933
934 return (x);
935}
936
937HostCmdsImpl::Parameters
938HostCmdsImpl::getPageParameters(const ConstElementPtr& params) {
939 Parameters x;
940
941 if (!params || params->getType() != Element::map) {
942 isc_throw(BadValue, "Parameters missing or are not a map.");
943 }
944
945 int64_t tmp = data::SimpleParser::getInteger(params, "limit", 0,
946 numeric_limits<uint32_t>::max());
947 x.page_limit = static_cast<size_t>(tmp);
948
949 // subnet-id, source-index and from host-id are optional.
950 if (params->contains("subnet-id")) {
951 tmp = data::SimpleParser::getInteger(params, "subnet-id",
952 0, dhcp::SUBNET_ID_MAX);
953 x.subnet_id = static_cast<SubnetID>(tmp);
954 x.has_subnet_id = true;
955 }
956
957 x.source_index = 0;
958 if (params->get("source-index")) {
959 tmp = data::SimpleParser::getInteger(params, "source-index", 0, 10);
960 x.source_index = static_cast<size_t>(tmp);
961 }
962
963 x.host_id = 0;
964 if (params->get("from")) {
965 tmp = data::SimpleParser::getInteger(params, "from");
966 x.host_id = static_cast<uint64_t>(tmp);
967 }
968
969 return (x);
970}
971
973HostCmdsImpl::getByHostnameParameters(const ConstElementPtr& params) {
974 Parameters x;
975
976 if (!params || params->getType() != Element::map) {
977 isc_throw(BadValue, "Parameters missing or are not a map.");
978 }
979
980 string hostname = data::SimpleParser::getString(params, "hostname");
981 x.hostname = hostname;
982
983 // subnet-id is optional.
984 if (params->contains("subnet-id")) {
985 int64_t tmp = data::SimpleParser::getInteger(params, "subnet-id",
986 0, dhcp::SUBNET_ID_MAX);
987 x.subnet_id = static_cast<SubnetID>(tmp);
988 x.has_subnet_id = true;
989 }
990
991 x.operation_target = getOperationTarget(params);
992
993 return (x);
994}
995
997HostCmdsImpl::getByIdParameters(const ConstElementPtr& params) {
998 Parameters x;
999
1000 if (!params || params->getType() != Element::map) {
1001 isc_throw(BadValue, "Parameters missing or are not a map.");
1002 }
1003
1004 ConstElementPtr type = params->get("identifier-type");
1005 ConstElementPtr ident = params->get("identifier");
1006 if (!type || type->getType() != Element::string) {
1007 isc_throw(BadValue, "'identifier-type' is either missing"
1008 " or not a string.");
1009 }
1010 if (!ident || ident->getType() != Element::string) {
1011 isc_throw(BadValue, "'identifier' is either missing or not a string.");
1012 }
1013
1014 // subnet-id is forbidden.
1015 if (params->contains("subnet-id")) {
1016 isc_throw(BadValue, "'subnet-id' is forbidden in reservation-get-by-id");
1017 }
1018
1019 // Got the parameters. Let's see if their values make sense.
1020
1021 // Try to parse the identifier value first.
1022 try {
1023 x.ident = util::str::quotedStringToBinary(ident->stringValue());
1024 if (x.ident.empty()) {
1025 util::str::decodeFormattedHexString(ident->stringValue(),
1026 x.ident);
1027 }
1028 } catch (...) {
1029 // The string doesn't match any known pattern, so we have to
1030 // report an error at this point.
1031 isc_throw(BadValue, "Unable to parse 'identifier' value.");
1032 }
1033
1034 if (x.ident.empty()) {
1035 isc_throw(BadValue, "Unable to query for empty 'identifier'.");
1036 }
1037
1038 // Next, try to convert identifier-type
1039 try {
1040 x.type = Host::getIdentifierType(type->stringValue());
1041 } catch (const std::exception& ex) {
1042 isc_throw(BadValue, "Value of 'identifier-type' was not recognized.");
1043 }
1044
1045 x.operation_target = getOperationTarget(params);
1046
1047 return (x);
1048}
1049
1051HostCmdsImpl::getByAddressParameters(const ConstElementPtr& params) {
1052 Parameters x;
1053
1054 if (!params || params->getType() != Element::map) {
1055 isc_throw(BadValue, "Parameters missing or are not a map.");
1056 }
1057
1058 // We support 1 type of reservation-get-by-address:
1059 // reservation-get-by-address(subnet-id, address, operation-target)
1060 // where subnet-id and operation-target are optional
1061 IOAddress addr = data::SimpleParser::getAddress(params, "ip-address");
1062 if (!addr.isV4() && !addr.isV6()) {
1063 isc_throw(BadValue, "Failed to parse IP address " << addr);
1064 }
1065
1066 x.addr = addr;
1067 x.query_by_addr = true;
1068
1069 if (params->contains("subnet-id")) {
1070 int64_t tmp = data::SimpleParser::getInteger(params, "subnet-id",
1071 0, dhcp::SUBNET_ID_MAX);
1072 x.subnet_id = static_cast<SubnetID>(tmp);
1073 x.has_subnet_id = true;
1074 }
1075
1076 x.operation_target = getOperationTarget(params);
1077
1078 return (x);
1079}
1080
1082HostCmdsImpl::getOperationTarget(const ConstElementPtr& args) {
1083 // Operation target is optional.
1084 if (!args->get("operation-target")) {
1085 return HostMgrOperationTarget::UNSPECIFIED_SOURCE;
1086 }
1087
1088 std::string raw = data::SimpleParser::getString(args, "operation-target");
1089
1090 if (raw == "memory") {
1091 return HostMgrOperationTarget::PRIMARY_SOURCE;
1092 } else if (raw == "database") {
1093 return HostMgrOperationTarget::ALTERNATE_SOURCES;
1094 } else if (raw == "all") {
1095 return HostMgrOperationTarget::ALL_SOURCES;
1096 } else if (raw == "default") {
1097 return HostMgrOperationTarget::UNSPECIFIED_SOURCE;
1098 } else {
1099 isc_throw(BadValue,
1100 "The 'operation-target' value (" << raw
1101 << ") is not within expected set: (memory, database, all, "
1102 << "default)");
1103 }
1104}
1105
1106int
1108 string txt = "(missing parameters)";
1109 Parameters p;
1110 ElementPtr hosts_json = Element::createList();
1111 try {
1112 extractCommand(handle);
1113 if (cmd_args_) {
1114 txt = cmd_args_->str();
1115 }
1116
1118 .arg(txt);
1119
1120 p = getAllParameters(cmd_args_);
1123 }
1124
1125 ConstHostCollection hosts;
1126 if (family_ == AF_INET) {
1127 validateHostForSubnet4(p.subnet_id,
1130 } else {
1131 validateHostForSubnet6(p.subnet_id, std::vector<IOAddress>());
1133 }
1134 for (auto const& host : hosts) {
1135 ElementPtr host_json;
1136 if (family_ == AF_INET) {
1137 host_json = host->toElement4();
1138 SubnetID subnet_id = host->getIPv4SubnetID();
1139 host_json->set("subnet-id", Element::create(subnet_id));
1140 } else {
1141 host_json = host->toElement6();
1142 SubnetID subnet_id = host->getIPv6SubnetID();
1143 host_json->set("subnet-id", Element::create(subnet_id));
1144 }
1145 hosts_json->add(host_json);
1146 }
1147 } catch (const std::exception& ex) {
1149 .arg(txt)
1150 .arg(ex.what());
1151 setErrorResponse(handle, ex.what());
1152 return (1);
1153 }
1154
1156 .arg(txt);
1157
1158 ostringstream msg;
1159 msg << hosts_json->size()
1160 << " IPv" << (family_ == AF_INET ? "4" : "6")
1161 << " host(s) found.";
1162 ElementPtr result = Element::createMap();
1163 result->set("hosts", hosts_json);
1164
1165 ConstElementPtr response = createAnswer(hosts_json->size() > 0 ?
1168 msg.str(), result);
1169 setResponse(handle, response);
1170
1171 return (0);
1172}
1173
1174int
1176 string txt = "(missing parameters)";
1177 Parameters p;
1178 size_t idx;
1179 ElementPtr hosts_json = Element::createList();
1180 uint64_t last_id(0);
1181 try {
1182 extractCommand(handle);
1183 if (cmd_args_) {
1184 txt = cmd_args_->str();
1185 }
1186
1188 .arg(txt);
1189
1190 p = getPageParameters(cmd_args_);
1191 idx = p.source_index;
1192 HostPageSize page_size(p.page_limit);
1193 ConstHostCollection hosts;
1194 if (p.has_subnet_id) {
1195 if (family_ == AF_INET) {
1196 validateHostForSubnet4(p.subnet_id,
1198 hosts = HostMgr::instance().getPage4(p.subnet_id, idx,
1199 p.host_id, page_size);
1200 } else {
1201 validateHostForSubnet6(p.subnet_id, std::vector<IOAddress>());
1202 hosts = HostMgr::instance().getPage6(p.subnet_id, idx,
1203 p.host_id, page_size);
1204 }
1205 } else {
1206 if (family_ == AF_INET) {
1207 hosts = HostMgr::instance().getPage4(idx, p.host_id, page_size);
1208 } else {
1209 hosts = HostMgr::instance().getPage6(idx, p.host_id, page_size);
1210 }
1211 }
1212 SubnetID subnet_id = p.subnet_id;
1213 ElementPtr host_json;
1214 for (auto const& host : hosts) {
1215 if (!p.has_subnet_id) {
1216 if (family_ == AF_INET) {
1217 subnet_id = host->getIPv4SubnetID();
1218 } else {
1219 subnet_id = host->getIPv6SubnetID();
1220 }
1221 if (subnet_id == SUBNET_ID_UNUSED) {
1222 continue;
1223 }
1224 }
1225 if (family_ == AF_INET) {
1226 host_json = host->toElement4();
1227 } else {
1228 host_json = host->toElement6();
1229 }
1230 host_json->set("subnet-id", Element::create(subnet_id));
1231 hosts_json->add(host_json);
1232 last_id = host->getHostId();
1233 }
1234 } catch (const std::exception& ex) {
1236 .arg(txt)
1237 .arg(ex.what());
1238 setErrorResponse(handle, ex.what());
1239 return (1);
1240 }
1241
1243 .arg(txt);
1244
1245 ostringstream msg;
1246 msg << hosts_json->size()
1247 << " IPv" << (family_ == AF_INET ? "4" : "6")
1248 << " host(s) found.";
1249 ElementPtr result = Element::createMap();
1250 result->set("hosts", hosts_json);
1251 result->set("count",
1252 Element::create(static_cast<int64_t>(hosts_json->size())));
1253 if (hosts_json->size() > 0) {
1255 next->set("source-index",
1256 Element::create(static_cast<int64_t>(idx)));
1257 next->set("from", Element::create(static_cast<int64_t>(last_id)));
1258 result->set("next", next);
1259 }
1260
1261 ConstElementPtr response = createAnswer(hosts_json->size() > 0 ?
1264 msg.str(), result);
1265 setResponse(handle, response);
1266
1267 return (0);
1268}
1269
1270int
1272 string txt = "(missing parameters)";
1273 Parameters p;
1274 ElementPtr hosts_json = Element::createList();
1275 try {
1276 extractCommand(handle);
1277 if (cmd_args_) {
1278 txt = cmd_args_->str();
1279 }
1280
1282 .arg(txt);
1283
1284 p = getByHostnameParameters(cmd_args_);
1287 }
1288
1289 string hostname = p.hostname;
1290 if (hostname.empty()) {
1291 isc_throw(isc::BadValue, "Empty hostname");
1292 }
1293 boost::algorithm::to_lower(hostname);
1294 ConstHostCollection hosts;
1295 if (p.has_subnet_id) {
1296 if (family_ == AF_INET) {
1297 validateHostForSubnet4(p.subnet_id,
1299 hosts = HostMgr::instance().getAllbyHostname4(hostname,
1300 p.subnet_id,
1302 } else {
1303 validateHostForSubnet6(p.subnet_id, std::vector<IOAddress>());
1304 hosts = HostMgr::instance().getAllbyHostname6(hostname,
1305 p.subnet_id,
1307 }
1308 } else {
1310 }
1311
1312 // Add the subnet-id when it was not specified by the command
1313 // parameters and filter out wrong universe entries.
1314 SubnetID subnet_id = p.subnet_id;
1315 ElementPtr host_json;
1316 for (auto const& host : hosts) {
1317 if (!p.has_subnet_id) {
1318 if (family_ == AF_INET) {
1319 subnet_id = host->getIPv4SubnetID();
1320 } else {
1321 subnet_id = host->getIPv6SubnetID();
1322 }
1323 if (subnet_id == SUBNET_ID_UNUSED) {
1324 continue;
1325 }
1326 }
1327 if (family_ == AF_INET) {
1328 host_json = host->toElement4();
1329 } else {
1330 host_json = host->toElement6();
1331 }
1332 host_json->set("subnet-id", Element::create(subnet_id));
1333 hosts_json->add(host_json);
1334 }
1335 } catch (const std::exception& ex) {
1337 .arg(txt)
1338 .arg(ex.what());
1339 setErrorResponse(handle, ex.what());
1340 return (1);
1341 }
1342
1344 .arg(txt);
1345
1346 ostringstream msg;
1347 msg << hosts_json->size()
1348 << " IPv" << (family_ == AF_INET ? "4" : "6")
1349 << " host(s) found.";
1350 ElementPtr result = Element::createMap();
1351 result->set("hosts", hosts_json);
1352
1353 ConstElementPtr response = createAnswer(hosts_json->size() > 0 ?
1356 msg.str(), result);
1357 setResponse(handle, response);
1358
1359 return (0);
1360}
1361
1362int
1364 string txt = "(missing parameters)";
1365 Parameters p;
1366 ElementPtr hosts_json = Element::createList();
1367 try {
1368 extractCommand(handle);
1369 if (cmd_args_) {
1370 txt = cmd_args_->str();
1371 }
1372
1374 .arg(txt);
1375
1376 p = getByIdParameters(cmd_args_);
1379 }
1380
1381 ConstHostCollection hosts;
1382 hosts = HostMgr::instance().getAll(p.type, &p.ident[0], p.ident.size(),
1384 SubnetID subnet_id;
1385 ElementPtr host_json;
1386 for (auto const& host : hosts) {
1387 if (family_ == AF_INET) {
1388 subnet_id = host->getIPv4SubnetID();
1389 } else {
1390 subnet_id = host->getIPv6SubnetID();
1391 }
1392 if (subnet_id == SUBNET_ID_UNUSED) {
1393 continue;
1394 }
1395 if (family_ == AF_INET) {
1396 host_json = host->toElement4();
1397 } else {
1398 host_json = host->toElement6();
1399 }
1400 host_json->set("subnet-id", Element::create(subnet_id));
1401 hosts_json->add(host_json);
1402 }
1403 } catch (const std::exception& ex) {
1405 .arg(txt)
1406 .arg(ex.what());
1407 setErrorResponse(handle, ex.what());
1408 return (1);
1409 }
1410
1412 .arg(txt);
1413
1414 ostringstream msg;
1415 msg << hosts_json->size()
1416 << " IPv" << (family_ == AF_INET ? "4" : "6")
1417 << " host(s) found.";
1418 ElementPtr result = Element::createMap();
1419 result->set("hosts", hosts_json);
1420
1421 ConstElementPtr response = createAnswer(hosts_json->size() > 0 ?
1424 msg.str(), result);
1425 setResponse(handle, response);
1426
1427 return (0);
1428}
1429
1430int
1432 string parameters("(missing parameters)");
1433 try {
1434 // Basic command extraction
1435 extractCommand(handle);
1436 if (cmd_args_) {
1437 parameters = cmd_args_->str();
1438 }
1439
1441 .arg(parameters);
1442
1443 // Sanity checks
1444 if (!cmd_args_) {
1446 "invalid command: does not contain mandatory '" << CONTROL_ARGUMENTS << "'");
1447 }
1448 if (cmd_args_->getType() != Element::map) {
1449 isc_throw(BadValue, "invalid command: expected '"
1450 << CONTROL_ARGUMENTS << "' to be a map, got "
1451 << Element::typeToName(cmd_args_->getType()) << " instead");
1452 }
1453 ConstElementPtr const reservation(cmd_args_->get("reservation"));
1454 if (!reservation) {
1455 isc_throw(BadValue, "invalid command: expected 'reservation' as the sole parameter "
1456 "inside the 'arguments' map, didn't get it instead");
1457 }
1458 if (reservation->getType() != Element::map) {
1459 isc_throw(BadValue, "invalid command: expected 'reservation' to be a map, got "
1460 << Element::typeToName(reservation->getType()) << " instead");
1461 }
1462
1463 HostMgrOperationTarget operation_target = getOperationTarget(cmd_args_);
1464 if (operation_target == HostMgrOperationTarget::UNSPECIFIED_SOURCE) {
1466 }
1467
1468 // Parse host-specific parameters.
1469 HostPtr host;
1470 if (family_ == AF_INET) {
1471 HostDataParser4 parser;
1472 host = parser.parseWithSubnet(reservation);
1473 } else {
1474 HostDataParser6 parser;
1475 host = parser.parseWithSubnet(reservation);
1476 }
1477
1478 // If db_storage_ was not accessed yet, try to retrieve it.
1479 if (!db_storage_) {
1480 db_storage_ = HostMgr::instance().getHostDataSource();
1481 }
1482
1483 if (!db_storage_ && operation_target == HostMgrOperationTarget::ALTERNATE_SOURCES) {
1484 // If it's still not available, bail out.
1485 isc_throw(BadValue, "host database not available, cannot update host");
1486 }
1487
1488 if (family_ == AF_INET) {
1489 // Validate the IPv4 subnet id against configured subnet and also verify
1490 // that the reserved IPv4 address (if non-zero) belongs to this subnet.
1491 validateHostForSubnet4(host->getIPv4SubnetID(),
1492 host->getIPv4Reservation());
1493
1494 } else {
1495 // Retrieve all reserved addresses from the host. We're going to
1496 // check if these addresses are in range with the specified subnet.
1497 // If any of them is not in range, we will reject the command.
1498 // Note that we do not validate delegated prefixes because they don't
1499 // have to match the subnet prefix.
1500 auto const& range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
1501 std::vector<IOAddress> addresses;
1502 BOOST_FOREACH(auto const& address, range) {
1503 addresses.push_back(address.second.getPrefix());
1504 }
1505 // Validate the IPv6 subnet id against configured subnet and also
1506 // verify that the reserved IPv6 addresses (if any) belong to this
1507 // subnet.
1508 validateHostForSubnet6(host->getIPv6SubnetID(), addresses);
1509 }
1510
1511 // Do the update.
1512 HostMgr::instance().update(host, operation_target);
1513 } catch (exception const& exception) {
1515 .arg(parameters)
1516 .arg(exception.what());
1517 setErrorResponse(handle, exception.what());
1518 return (1);
1519 }
1520
1522 setSuccessResponse(handle, "Host updated.");
1523
1524 return (0);
1525}
1526
1528 :impl_(new HostCmdsImpl()) {
1529}
1530
1531int
1533 return (impl_->reservationAddHandler(handle));
1534}
1535
1536int
1538 return (impl_->reservationGetHandler(handle));
1539}
1540
1541int
1543 return (impl_->reservationDelHandler(handle));
1544}
1545
1546int
1548 return (impl_->reservationGetAllHandler(handle));
1549}
1550
1551int
1553 return (impl_->reservationGetPageHandler(handle));
1554}
1555
1556int
1558 return (impl_->reservationGetByHostnameHandler(handle));
1559}
1560
1561int
1563 return (impl_->reservationGetByIdHandler(handle));
1564}
1565
1566int
1568 return (impl_->reservationUpdateHandler(handle));
1569}
1570
1571int
1573 return (impl_->reservationGetByAddressHandler(handle));
1574}
1575
1576} // namespace host_cmds
1577} // namespace isc
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static std::string typeToName(Element::types type)
Returns the name of the given type as a string.
Definition data.cc:651
@ map
Definition data.h:147
@ string
Definition data.h:144
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Base class that command handler implementers may use for common tasks.
Definition cmds_impl.h:21
void setErrorResponse(hooks::CalloutHandle &handle, const std::string &text, int status=CONTROL_RESULT_ERROR)
Set the callout argument "response" to indicate an error.
Definition cmds_impl.h:54
data::ConstElementPtr cmd_args_
Stores the command arguments extracted by a call to extractCommand.
Definition cmds_impl.h:72
void extractCommand(hooks::CalloutHandle &handle)
Extracts the command name and arguments from a Callout handle.
Definition cmds_impl.h:29
void setSuccessResponse(hooks::CalloutHandle &handle, const std::string &text)
Set the callout argument "response" to indicate success.
Definition cmds_impl.h:43
void setResponse(hooks::CalloutHandle &handle, data::ConstElementPtr &response)
Set the callout argument "response" to the given response.
Definition cmds_impl.h:64
static isc::asiolink::IOAddress getAddress(const ConstElementPtr &scope, const std::string &name)
Returns a IOAddress parameter from a scope.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
uint16_t getFamily() const
Returns address family.
Definition cfgmgr.h:246
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
ConstHostCollection getAll6(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv6 subnet.
Definition host_mgr.cc:171
ConstHostCollection getAll4(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv4 subnet.
Definition host_mgr.cc:151
virtual ConstHostCollection getPage6(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const
Returns range of hosts in a DHCPv6 subnet.
Definition host_mgr.cc:290
ConstHostCollection getAllbyHostname4(const std::string &hostname, const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts with a hostname in a DHCPv4 subnet.
Definition host_mgr.cc:211
bool del4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target)
Attempts to delete a host by (subnet4-id, identifier, identifier-type, operation-target)
Definition host_mgr.cc:824
ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
Definition host_mgr.cc:123
bool del6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target)
Attempts to delete a host by (subnet6-id, identifier, identifier-type, operation-target)
Definition host_mgr.cc:861
void add(const HostPtr &host, const HostMgrOperationTarget target)
Adds a new host to the alternate data source.
Definition host_mgr.cc:764
bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr, const HostMgrOperationTarget target)
Attempts to delete hosts by address.
Definition host_mgr.cc:794
ConstHostCollection getAllbyHostname6(const std::string &hostname, const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts with a hostname in a DHCPv6 subnet.
Definition host_mgr.cc:235
virtual ConstHostCollection getPage4(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const
Returns range of hosts in a DHCPv4 subnet.
Definition host_mgr.cc:259
HostDataSourcePtr getHostDataSource() const
Returns the first host data source.
Definition host_mgr.cc:84
static HostMgr & instance()
Returns a sole instance of the HostMgr.
Definition host_mgr.cc:114
void update(HostPtr const &host, const HostMgrOperationTarget target)
Implements BaseHostDataSource::update() for alternate sources.
Definition host_mgr.cc:898
ConstHostCollection getAllbyHostname(const std::string &hostname, const HostMgrOperationTarget target) const
Return all hosts with a hostname.
Definition host_mgr.cc:191
ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv4 subnet.
Definition host_mgr.cc:465
ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv6 subnet.
Definition host_mgr.cc:650
Wraps value holding size of the page with host reservations.
Represents a device with IPv4 and/or IPv6 reservations.
Definition host.h:327
IdentifierType
Type of the host identifier.
Definition host.h:337
IdentifierType getIdentifierType() const
Returns the identifier type.
Definition host.cc:273
Per-packet callout handle.
Parameters specified for reservation-get and reservation-del.
Definition host_cmds.cc:60
HostMgrOperationTarget operation_target
Specifies the target host source (default UNSPECIFIED_SOURCE which means the default host source is c...
Definition host_cmds.cc:97
std::string hostname
Specifies host name (default "").
Definition host_cmds.cc:93
uint64_t host_id
Specifies host identifier (default 0).
Definition host_cmds.cc:90
std::vector< uint8_t > ident
Specifies identifier value (used when query_by_addr is false)
Definition host_cmds.cc:77
SubnetID subnet_id
Specifies subnet-id.
Definition host_cmds.cc:64
bool query_by_addr
Specifies parameter types (true = query by address, false = query by identifier-type,...
Definition host_cmds.cc:81
size_t source_index
Specifies source index (default 0).
Definition host_cmds.cc:87
Host::IdentifierType type
Specifies identifier type (usually FLEX_ID, used when query_by_addr is false)
Definition host_cmds.cc:74
IOAddress addr
Specifies IPv4 or IPv6 address (used when query_by_addr is true)
Definition host_cmds.cc:70
bool has_subnet_id
Specifies if subnet-id is present.
Definition host_cmds.cc:67
size_t page_limit
Specifies page limit (no default).
Definition host_cmds.cc:84
Wrapper class around reservation command handlers.
Definition host_cmds.cc:42
int reservationGetAllHandler(CalloutHandle &handle)
reservation-get-all command handler
int reservationAddHandler(CalloutHandle &handle)
reservation-add command handler
Definition host_cmds.cc:345
int reservationGetPageHandler(CalloutHandle &handle)
reservation-get-page command handler
int reservationGetHandler(CalloutHandle &handle)
reservation-get command handler
Definition host_cmds.cc:702
int reservationUpdateHandler(CalloutHandle &handle)
reservation-update command handler
int reservationGetByHostnameHandler(CalloutHandle &handle)
reservation-get-by-hostname command handler
int reservationDelHandler(CalloutHandle &handle)
reservation-del command handler
Definition host_cmds.cc:864
int reservationGetByAddressHandler(CalloutHandle &handle)
reservation-get-by-address command handler
Definition host_cmds.cc:773
int reservationGetByIdHandler(CalloutHandle &handle)
reservation-get-by-id command handler
int reservationGetPageHandler(hooks::CalloutHandle &handle)
reservation-get-page command handler
int reservationGetAllHandler(hooks::CalloutHandle &handle)
reservation-get-all command handler
int reservationGetByAddressHandler(hooks::CalloutHandle &handle)
reservation-get-by-address command handler
int reservationGetByHostnameHandler(hooks::CalloutHandle &handle)
reservation-get-by-hostname command handler
int reservationUpdateHandler(hooks::CalloutHandle &handle)
reservation-update command handler
int reservationGetHandler(hooks::CalloutHandle &handle)
reservation-get command handler
int reservationAddHandler(hooks::CalloutHandle &handle)
reservation-add command handler
int reservationDelHandler(hooks::CalloutHandle &handle)
reservation-del command handler
int reservationGetByIdHandler(hooks::CalloutHandle &handle)
reservation-get-by-id command handler
isc::dhcp::HostPtr parseWithSubnet(isc::data::ConstElementPtr host_data, bool required=true)
Parser specified parameter as host reservation data.
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
const isc::log::MessageID HOST_CMDS_RESERV_UPDATE
const isc::log::MessageID HOST_CMDS_RESERV_GET_ALL_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_ADD
const isc::log::MessageID HOST_CMDS_RESERV_GET_PAGE
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_HOSTNAME_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_DEL_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_ADD_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_ID
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_ADDRESS_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_PAGE_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_GET
const isc::log::MessageID HOST_CMDS_RESERV_DEL
const isc::log::MessageID HOST_CMDS_RESERV_UPDATE_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_PAGE_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_ID_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_ADDRESS_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_GET_ALL_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_UPDATE_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_GET_ALL
const isc::log::MessageID HOST_CMDS_RESERV_DEL_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_HOSTNAME_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_ID_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_ADD_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_SUCCESS
const isc::log::MessageID HOST_CMDS_RESERV_GET_FAILED
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_HOSTNAME
const isc::log::MessageID HOST_CMDS_RESERV_GET_BY_ADDRESS
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
const char * CONTROL_ARGUMENTS
String used for arguments map ("arguments")
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< BaseHostDataSource > HostDataSourcePtr
HostDataSource pointer.
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:623
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition host.h:837
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Definition host.h:843
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:458
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition host.h:840
HostMgrOperationTarget
Definition host_mgr.h:25
@ ALTERNATE_SOURCES
Definition host_mgr.h:31
@ UNSPECIFIED_SOURCE
Definition host_mgr.h:27
@ ALL_SOURCES
Definition host_mgr.h:33
isc::log::Logger host_cmds_logger("host-cmds-hooks")
HostDataParser< isc::dhcp::HostReservationParser6 > HostDataParser6
Parser for DHCPv4 host reservation.
HostDataParser< isc::dhcp::HostReservationParser4 > HostDataParser4
Parser for DHCPv4 host reservation.
void decodeFormattedHexString(const string &hex_string, vector< uint8_t > &binary)
Converts a formatted string of hexadecimal digits into a vector.
Definition str.cc:212
vector< uint8_t > quotedStringToBinary(const string &quoted_string)
Converts a string in quotes into vector.
Definition str.cc:139
Defines the logger used by the top-level component of kea-lfc.