From: Francis Dupont Date: Wed, 16 Oct 2019 20:08:34 +0000 (+0200) Subject: [393-global-search-through-leases-by-mac-or-hostname-w-o-specifying-a-subnet-id]... X-Git-Tag: Kea-1.7.1~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=53d0bd5319a0ad982830657ee3fbddace1e97e6f;p=thirdparty%2Fkea.git [393-global-search-through-leases-by-mac-or-hostname-w-o-specifying-a-subnet-id] Implemented new commands --- diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.cc b/src/hooks/dhcp/lease_cmds/lease_cmds.cc index 5ec7bce1f1..7ded5be594 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -174,6 +175,51 @@ public: int leaseGetPageHandler(hooks::CalloutHandle& handle); + /// @brief lease4-get-by-hw-address command handler + /// + /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::leaseGetByHwAddressHandler + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByHwAddressHandler(hooks::CalloutHandle& handle); + + /// @brief lease4-get-by-client-id command handler + /// + /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::leaseGetByClientIdHandler + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByClientIdHandler(hooks::CalloutHandle& handle); + + /// @brief lease6-get-by-duid command handler + /// + /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::leaseGetByDuidHandler + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByDuidHandler(hooks::CalloutHandle& handle); + + /// @brief lease4-get-by-hostname and lease6-get-by-hostname commands + /// handler + /// + /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::leaseGetByHostnameHandler + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByHostnameHandler(hooks::CalloutHandle& handle); + /// @brief lease4-del command handler /// /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::lease4DelHandler @@ -748,6 +794,230 @@ LeaseCmdsImpl::leaseGetPageHandler(CalloutHandle& handle) { return (CONTROL_RESULT_SUCCESS); } +int +LeaseCmdsImpl::leaseGetByHwAddressHandler(CalloutHandle& handle) { + try { + extractCommand(handle); + + // arguments must always be present + if (!cmd_args_) { + isc_throw(BadValue, "no parameters specified for the " << cmd_name_ + << " command"); + } + + // the hw-address parameter is mandatory. + ConstElementPtr hw_address = cmd_args_->get("hw-address"); + if (!hw_address) { + isc_throw(BadValue, "'hw-address' parameter not specified"); + } + + // The 'hw-address' argument is a string. + if (hw_address->getType() != Element::string) { + isc_throw(BadValue, "'hw-address'parameter must be a string"); + } + + HWAddr hwaddr = HWAddr::fromText(hw_address->stringValue()); + + Lease4Collection leases = + LeaseMgrFactory::instance().getLease4(hwaddr); + ElementPtr leases_json = Element::createList(); + for (auto lease : leases) { + ElementPtr lease_json = lease->toElement(); + leases_json->add(lease_json); + } + + std::ostringstream s; + s << leases_json->size() << " IPv4 lease(s) found."; + ElementPtr args = Element::createMap(); + args->set("leases", leases_json); + ConstElementPtr response = + createAnswer(leases_json->size() > 0 ? + CONTROL_RESULT_SUCCESS : + CONTROL_RESULT_EMPTY, + s.str(), args); + setResponse(handle, response); + + } catch (const std::exception& ex) { + setErrorResponse(handle, ex.what()); + return (CONTROL_RESULT_ERROR); + } + + return (0); +} + +int +LeaseCmdsImpl::leaseGetByClientIdHandler(CalloutHandle& handle) { + try { + extractCommand(handle); + + // arguments must always be present + if (!cmd_args_) { + isc_throw(BadValue, "no parameters specified for the " << cmd_name_ + << " command"); + } + + // the client-id parameter is mandatory. + ConstElementPtr client_id = cmd_args_->get("client-id"); + if (!client_id) { + isc_throw(BadValue, "'client-id' parameter not specified"); + } + + // The 'client-id' argument is a string. + if (client_id->getType() != Element::string) { + isc_throw(BadValue, "'client-id'parameter must be a string"); + } + + ClientIdPtr clientid = ClientId::fromText(client_id->stringValue()); + + Lease4Collection leases = + LeaseMgrFactory::instance().getLease4(*clientid); + ElementPtr leases_json = Element::createList(); + for (auto lease : leases) { + ElementPtr lease_json = lease->toElement(); + leases_json->add(lease_json); + } + + std::ostringstream s; + s << leases_json->size() << " IPv4 lease(s) found."; + ElementPtr args = Element::createMap(); + args->set("leases", leases_json); + ConstElementPtr response = + createAnswer(leases_json->size() > 0 ? + CONTROL_RESULT_SUCCESS : + CONTROL_RESULT_EMPTY, + s.str(), args); + setResponse(handle, response); + + } catch (const std::exception& ex) { + setErrorResponse(handle, ex.what()); + return (CONTROL_RESULT_ERROR); + } + + return (0); +} + +int +LeaseCmdsImpl::leaseGetByDuidHandler(CalloutHandle& handle) { + try { + extractCommand(handle); + + // arguments must always be present + if (!cmd_args_) { + isc_throw(BadValue, "no parameters specified for the " << cmd_name_ + << " command"); + } + + // the duid parameter is mandatory. + ConstElementPtr duid = cmd_args_->get("duid"); + if (!duid) { + isc_throw(BadValue, "'duid' parameter not specified"); + } + + // The 'duid' argument is a string. + if (duid->getType() != Element::string) { + isc_throw(BadValue, "'duid'parameter must be a string"); + } + + DUID duid_ = DUID::fromText(duid->stringValue()); + + Lease6Collection leases = + LeaseMgrFactory::instance().getLeases6(duid_); + ElementPtr leases_json = Element::createList(); + for (auto lease : leases) { + ElementPtr lease_json = lease->toElement(); + leases_json->add(lease_json); + } + + std::ostringstream s; + s << leases_json->size() << " IPv4 lease(s) found."; + ElementPtr args = Element::createMap(); + args->set("leases", leases_json); + ConstElementPtr response = + createAnswer(leases_json->size() > 0 ? + CONTROL_RESULT_SUCCESS : + CONTROL_RESULT_EMPTY, + s.str(), args); + setResponse(handle, response); + + } catch (const std::exception& ex) { + setErrorResponse(handle, ex.what()); + return (CONTROL_RESULT_ERROR); + } + + return (0); +} + +int +LeaseCmdsImpl::leaseGetByHostnameHandler(CalloutHandle& handle) { + bool v4; + try { + extractCommand(handle); + v4 = (cmd_name_ == "lease4-get-by-hostname"); + + // arguments must always be present + if (!cmd_args_) { + isc_throw(BadValue, "no parameters specified for the " << cmd_name_ + << " command"); + } + + // the hostname parameter is mandatory. + ConstElementPtr hostname = cmd_args_->get("hostname"); + if (!hostname) { + isc_throw(BadValue, "'hostname' parameter not specified"); + } + + // The 'hostname' argument is a string. + if (hostname->getType() != Element::string) { + isc_throw(BadValue, "'hostname'parameter must be a string"); + } + + std::string hostname_ = hostname->stringValue(); + /// The 'hostname' argument should not be empty. + if (hostname_.empty()) { + isc_throw(BadValue, "'hostname' parameter is empty"); + } + boost::algorithm::to_lower(hostname_); + + ElementPtr leases_json = Element::createList(); + if (v4) { + Lease4Collection leases = + LeaseMgrFactory::instance().getLeases4(hostname_); + + for (auto lease : leases) { + ElementPtr lease_json = lease->toElement(); + leases_json->add(lease_json); + } + } else { + Lease6Collection leases = + LeaseMgrFactory::instance().getLeases6(hostname_); + + for (auto lease : leases) { + ElementPtr lease_json = lease->toElement(); + leases_json->add(lease_json); + } + } + + std::ostringstream s; + s << leases_json->size() + << " IPv" << (v4 ? "4" : "6") + << " lease(s) found."; + ElementPtr args = Element::createMap(); + args->set("leases", leases_json); + ConstElementPtr response = + createAnswer(leases_json->size() > 0 ? + CONTROL_RESULT_SUCCESS : + CONTROL_RESULT_EMPTY, + s.str(), args); + setResponse(handle, response); + + } catch (const std::exception& ex) { + setErrorResponse(handle, ex.what()); + return (CONTROL_RESULT_ERROR); + } + + return (0); +} + int LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) { Parameters p; @@ -1264,7 +1534,7 @@ LeaseCmdsImpl::getIPv6AddressForDelete(const Parameters& parameters) const { if (lease6) { addr = lease6->addr_; } - + break; default: @@ -1323,6 +1593,26 @@ LeaseCmds::leaseGetPageHandler(hooks::CalloutHandle& handle) { return (impl_->leaseGetPageHandler(handle)); } +int +LeaseCmds::leaseGetByHwAddressHandler(hooks::CalloutHandle& handle) { + return (impl_->leaseGetByHwAddressHandler(handle)); +} + +int +LeaseCmds::leaseGetByClientIdHandler(hooks::CalloutHandle& handle) { + return (impl_->leaseGetByClientIdHandler(handle)); +} + +int +LeaseCmds::leaseGetByDuidHandler(hooks::CalloutHandle& handle) { + return (impl_->leaseGetByDuidHandler(handle)); +} + +int +LeaseCmds::leaseGetByHostnameHandler(hooks::CalloutHandle& handle) { + return (impl_->leaseGetByHostnameHandler(handle)); +} + int LeaseCmds::lease4DelHandler(CalloutHandle& handle) { return(impl_->lease4DelHandler(handle)); diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.h b/src/hooks/dhcp/lease_cmds/lease_cmds.h index 66c2851a9c..1f8e8481df 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.h +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.h @@ -258,6 +258,87 @@ public: int leaseGetPageHandler(hooks::CalloutHandle& handle); + /// @brief lease4-get-by-hw-address command handler + /// + /// This command attempts to retrieve all IPv4 leases with a particular + /// hardware address. + /// + /// Example command: + /// { + /// "command": "lease4-get-by-hw-address", + /// "arguments": { + /// "hwaddr": "00:01:02:03:04:05" + /// } + /// } + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByHwAddressHandler(hooks::CalloutHandle& handle); + + /// @brief lease4-get-by-client-id command handler + /// + /// This command attempts to retrieve all IPv4 leases with a particular + /// Client Id. + /// + /// Example command: + /// { + /// "command": "lease4-get-by-client-id", + /// "arguments": { + /// "client-id": "this-is-a-client" + /// } + /// } + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByClientIdHandler(hooks::CalloutHandle& handle); + + /// @brief lease6-get-by-duid command handler + /// + /// This command attempts to retrieve all IPv6 leases with a particular + /// DUID. + /// + /// Example command: + /// { + /// "command": "lease6-get-by-duid", + /// "arguments": { + /// "duid": "01:02:03:04:05:06:07:08" + /// } + /// } + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByDuidHandler(hooks::CalloutHandle& handle); + + /// @brief lease4-get-by-hostname and lease6-get-by-hostname commands + /// handler + /// + /// Thesecommands attempt to retrieve all IPv4 or Ipv6 leases with + /// a particular hostname. + /// + /// Example command for v4: + /// { + /// "command": "lease4-get-by-hostname", + /// "arguments": { + /// "hostname": "urania.example.org" + /// } + /// } + /// + /// @param handle Callout context - which is expected to contain the + /// get command JSON text in the "command" argument + /// @return 0 if the handler has been invoked successfully, 1 if an + /// error occurs, 3 if no leases are returned. + int + leaseGetByHostnameHandler(hooks::CalloutHandle& handle); + /// @brief lease4-del command handler /// /// This command attempts to delete an IPv4 lease that match selected diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc b/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc index b610af68fe..1b28e4615e 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc @@ -121,6 +121,61 @@ int lease6_get_page(CalloutHandle& handle) { return (lease_cmds.leaseGetPageHandler(handle)); } +/// @brief This is a command callout for 'lease4-get-by-hw-address' command. +/// +/// @param handle Callout handle used to retrieve a command and +/// provide a response. +/// @return 0 if this callout has been invoked successfully, +/// 1 if an error occurs, 3 if no leases are returned. +int lease4_get_by_hw_address(CalloutHandle& handle) { + LeaseCmds lease_cmds; + return (lease_cmds.leaseGetByHwAddressHandler(handle)); +} + +/// @brief This is a command callout for 'lease4-get-by-client-id' command. +/// +/// @param handle Callout handle used to retrieve a command and +/// provide a response. +/// @return 0 if this callout has been invoked successfully, +/// 1 if an error occurs, 3 if no leases are returned. +int lease4_get_by_client_id(CalloutHandle& handle) { + LeaseCmds lease_cmds; + return (lease_cmds.leaseGetByClientIdHandler(handle)); +} + +/// @brief This is a command callout for 'lease6-get-by-duid' command. +/// +/// @param handle Callout handle used to retrieve a command and +/// provide a response. +/// @return 0 if this callout has been invoked successfully, +/// 1 if an error occurs, 3 if no leases are returned. +int lease6_get_by_duid(CalloutHandle& handle) { + LeaseCmds lease_cmds; + return (lease_cmds.leaseGetByDuidHandler(handle)); +} + +/// @brief This is a command callout for 'lease4-get-by-hostname' command. +/// +/// @param handle Callout handle used to retrieve a command and +/// provide a response. +/// @return 0 if this callout has been invoked successfully, +/// 1 if an error occurs, 3 if no leases are returned. +int lease4_get_by_hostname(CalloutHandle& handle) { + LeaseCmds lease_cmds; + return (lease_cmds.leaseGetByHostnameHandler(handle)); +} + +/// @brief This is a command callout for 'lease6-get-by-hostname' command. +/// +/// @param handle Callout handle used to retrieve a command and +/// provide a response. +/// @return 0 if this callout has been invoked successfully, +/// 1 if an error occurs, 3 if no leases are returned. +int lease6_get_by_hostname(CalloutHandle& handle) { + LeaseCmds lease_cmds; + return (lease_cmds.leaseGetByHostnameHandler(handle)); +} + /// @brief This is a command callout for 'lease4-del' command. /// /// @param handle Callout handle used to retrieve a command and @@ -201,6 +256,15 @@ int load(LibraryHandle& handle) { handle.registerCommandCallout("lease6-get-all", lease6_get_all); handle.registerCommandCallout("lease4-get-page", lease4_get_page); handle.registerCommandCallout("lease6-get-page", lease6_get_page); + handle.registerCommandCallout("lease4-get-by-hw-address", + lease4_get_by_hw_address); + handle.registerCommandCallout("lease4-get-by-client-id", + lease4_get_by_client_id); + handle.registerCommandCallout("lease6-get-by-duid", lease6_get_by_duid); + handle.registerCommandCallout("lease4-get-by-hostname", + lease4_get_by_hostname); + handle.registerCommandCallout("lease6-get-by-hostname", + lease6_get_by_hostname); handle.registerCommandCallout("lease4-del", lease4_del); handle.registerCommandCallout("lease6-del", lease6_del); handle.registerCommandCallout("lease4-update", lease4_update);