]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add a SMT FFI interface to dynBlockRulesGroup
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 7 Jan 2019 16:14:02 +0000 (17:14 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 7 Jan 2019 16:14:02 +0000 (17:14 +0100)
pdns/dnsdist-dynblocks.hh
pdns/dnsdist-lua-inspection.cc
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/configure.ac
pdns/dnsdistdist/dnsdist-lua-inspection-ffi.cc [new file with mode: 0644]
pdns/dnsdistdist/dnsdist-lua-inspection-ffi.hh [new file with mode: 0644]

index a66899c1bc90fc53da92fcd4ea9f9f5c5bcca39d..5d9923fb07efafbd5b188d6fd767b53ce6b4a8ce 100644 (file)
 #include "dnsdist-rings.hh"
 #include "statnode.hh"
 
+#include "dnsdist-lua-inspection-ffi.hh"
+
+// dnsdist_ffi_stat_node_t is a lightuserdata
+template<>
+struct LuaContext::Pusher<dnsdist_ffi_stat_node_t*> {
+    static const int minSize = 1;
+    static const int maxSize = 1;
+
+    static PushedObject push(lua_State* state, dnsdist_ffi_stat_node_t* ptr) noexcept {
+        lua_pushlightuserdata(state, ptr);
+        return PushedObject{state, 1};
+    }
+};
+
+typedef std::function<bool(dnsdist_ffi_stat_node_t*)> dnsdist_ffi_stat_node_visitor_t;
+
+struct dnsdist_ffi_stat_node_t
+{
+  dnsdist_ffi_stat_node_t(const StatNode& node_, const StatNode::Stat& self_, const StatNode::Stat& children_): node(node_), self(self_), children(children_)
+  {
+  }
+
+  const StatNode& node;
+  const StatNode::Stat& self;
+  const StatNode::Stat& children;
+};
+
 class DynBlockRulesGroup
 {
 private:
@@ -160,6 +187,12 @@ public:
     d_smtVisitor = visitor;
   }
 
+  void setSuffixMatchRuleFFI(unsigned int seconds, std::string reason, unsigned int blockDuration, DNSAction::Action action, dnsdist_ffi_stat_node_visitor_t visitor)
+  {
+    d_suffixMatchRule = DynBlockRule(reason, blockDuration, 0, 0, seconds, action);
+    d_smtVisitorFFI = visitor;
+  }
+
   void apply()
   {
     struct timespec now;
@@ -256,7 +289,16 @@ public:
       StatNode::Stat node;
       std::unordered_set<DNSName> namesToBlock;
       statNodeRoot.visit([this,&namesToBlock](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) {
-                           bool block = d_smtVisitor(*node_, self, children);
+                           bool block = false;
+
+                           if (d_smtVisitorFFI) {
+                             dnsdist_ffi_stat_node_t tmp(*node_, self, children);
+                             block = d_smtVisitorFFI(&tmp);
+                           }
+                           else {
+                             block = d_smtVisitor(*node_, self, children);
+                           }
+
                            if (block) {
                              namesToBlock.insert(DNSName(node_->fullname));
                            }
@@ -548,5 +590,6 @@ private:
   NetmaskGroup d_excludedSubnets;
   SuffixMatchNode d_excludedDomains;
   smtVisitor_t d_smtVisitor;
+  dnsdist_ffi_stat_node_visitor_t d_smtVisitorFFI;
   bool d_beQuiet{false};
 };
index dda84759c363bc59de6d77accb7fa4efa6bdc9fb..554afa0d6c160951672d24967a0b9eaa5633ca97 100644 (file)
@@ -665,6 +665,11 @@ void setupLuaInspection()
         group->setSuffixMatchRule(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, visitor);
       }
     });
