]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1106] Added leaseX-resend-ddns command to Lease Commands hook lib
authorThomas Markwalder <tmark@isc.org>
Mon, 16 Mar 2020 12:28:30 +0000 (08:28 -0400)
committerThomas Markwalder <tmark@isc.org>
Thu, 19 Mar 2020 14:44:24 +0000 (10:44 -0400)
src/hooks/dhcp/lease_cmds/lease_cmds.*
    LeaseCmds::
        lease4ResendDdnsHandler()
        lease6ResendDdnsHandler()
    LeaseCmdsImpl::
        lease4ResendDdnsHandler()
        lease6ResendDdnsHandler()
        getAddressParam()

src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc
    lease4_resend_ddns()
    lease6_resend_ddns()

src/hooks/dhcp/lease_cmds/lease_cmds_messages.*
    New log messages

src/hooks/dhcp/lease_cmds/lease_cmds.cc
src/hooks/dhcp/lease_cmds/lease_cmds.h
src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc
src/hooks/dhcp/lease_cmds/lease_cmds_messages.cc
src/hooks/dhcp/lease_cmds/lease_cmds_messages.h
src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes

index 54bc8d3b6e23f4e229250adce030c07bb0c51a8e..90e22b77d6b7a7dc5565073c61d45c15fdf7a427 100644 (file)
@@ -14,6 +14,7 @@
 #include <dhcpsrv/dhcpsrv_exceptions.h>
 #include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/ncr_generator.h>
 #include <dhcpsrv/subnet_id.h>
 #include <dhcpsrv/sanity_checker.h>
 #include <dhcp/duid.h>
@@ -34,6 +35,7 @@
 
 using namespace isc::dhcp;
 using namespace isc::data;
+using namespace isc::dhcp_ddns;
 using namespace isc::config;
 using namespace isc::asiolink;
 using namespace isc::hooks;
@@ -282,6 +284,24 @@ public:
     int
     lease6WipeHandler(CalloutHandle& handle);
 
+    /// @brief lease4-resend-ddns handler
+    ///
+    /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::lease4ResendDdnsHandler
+    ///
+    /// @param handle Callout context - which is expected to contain the
+    /// wipe command JSON text in the "command" argument
+    /// @return 0 upon success, non-zero otherwise
+    int lease4ResendDdnsHandler(CalloutHandle& handle);
+
+    /// @brief lease6-resend-ddns handler
+    ///
+    /// Provides the implementation for @ref isc::lease_cmds::LeaseCmds::lease6ResendDdnsHandler
+    ///
+    /// @param handle Callout context - which is expected to contain the
+    /// wipe command JSON text in the "command" argument
+    /// @return 0 upon success, non-zero otherwise
+    int lease6ResendDdnsHandler(CalloutHandle& handle);
+
     /// @brief Extracts parameters required for reservation-get and reservation-del
     ///
     /// See @ref Parameters class for detailed description of what is expected
@@ -329,6 +349,16 @@ public:
                                     const DuidPtr& duid,
                                     const int control_result,
                                     const std::string& error_message) const;
+
+    /// @brief Fetches an IP address parameter from a map of parameters
+    /// @param map of parameters in which to look
+    /// @name name of the parameter desired
+    /// @family expected protocol family of the address parameter, AF_INET
+    /// or AF_INET6
+    /// @return IOAddress containing the value of the parameter.
+    /// @throw BadValue if the parameter is missing or invalid
+    IOAddress getAddressParam(ConstElementPtr params, const std::string name,
+                              short family = AF_INET) const;
 };
 
 int
@@ -1543,6 +1573,121 @@ LeaseCmdsImpl::getIPv6LeaseForDelete(const Parameters& parameters) const {
     return (lease6);
 }
 
