From: Remi Gacogne Date: Fri, 10 Nov 2023 15:59:41 +0000 (+0100) Subject: dnsdist: Add a Lua FFI interface to get the list of dynamic blocks X-Git-Tag: rec-5.0.0-rc1~31^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=726f1a169f0c04a380ef913f0a7f373bce1347e1;p=thirdparty%2Fpdns.git dnsdist: Add a Lua FFI interface to get the list of dynamic blocks --- diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h b/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h index face00a920..93d476ccde 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h +++ b/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h @@ -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"))); diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index 0f2a0ddf87..a9765218f9 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -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 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(); + + 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(details.until.tv_sec - now.tv_sec), static_cast(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 */