+  g_lua.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(unsigned int, const std::string&, unsigned int, boost::optional<DNSAction::Action>, dnsdist_ffi_stat_node_visitor_t)>("setSuffixMatchRuleFFI", [](std::shared_ptr<DynBlockRulesGroup>& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional<DNSAction::Action> action, dnsdist_ffi_stat_node_visitor_t visitor) {
+      if (group) {
+        group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, visitor);
+      }
+    });
   g_lua.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional<DNSAction::Action>, boost::optional<unsigned int>)>("setRCodeRate", [](std::shared_ptr<DynBlockRulesGroup>& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional<DNSAction::Action> action, boost::optional<unsigned int> warningRate) {
       if (group) {
         group->setRCodeRate(rcode, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None);
index 6625d5b93140e30db801a996d5c3edd0519c5984..7dc18175a2d706bcffe1caa52d8f84926e57a79a 100644 (file)
@@ -102,6 +102,7 @@ dnsdist_SOURCES = \
        dnsdist-lua-bindings.cc \
        dnsdist-lua-bindings-dnsquestion.cc \
        dnsdist-lua-inspection.cc \
+       dnsdist-lua-inspection-ffi.cc dnsdist-lua-inspection-ffi.hh \
        dnsdist-lua-rules.cc \
        dnsdist-lua-vars.cc \
        dnsdist-protobuf.cc dnsdist-protobuf.hh \
index a1b41989cff632799882b3f48f5289a6f9e5fa16..158ba4e998bf961238929298cdce67ac784c04c3 100644 (file)
@@ -48,6 +48,11 @@ AC_SUBST([YAHTTP_CFLAGS], ['-I$(top_srcdir)/ext/yahttp'])
 AC_SUBST([YAHTTP_LIBS], ['$(top_builddir)/ext/yahttp/yahttp/libyahttp.la'])
 
 PDNS_WITH_LUA([mandatory])
+AS_IF([test "x$LUAPC" = "xluajit"], [
+  # export all symbols to be able to use the Lua FFI interface
+  AC_MSG_NOTICE([Adding -rdynamic to export all symbols for the Lua FFI interface])
+  LDFLAGS="$LDFLAGS -rdynamic"
+])
 PDNS_CHECK_LUA_HPP
 
 DNSDIST_ENABLE_DNS_OVER_TLS
diff --git a/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.cc
new file mode 100644 (file)
index 0000000..d05882a
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dnsdist.hh"
+#include "dnsdist-dynblocks.hh"
+
+uint64_t dnsdist_ffi_stat_node_get_queries_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->self.queries;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_noerrors_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->self.noerrors;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_nxdomains_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->self.nxdomains;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_servfails_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->self.servfails;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_drops_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->self.drops;
+}
+
+unsigned int dnsdist_ffi_stat_node_get_labels_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->node.labelsCount;
+}
+
+void dnsdist_ffi_stat_node_get_full_name_raw(const dnsdist_ffi_stat_node_t* node, const char** name, size_t* nameSize)
+{
+  const auto& storage = node->node.fullname;
+  *name = storage.c_str();
+  *nameSize = storage.size();
+}
+
+unsigned int dnsdist_ffi_stat_node_get_children_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->node.children.size();
+}
+
+uint64_t dnsdist_ffi_stat_node_get_children_queries_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->children.queries;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_children_noerrors_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->children.noerrors;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_children_nxdomains_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->children.nxdomains;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_children_servfails_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->children.servfails;
+}
+
+uint64_t dnsdist_ffi_stat_node_get_children_drops_count(const dnsdist_ffi_stat_node_t* node)
+{
+  return node->children.drops;
+}
diff --git a/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.hh b/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.hh
new file mode 100644 (file)
index 0000000..c4329a2
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern "C" {
+  typedef struct dnsdist_ffi_stat_node_t dnsdist_ffi_stat_node_t;
+
+  uint64_t dnsdist_ffi_stat_node_get_queries_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_noerrors_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_nxdomains_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_servfails_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_drops_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  unsigned int dnsdist_ffi_stat_node_get_labels_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  void dnsdist_ffi_stat_node_get_full_name_raw(const dnsdist_ffi_stat_node_t* node, const char** name, size_t* nameSize) __attribute__ ((visibility ("default")));
+
+  unsigned int dnsdist_ffi_stat_node_get_children_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+
+  uint64_t dnsdist_ffi_stat_node_get_children_queries_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_children_noerrors_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_children_nxdomains_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_children_servfails_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+  uint64_t dnsdist_ffi_stat_node_get_children_drops_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+}