]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a Lua FFI interface to get the list of dynamic blocks
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 10 Nov 2023 15:59:41 +0000 (16:59 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 14 Nov 2023 14:43:37 +0000 (15:43 +0100)
pdns/dnsdistdist/dnsdist-lua-ffi-interface.h
pdns/dnsdistdist/dnsdist-lua-ffi.cc

index face00a92055e7324bb0536dad6d8ec88990506c..93d476ccdee68c2671c90491f72c46b0e996f9e1 100644 (file)
@@ -252,3 +252,19 @@ uint16_t dnsdist_ffi_network_message_get_endpoint_id(const dnsdist_ffi_network_m
    - clientIPPort indicates It is also possible to take the IPv4 UDP and TCP ports into account, for CGNAT deployments, by setting the number of bits of the port to consider. For example passing 2 as the last parameter, which only makes sense if the previous parameters are respectively 32 and 128, will split a given IP address into four port ranges: 0-16383, 16384-32767, 32768-49151 and 49152-65535.
 */
 bool dnsdist_ffi_dynamic_blocks_add(const char* address, const char* message, uint8_t action, unsigned int duration, uint8_t clientIPMask, uint8_t clientIPPortMask) __attribute__ ((visibility ("default")));
+
+typedef struct dnsdist_ffi_dynamic_block_entry {
+  char* client;
+  char* reason;
+  uint64_t blockedQueries;
+  uint64_t remainingTime;
+  uint8_t action;
+  bool ebpf;
+  bool warning;
+} dnsdist_ffi_dynamic_block_entry_t;
+
+typedef struct dnsdist_ffi_dynamic_blocks_list_t dnsdist_ffi_dynamic_blocks_list_t;
+
+size_t dnsdist_ffi_dynamic_blocks_get_entries(dnsdist_ffi_dynamic_blocks_list_t** out) __attribute__ ((visibility ("default")));
+const dnsdist_ffi_dynamic_block_entry_t* dnsdist_ffi_dynamic_blocks_list_get(const dnsdist_ffi_dynamic_blocks_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+void dnsdist_ffi_dynamic_blocks_list_free(dnsdist_ffi_dynamic_blocks_list_t*) __attribute__ ((visibility ("default")));
index 0f2a0ddf8792f1bdbffa7c18fb8e0ae493280f51..a9765218f9deb62813d0f69c0d310ae7e06018b8 100644 (file)
@@ -1698,6 +1698,7 @@ uint16_t dnsdist_ffi_network_message_get_endpoint_id(const dnsdist_ffi_network_m
   return 0;
 }
 
+#ifndef DISABLE_DYNBLOCKS
 bool dnsdist_ffi_dynamic_blocks_add(const char* address, const char* message, uint8_t action, unsigned int duration, uint8_t clientIPMask, uint8_t clientIPPortMask)
 {
   try {
@@ -1735,3 +1736,68 @@ bool dnsdist_ffi_dynamic_blocks_add(const char* address, const char* message, ui
   }
   return false;
 }
+
+struct dnsdist_ffi_dynamic_blocks_list_t
+{
+  std::vector<dnsdist_ffi_dynamic_block_entry_t> d_entries;
+};
+
+size_t dnsdist_ffi_dynamic_blocks_get_entries(dnsdist_ffi_dynamic_blocks_list_t** out)
+{
+  if (out == nullptr) {
+    return 0;
+  }
+
+  auto list = std::make_unique<dnsdist_ffi_dynamic_blocks_list_t>();
+
+  struct timespec now;
+  gettime(&now);
+
+  auto fullCopy = g_dynblockNMG.getCopy();
+  for (const auto& entry : fullCopy) {
+    const auto& client = entry.first;
+    const auto& details = entry.second;
+    if (!(now < details.until)) {
+      continue;
+    }
+
+    uint64_t counter = details.blocks;
+    if (g_defaultBPFFilter && details.bpf) {
+      counter += g_defaultBPFFilter->getHits(client.getNetwork());
+    }
+    list->d_entries.push_back({strdup(client.toString().c_str()), strdup(details.reason.c_str()), counter, static_cast<uint64_t>(details.until.tv_sec - now.tv_sec), static_cast<uint8_t>(details.action != DNSAction::Action::None ? details.action : g_dynBlockAction), g_defaultBPFFilter && details.bpf, details.warning});
+  }
+
+  auto count = list->d_entries.size();
+  *out = list.release();
+  return count;
+}
+
+const dnsdist_ffi_dynamic_block_entry_t* dnsdist_ffi_dynamic_blocks_list_get(const dnsdist_ffi_dynamic_blocks_list_t* list, size_t idx)
+{
+  if (list == nullptr) {
+    return nullptr;
+  }
+
+  if (idx >= list->d_entries.size()) {
+    return nullptr;
+  }
+
+  return &list->d_entries.at(idx);
+}
+
+void dnsdist_ffi_dynamic_blocks_list_free(dnsdist_ffi_dynamic_blocks_list_t* list)
+{
+  if (list == nullptr) {
+    return;
+  }
+
+  for (auto& entry : list->d_entries) {
+    free(entry.client);
+    free(entry.reason);
+  }
+
+  delete list;
+}
+
+#endif /* DISABLE_DYNBLOCKS */