]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1548] ddns-tuning core skeleton files added
authorTomek Mrugalski <tomek@isc.org>
Mon, 14 Feb 2022 19:29:21 +0000 (20:29 +0100)
committerThomas Markwalder <tmark@isc.org>
Thu, 21 Apr 2022 14:19:19 +0000 (10:19 -0400)
src/hooks/dhcp/ddns_tuning/Makefile.am [new file with mode: 0644]
src/hooks/dhcp/ddns_tuning/ddns_tuning.cc [new file with mode: 0644]
src/hooks/dhcp/ddns_tuning/ddns_tuning.h [new file with mode: 0644]
src/hooks/dhcp/ddns_tuning/ddns_tuning_callouts.cc [new file with mode: 0644]
src/hooks/dhcp/ddns_tuning/ddns_tuning_log.cc [new file with mode: 0644]
src/hooks/dhcp/ddns_tuning/ddns_tuning_log.h [new file with mode: 0644]
src/hooks/dhcp/ddns_tuning/ddns_tuning_messages.mes [new file with mode: 0644]

diff --git a/src/hooks/dhcp/ddns_tuning/Makefile.am b/src/hooks/dhcp/ddns_tuning/Makefile.am
new file mode 100644 (file)
index 0000000..04f2505
--- /dev/null
@@ -0,0 +1,88 @@
+SUBDIRS = . libloadtests tests
+
+AM_CPPFLAGS  = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CXXFLAGS  = $(KEA_CXXFLAGS)
+
+HOOK_NAME=ddns_tuning
+
+# Ensure that the message file and doxygen file is included in the distribution
+EXTRA_DIST = $(HOOK_NAME)_messages.mes
+EXTRA_DIST += $(HOOK_NAME).dox
+
+CLEANFILES = *.gcno *.gcda
+
+# convenience archive
+
+noinst_LTLIBRARIES = libddns_tuning.la
+
+libddns_tuning_la_SOURCES  = $(HOOK_NAME).cc $(HOOK_NAME).h
+libddns_tuning_la_SOURCES += $(HOOK_NAME)_callouts.cc
+libddns_tuning_la_SOURCES += $(HOOK_NAME)_log.cc $(HOOK_NAME)_log.h
+libddns_tuning_la_SOURCES += $(HOOK_NAME)_messages.cc $(HOOK_NAME)_messages.h
+libddns_tuning_la_SOURCES += version.cc
+
+ddns_tuning_la_CXXFLAGS = $(AM_CXXFLAGS)
+ddns_tuning_la_CPPFLAGS = $(AM_CPPFLAGS)
+
+# install the shared object into $(libdir)/kea/hooks
+lib_hooksdir = $(libdir)/kea/hooks
+lib_hooks_LTLIBRARIES = libdhcp_ddns_tuning.la
+
+libdhcp_ddns_tuning_la_SOURCES  =
+libdhcp_ddns_tuning_la_LDFLAGS  = $(AM_LDFLAGS)
+libdhcp_ddns_tuning_la_LDFLAGS  += -avoid-version -export-dynamic -module
+libdhcp_ddns_tuning_la_LIBADD = lib$(HOOK_NAME).la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/process/libkea-process.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/eval/libkea-eval.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/stats/libkea-stats.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/http/libkea-http.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/database/libkea-database.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la
+libdhcp_ddns_tuning_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+libdhcp_ddns_tuning_la_LIBADD += $(LOG4CPLUS_LIBS)
+libdhcp_ddns_tuning_la_LIBADD += $(CRYPTO_LIBS)
+libdhcp_ddns_tuning_la_LIBADD += $(BOOST_LIBS)
+
+# If we want to get rid of all generated messages files, we need to use
+# make maintainer-clean. The proper way to introduce custom commands for
+# that operation is to define maintainer-clean-local target. However,
+# make maintainer-clean also removes Makefile, so running configure script
+# is required.  To make it easy to rebuild messages without going through
+# reconfigure, a new target messages-clean has been added.
+maintainer-clean-local:
+       rm -f $(HOOK_NAME)_messages.h $(HOOK_NAME)_messages.cc
+
+# To regenerate messages files, one can do:
+#
+# make messages-clean
+# make messages
+#
+# This is needed only when a .mes file is modified.
+messages-clean: maintainer-clean-local
+
+if GENERATE_MESSAGES
+
+# Define rule to build logging source files from message file
+messages: $(HOOK_NAME)_messages.h $(HOOK_NAME)_messages.cc
+       @echo Message files regenerated
+
+$(HOOK_NAME)_messages.h $(HOOK_NAME)_messages.cc: $(HOOK_NAME)_messages.mes
+       $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/hooks/dhcp/$(HOOK_NAME)/$(HOOK_NAME)_messages.mes
+
+else
+
+messages $(HOOK_NAME)_messages.h $(HOOK_NAME)_messages.cc:
+       @echo Messages generation disabled. Configure with --enable-generate-messages to enable it.
+
+endif
diff --git a/src/hooks/dhcp/ddns_tuning/ddns_tuning.cc b/src/hooks/dhcp/ddns_tuning/ddns_tuning.cc
new file mode 100644 (file)
index 0000000..62dd3bb
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <ddns_tuning.h>
+#include <ddns_tuning_log.h>
+#include <util/strutil.h>
+#include <cc/simple_parser.h>
+#include <dhcp/dhcp4.h>
+#include <dhcp/libdhcp++.h>
+#include <eval/eval_context.h>
+
+using namespace isc;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::eval;
+using namespace isc::log;
+using namespace isc::util;
+using namespace std;
+
+namespace isc {
+namespace ddns_tuning {
+
+DdnsTuningImpl::DdnsTuningImpl() {
+}
+
+DdnsTuningImpl::~DdnsTuningImpl() {
+}
+
+void DdnsTuningImpl::configure(isc::data::ConstElementPtr params) {
+    if (!params) {
+        isc_throw(BadValue, "missing parameters");
+    }
+    ConstElementPtr hostname = params->get("hostname-expr");
+    if (!hostname) {
+        isc_throw(BadValue, "hostname-expr parameter missing");
+    }
+    if (hostname->getType() != Element::string) {
+        isc_throw(BadValue, "'hostname-expr' must e a string");
+    }
+
+    /// @todo: Parse expression
+    setText(hostname->str());
+
+}
+
+
+} // end of namespace ddns_tuning
+} // end of namespace isc
diff --git a/src/hooks/dhcp/ddns_tuning/ddns_tuning.h b/src/hooks/dhcp/ddns_tuning/ddns_tuning.h
new file mode 100644 (file)
index 0000000..5fd65d5
--- /dev/null
@@ -0,0 +1,103 @@
+// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef DDNS_TUNING_H
+#define DDNS_TUNING_H
+
+#include <cc/data.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option.h>
+#include <eval/evaluate.h>
+#include <eval/token.h>
+#include <util/strutil.h>
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+
+#include <map>
+#include <string>
+
+namespace isc {
+namespace ddns_tuning {
+
+/// @brief DDNS Tuning implementation.
+///
+/// The implementation can be divided into two parts:
+///  - the configuration parsed and stored by load()
+///  - the response packet processing performed by the process method
+///
+class DdnsTuningImpl {
+public:
+
+    /// @brief Set textual expression.
+    ///
+    /// @param text the textual expression.
+    void setText(const std::string& text) {
+        text_ = text;
+    };
+
+    /// @brief Get textual expression.
+    ///
+    /// @return textual expression.
+    const std::string& getText() const {
+        return (text_);
+    }
+
+    /// @brief Set match expression.
+    ///
+    /// @param expr the match expression.
+    void setExpr(const isc::dhcp::ExpressionPtr expr) {
+        expr_ = expr;
+    }
+
+    /// @brief Get match expression.
+    ///
+    /// @return the match expression.
+    const isc::dhcp::ExpressionPtr& getExpr() const {
+        return (expr_);
+    }
+
+    /// @brief Constructor.
+    DdnsTuningImpl();
+
+    /// @brief Destructor.
+    ~DdnsTuningImpl();
+
+    /// @brief Configure the Ddns Tuning implementation.
+    ///
+    /// @param hostname The JSON element with the expression.
+    /// @throw BadValue and similar exceptions on error.
+    void configure(isc::data::ConstElementPtr hostname);
+
+    /// @brief Process a query / response pair.
+    ///
+    /// @tparam PktType The type of pointers to packets: Pkt4Ptr or Pkt6Ptr.
+    /// @param universe The option universe: Option::V4 or Option::V6.
+    /// @param query The query packet.
+    /// @param response The response packet.
+    template <typename PktType>
+    void process(isc::dhcp::Option::Universe universe,
+                 PktType query, PktType /*response*/) {
+        std::string value = isc::dhcp::evaluateString(*getExpr(), *query);
+        if (value.empty()) {
+            return;
+        }
+    }
+
+private:
+    /// @brief The textual expression.
+    std::string text_;
+
+    /// @brief The match expression.
+    isc::dhcp::ExpressionPtr expr_;
+};
+
+/// @brief The type of shared pointers to DDNS Tuning implementations.
+typedef boost::shared_ptr<DdnsTuningImpl> DdnsTuningImplPtr;
+
+} // end of namespace ddns_tuning
+} // end of namespace isc
+#endif
diff --git a/src/hooks/dhcp/ddns_tuning/ddns_tuning_callouts.cc b/src/hooks/dhcp/ddns_tuning/ddns_tuning_callouts.cc
new file mode 100644 (file)
index 0000000..3d07c08
--- /dev/null
@@ -0,0 +1,151 @@
+// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <ddns_tuning.h>
+#include <ddns_tuning_log.h>
+#include <cc/command_interpreter.h>
+#include <hooks/hooks.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
+
+namespace isc {
+namespace ddns_tuning {
+
+DdnsTuningImplPtr impl;
+
+} // end of namespace ddns_tuning
+} // end of namespace isc
+
+using namespace isc;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::hooks;
+using namespace isc::ddns_tuning;
+
+// Functions accessed by the hooks framework use C linkage to avoid the name
+// mangling that accompanies use of the C++ compiler as well as to avoid
+// issues related to namespaces.
+extern "C" {
+
+/// @brief This callout is called at the "pkt4_send" hook.
+///
+/// It retrieves v4 query and response packets, and then adds, supersedes
+/// or removes option values in the response according to expressions
+/// evaluated on the query.
+///
+/// @param handle CalloutHandle.
+///
+/// @return 0 upon success, non-zero otherwise
+int pkt4_send(CalloutHandle& handle) {
+    CalloutHandle::CalloutNextStep status = handle.getStatus();
+    if (status == CalloutHandle::NEXT_STEP_DROP) {
+        return (0);
+    }
+
+    // Sanity.
+    if (!impl) {
+        return (0);
+    }
+
+    // Get the parameters.
+    Pkt4Ptr query;
+    Pkt4Ptr response;
+    handle.getArgument("query4", query);
+    handle.getArgument("response4", response);
+
+    if (status == CalloutHandle::NEXT_STEP_SKIP) {
+        isc_throw(InvalidOperation, "packet pack already handled");
+    }
+
+    try {
+        impl->process<Pkt4Ptr>(Option::V4, query, response);
+    } catch (const std::exception& ex) {
+        LOG_ERROR(ddns_tuning_logger, DDNS_TUNING_PROCESS_ERROR)
+            .arg(query->getLabel())
+            .arg(ex.what());
+    }
+
+    return (0);
+}
+
+/// @brief This callout is called at the "pkt6_send" hook.
+///
+/// It retrieves v6 query and response packets, and then adds, supersedes
+/// or removes option values in the response according to expressions
+/// evaluated on the query.
+///
+/// @param handle CalloutHandle.
+///
+/// @return 0 upon success, non-zero otherwise
+int pkt6_send(CalloutHandle& handle) {
+    CalloutHandle::CalloutNextStep status = handle.getStatus();
+    if (status == CalloutHandle::NEXT_STEP_DROP) {
+        return (0);
+    }
+
+    // Sanity.
+    if (!impl) {
+        return (0);
+    }
+
+    if (status == CalloutHandle::NEXT_STEP_SKIP) {
+        isc_throw(InvalidOperation, "packet pack already handled");
+    }
+
+    // Get the parameters.
+    Pkt6Ptr query;
+    Pkt6Ptr response;
+    handle.getArgument("query6", query);
+    handle.getArgument("response6", response);
+
+    try {
+        impl->process<Pkt6Ptr>(Option::V6, query, response);
+    } catch (const std::exception& ex) {
+        LOG_ERROR(ddns_tuning_logger, DDNS_TUNING_PROCESS_ERROR)
+            .arg(query->getLabel())
+            .arg(ex.what());
+    }
+
+    return (0);
+}
+
+/// @brief This function is called when the library is loaded.
+///
+/// @param handle library handle
+/// @return 0 when initialization is successful, 1 otherwise
+int load(LibraryHandle& handle) {
+    try {
+        impl.reset(new DdnsTuningImpl());
+        ConstElementPtr json = handle.getParameters();
+        impl->configure(json);
+    } catch (const std::exception& ex) {
+        LOG_ERROR(ddns_tuning_logger, DDNS_TUNING_LOAD_ERROR)
+            .arg(ex.what());
+        return (1);
+    }
+
+    return (0);
+}
+
+/// @brief This function is called when the library is unloaded.
+///
+/// @return always 0.
+int unload() {
+    impl.reset();
+    LOG_INFO(ddns_tuning_logger, DDNS_TUNING_UNLOAD);
+    return (0);
+}
+
+/// @brief This function is called to retrieve the multi-threading compatibility.
+///
+/// @return 1 which means compatible with multi-threading.
+int multi_threading_compatible() {
+    return (1);
+}
+
+} // end extern "C"
diff --git a/src/hooks/dhcp/ddns_tuning/ddns_tuning_log.cc b/src/hooks/dhcp/ddns_tuning/ddns_tuning_log.cc
new file mode 100644 (file)
index 0000000..51531af
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <ddns_tuning_log.h>
+
+namespace isc {
+namespace ddns_tuning {
+
+isc::log::Logger ddns_tuning_logger("ddns-tuning-hooks");
+
+} // namespace ddns_tuning
+} // namespace isc
diff --git a/src/hooks/dhcp/ddns_tuning/ddns_tuning_log.h b/src/hooks/dhcp/ddns_tuning/ddns_tuning_log.h
new file mode 100644 (file)
index 0000000..a1290e4
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef DDNS_TUNING_LOG_H
+#define DDNS_TUNING_LOG_H
+
+#include <log/logger_support.h>
+#include <log/macros.h>
+#include <log/log_dbglevels.h>
+#include <ddns_tuning_messages.h>
+
+namespace isc {
+namespace ddns_tuning {
+
+extern isc::log::Logger ddns_tuning_logger;
+
+} // end of namespace ddns_tuning
+} // end of namespace isc
+#endif
diff --git a/src/hooks/dhcp/ddns_tuning/ddns_tuning_messages.mes b/src/hooks/dhcp/ddns_tuning/ddns_tuning_messages.mes
new file mode 100644 (file)
index 0000000..dbed301
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+
+% DDNS_TUNING_LOAD_ERROR loading Flex Option hooks library failed: %1
+This error message indicates an error during loading the Flex Option
+hooks library. The details of the error are provided as argument of
+the log message.
+
+% DDNS_TUNING_PROCESS_ERROR An error occurred processing query %1: %2
+This error message indicates an error during processing of a query
+by the Flex Option hooks library. The client identification information
+from the query and the details of the error are provided as arguments
+of the log message.
+
+% DDNS_TUNING_UNLOAD Flex Option hooks library has been unloaded
+This info message indicates that the Flex Option hooks library has been
+unloaded.