+IOAddress
+LeaseCmdsImpl::getAddressParam(ConstElementPtr params, const std::string name,
+                               short family) const {
+    ConstElementPtr param = params->get(name);
+    if (!param) {
+        isc_throw(BadValue, "'" << name << "' parameter is missing.");
+    }
+
+    if (param->getType() != Element::string) {
+        isc_throw(BadValue, "'" << name << "' is not a string.");
+    }
+
+    IOAddress addr(0);
+    try {
+        addr = IOAddress(param->stringValue());
+    } catch (const std::exception& ex) {
+        isc_throw(BadValue, "'" << param->stringValue()
+                                << "' is not a valid IP address.");
+    }
+
+    if (addr.getFamily() != family) {
+        isc_throw(BadValue, "Invalid "
+                  << (family == AF_INET6 ? "IPv6" : "IPv4")
+                  << " address specified: " << param->stringValue());
+    }
+
+    return (addr);
+}
+
+int
+LeaseCmdsImpl::lease4ResendDdnsHandler(CalloutHandle& handle) {
+    Lease4Ptr lease;
+    std::stringstream ss;
+
+    try {
+        extractCommand(handle);
+
+        // Get the target lease address. Invalid value will throw.
+        IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET);
+
+        // Find the lease.
+        lease = LeaseMgrFactory::instance().getLease4(addr);
+        if (!lease) {
+            ss << "No lease found for: " << addr.toText();
+        } else if (lease->hostname_.empty()) {
+            ss << "Lease for: " << addr.toText()
+               << ", has no hostname, nothing to update";
+        } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
+            ss << "Neither forward nor reverse updates enabled for lease for: "
+               << addr.toText();
+        } else if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
+            ss << "DDNS updating is not enabled";
+        } else {
+            // We have a lease with a hostname and updates in at least
+            // one direction enabled.  Queue an NCR for it.
+            queueNCR(CHG_ADD, lease);
+            ss << "NCR generated for: " << addr.toText()
+               << ", hostname: " << lease->hostname_;
+            setSuccessResponse(handle, ss.str());
+            LOG_INFO(lease_cmds_logger, LEASE_CMDS_RESEND_DDNS4).arg(ss.str());
+            return (CONTROL_RESULT_SUCCESS);
+        }
+    } catch (const std::exception& ex) {
+        ss << ex.what();
+    }
+
+    LOG_ERROR(lease_cmds_logger, LEASE_CMDS_RESEND_DDNS4_FAILED).arg(ss.str());
+    setErrorResponse(handle, ss.str());
+    return (CONTROL_RESULT_ERROR);
+}
+
+int
+LeaseCmdsImpl::lease6ResendDdnsHandler(CalloutHandle& handle) {
+    Lease6Ptr lease;
+    std::stringstream ss;
+
+    try {
+        extractCommand(handle);
+
+        // Get the target lease address. Invalid value will throw.
+        IOAddress addr = getAddressParam(cmd_args_, "ip-address", AF_INET6);
+
+        // Find the lease.
+        lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
+        if (!lease) {
+            ss << "No lease found for: " << addr.toText();
+        } else if (lease->hostname_.empty()) {
+            ss << "Lease for: " << addr.toText()
+               << ", has no hostname, nothing to update";
+        } else if (!lease->fqdn_fwd_ && !lease->fqdn_rev_) {
+            ss << "Neither forward nor reverse updates enabled for lease for: "
+               << addr.toText();
+        } else if (!CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
+            ss << "DDNS updating is not enabled";
+        } else {
+            // We have a lease with a hostname and updates in at least
+            // one direction enabled.  Queue an NCR for it.
+            queueNCR(CHG_ADD, lease);
+            ss << "NCR generated for: " << addr.toText()
+               << ", hostname: " << lease->hostname_;
+            setSuccessResponse(handle, ss.str());
+            LOG_INFO(lease_cmds_logger, LEASE_CMDS_RESEND_DDNS6).arg(ss.str());
+            return (CONTROL_RESULT_SUCCESS);
+        }
+    } catch (const std::exception& ex) {
+        ss << ex.what();
+    }
+
+    LOG_ERROR(lease_cmds_logger, LEASE_CMDS_RESEND_DDNS6_FAILED).arg(ss.str());
+    setErrorResponse(handle, ss.str());
+    return (CONTROL_RESULT_ERROR);
+}
+
+
+
 ElementPtr
 LeaseCmdsImpl::createFailedLeaseMap(const Lease::Type& lease_type,
                                     const IOAddress& lease_address,
@@ -1651,6 +1796,16 @@ LeaseCmds::lease6WipeHandler(CalloutHandle& handle) {
     return (impl_->lease6WipeHandler(handle));
 }
 
+int
+LeaseCmds::lease4ResendDdnsHandler(CalloutHandle& handle) {
+    return (impl_->lease4ResendDdnsHandler(handle));
+}
+
+int
+LeaseCmds::lease6ResendDdnsHandler(CalloutHandle& handle) {
+    return (impl_->lease6ResendDdnsHandler(handle));
+}
+
 LeaseCmds::LeaseCmds()
     :impl_(new LeaseCmdsImpl()) {
 }
index 86245f7f8079d40085e14ee0c135612c8ada28ba..af8185661b6a046f547b2636551077b76c2f60bc 100644 (file)
@@ -525,6 +525,56 @@ public:
     int
     lease6WipeHandler(hooks::CalloutHandle& handle);
 
+    /// @brief lease4-resend-ddns command handler
+    ///
+    /// This command attempts to resend the DDNS updates for the IPv4 lease that
+    /// matches the selection criteria.
+    ///
+    /// It extracts the command name and arguments from the given Callouthandle,
+    /// attempts to process them, and then set's the handle's "response"
+    /// argument accordingly.
+    ///
+    /// A single parameter is supported: ip-address:
+    ///
+    /// Example command to resend DDNS based on existing FDQN and flags
+    /// {
+    ///     "command": "lease4-resend-ddns",
+    ///     "arguments": {
+    ///         "ip-address": "192.0.2.202"
+    ///     }
+    /// }
+    ///
+    /// @param handle Callout context - which is expected to contain the
+    /// delete command JSON text in the "command" argument
+    /// @return result of the operation
+    int
+    lease4ResendDdnsHandler(hooks::CalloutHandle& handle);
+
+    /// @brief lease6-resend-ddns command handler
+    ///
+    /// This command attempts to resend the DDNS updates for the IPv6 lease that
+    /// matches the selection criteria.
+    ///
+    /// It extracts the command name and arguments from the given Callouthandle,
+    /// attempts to process them, and then set's the handle's "response"
+    /// argument accordingly.
+    ///
+    /// A single parameter is supported: ip-address:
+    ///
+    /// Example command to resend DDNS based on existing FDQN and flags
+    /// {
+    ///     "command": "lease6-resend-ddns",
+    ///     "arguments": {
+    ///         "ip-address": "2001:db8:abcd::",
+    ///     }
+    /// }
+    ///
+    /// @param handle Callout context - which is expected to contain the
+    /// delete command JSON text in the "command" argument
+    /// @return result of the operation
+    int
+    lease6ResendDdnsHandler(hooks::CalloutHandle& handle);
+
 private:
     /// Pointer to the actual implementation
     boost::shared_ptr<LeaseCmdsImpl> impl_;
index f2612562132792c1d72839fbdcacf4174f473275..4136deb5cc118e8e75170dd181dd49b2f93278af 100644 (file)
@@ -242,6 +242,28 @@ int lease6_wipe(CalloutHandle& handle) {
     return(lease_cmds.lease6WipeHandler(handle));
 }
 
+/// @brief This is a command callout for 'lease4-resend-ddns' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease4_resend_ddns(CalloutHandle& handle) {
+    LeaseCmds lease_cmds;
+    return(lease_cmds.lease4ResendDdnsHandler(handle));
+}
+
+/// @brief This is a command callout for 'lease6-resend-ddns' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease6_resend_ddns(CalloutHandle& handle) {
+    LeaseCmds lease_cmds;
+    return(lease_cmds.lease6ResendDdnsHandler(handle));
+}
+
 /// @brief This function is called when the library is loaded.
 ///
 /// @param handle library handle
@@ -271,6 +293,8 @@ int load(LibraryHandle& handle) {
     handle.registerCommandCallout("lease6-update", lease6_update);
     handle.registerCommandCallout("lease4-wipe", lease4_wipe);
     handle.registerCommandCallout("lease6-wipe", lease6_wipe);
+    handle.registerCommandCallout("lease4-resend-ddns", lease4_resend_ddns);
+    handle.registerCommandCallout("lease6-resend-ddns", lease6_resend_ddns);
 
     LOG_INFO(lease_cmds_logger, LEASE_CMDS_INIT_OK);
     return (0);
index dad1ccb580332a628052423bb132b12a05ba0fd2..648e5d4f96afc3f5ec4b3797af8393f6affdf1f2 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../../src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes on Fri Feb 08 2019 20:34
+// File created from ../../../../src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes on Fri Mar 13 2020 14:35
 
 #include <cstddef>
 #include <log/message_types.h>
@@ -16,6 +16,10 @@ extern const isc::log::MessageID LEASE_CMDS_DEL6 = "LEASE_CMDS_DEL6";
 extern const isc::log::MessageID LEASE_CMDS_DEL6_FAILED = "LEASE_CMDS_DEL6_FAILED";
 extern const isc::log::MessageID LEASE_CMDS_INIT_FAILED = "LEASE_CMDS_INIT_FAILED";
 extern const isc::log::MessageID LEASE_CMDS_INIT_OK = "LEASE_CMDS_INIT_OK";
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4 = "LEASE_CMDS_RESEND_DDNS4";
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED = "LEASE_CMDS_RESEND_DDNS4_FAILED";
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6 = "LEASE_CMDS_RESEND_DDNS6";
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6_FAILED = "LEASE_CMDS_RESEND_DDNS6_FAILED";
 
 namespace {
 
@@ -32,6 +36,10 @@ const char* values[] = {
     "LEASE_CMDS_DEL6_FAILED", "lease6-del command failed (parameters: %1, reason: %2)",
     "LEASE_CMDS_INIT_FAILED", "loading Lease Commands hooks library failed: %1",
     "LEASE_CMDS_INIT_OK", "loading Lease Commands hooks library successful",
+    "LEASE_CMDS_RESEND_DDNS4", "lease6-resend-ddns command successful: %1",
+    "LEASE_CMDS_RESEND_DDNS4_FAILED", "lease6-resend-ddns command failed: %1",
+    "LEASE_CMDS_RESEND_DDNS6", "lease6-resend-ddns command successful: %1",
+    "LEASE_CMDS_RESEND_DDNS6_FAILED", "lease6-resend-ddns command failed: %1",
     NULL
 };
 
index 7fa71b271388cdb464109d656fb93a7888df8fc5..ed897e0b486ee7fe88f8e6d0de4ac04e80cb00fb 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../../src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes on Fri Feb 08 2019 20:34
+// File created from ../../../../src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes on Fri Mar 13 2020 14:35
 
 #ifndef LEASE_CMDS_MESSAGES_H
 #define LEASE_CMDS_MESSAGES_H
@@ -17,5 +17,9 @@ extern const isc::log::MessageID LEASE_CMDS_DEL6;
 extern const isc::log::MessageID LEASE_CMDS_DEL6_FAILED;
 extern const isc::log::MessageID LEASE_CMDS_INIT_FAILED;
 extern const isc::log::MessageID LEASE_CMDS_INIT_OK;
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4;
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED;
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6;
+extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6_FAILED;
 
 #endif // LEASE_CMDS_MESSAGES_H
index 0684281701298c76951d3945a87803b193ce7af2..bcedf903e73dd2af4ed91fb4232284efb0af5ea8 100644 (file)
@@ -49,3 +49,19 @@ the log message.
 % LEASE_CMDS_INIT_OK loading Lease Commands hooks library successful
 This info message indicates that the Lease Commands hooks library has been
 loaded successfully. Enjoy!
+
+% LEASE_CMDS_RESEND_DDNS4 lease6-resend-ddns command successful: %1
+A request to update DNS for the requested IPv4 lease address has been 
+successfully queued for transmission to kea-dhcp-ddns.  
+
+% LEASE_CMDS_RESEND_DDNS4_FAILED lease6-resend-ddns command failed: %1
+A request to update DNS for the requested IPv4 lease has failed.  The
+reason for the failure is logged.
+
+% LEASE_CMDS_RESEND_DDNS6 lease6-resend-ddns command successful: %1
+A request to update DNS for the requested IPv6 lease address has been 
+successfully queued for transmission to kea-dhcp-ddns.  
+
+% LEASE_CMDS_RESEND_DDNS6_FAILED lease6-resend-ddns command failed: %1
+A request to update DNS for the requested IPv6 lease has failed.  The
+reason for the failure is logged.