summaryrefslogtreecommitdiffstats
path: root/dnsdist-lua-ffi.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dnsdist-lua-ffi.cc')
-rw-r--r--dnsdist-lua-ffi.cc420
1 files changed, 379 insertions, 41 deletions
diff --git a/dnsdist-lua-ffi.cc b/dnsdist-lua-ffi.cc
index bf46aad..6c08cfc 100644
--- a/dnsdist-lua-ffi.cc
+++ b/dnsdist-lua-ffi.cc
@@ -22,6 +22,7 @@
#include "dnsdist-async.hh"
#include "dnsdist-dnsparser.hh"
+#include "dnsdist-dynblocks.hh"
#include "dnsdist-ecs.hh"
#include "dnsdist-lua-ffi.hh"
#include "dnsdist-mac-address.hh"
@@ -67,6 +68,15 @@ void dnsdist_ffi_dnsquestion_get_localaddr(const dnsdist_ffi_dnsquestion_t* dq,
dnsdist_ffi_comboaddress_to_raw(dq->dq->ids.origDest, addr, addrSize);
}
+bool dnsdist_ffi_dnsquestion_is_remote_v6(const dnsdist_ffi_dnsquestion_t* dnsQuestion)
+{
+ if (dnsQuestion == nullptr || dnsQuestion->dq == nullptr) {
+ return false;
+ }
+
+ return dnsQuestion->dq->ids.origRemote.isIPv6();
+}
+
void dnsdist_ffi_dnsquestion_get_remoteaddr(const dnsdist_ffi_dnsquestion_t* dq, const void** addr, size_t* addrSize)
{
dnsdist_ffi_comboaddress_to_raw(dq->dq->ids.origRemote, addr, addrSize);
@@ -129,7 +139,7 @@ int dnsdist_ffi_dnsquestion_get_rcode(const dnsdist_ffi_dnsquestion_t* dq)
void* dnsdist_ffi_dnsquestion_get_header(const dnsdist_ffi_dnsquestion_t* dq)
{
- return dq->dq->getHeader();
+ return dq->dq->getMutableHeader();
}
uint16_t dnsdist_ffi_dnsquestion_get_len(const dnsdist_ffi_dnsquestion_t* dq)
@@ -458,14 +468,30 @@ void dnsdist_ffi_dnsquestion_set_http_response(dnsdist_ffi_dnsquestion_t* dq, ui
#ifdef HAVE_DNS_OVER_HTTPS
PacketBuffer bodyVect(body, body + bodyLen);
dq->dq->ids.du->setHTTPResponse(statusCode, std::move(bodyVect), contentType);
- dq->dq->getHeader()->qr = true;
+ dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->dq->getMutableData(), [](dnsheader& header) {
+ header.qr = true;
+ return true;
+ });
#endif
}
+void dnsdist_ffi_dnsquestion_set_extended_dns_error(dnsdist_ffi_dnsquestion_t* dnsQuestion, uint16_t infoCode, const char* extraText, size_t extraTextSize)
+{
+ EDNSExtendedError ede;
+ ede.infoCode = infoCode;
+ if (extraText != nullptr && extraTextSize > 0) {
+ ede.extraText = std::string(extraText, extraTextSize);
+ }
+ dnsQuestion->dq->ids.d_extendedError = std::make_unique<EDNSExtendedError>(ede);
+}
+
void dnsdist_ffi_dnsquestion_set_rcode(dnsdist_ffi_dnsquestion_t* dq, int rcode)
{
- dq->dq->getHeader()->rcode = rcode;
- dq->dq->getHeader()->qr = true;
+ dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->dq->getMutableData(), [rcode](dnsheader& header) {
+ header.rcode = rcode;
+ header.qr = true;
+ return true;
+ });
}
void dnsdist_ffi_dnsquestion_set_len(dnsdist_ffi_dnsquestion_t* dq, uint16_t len)
@@ -571,8 +597,8 @@ void dnsdist_ffi_dnsquestion_send_trap(dnsdist_ffi_dnsquestion_t* dq, const char
void dnsdist_ffi_dnsquestion_spoof_packet(dnsdist_ffi_dnsquestion_t* dq, const char* raw, size_t len)
{
std::string result;
- SpoofAction sa(raw, len);
- sa(dq->dq, &result);
+ SpoofAction tempSpoofAction(raw, len);
+ tempSpoofAction(dq->dq, &result);
}
void dnsdist_ffi_dnsquestion_spoof_raw(dnsdist_ffi_dnsquestion_t* dq, const dnsdist_ffi_raw_value_t* values, size_t valuesCount)
@@ -585,8 +611,8 @@ void dnsdist_ffi_dnsquestion_spoof_raw(dnsdist_ffi_dnsquestion_t* dq, const dnsd
}
std::string result;
- SpoofAction sa(data);
- sa(dq->dq, &result);
+ SpoofAction tempSpoofAction(data, std::nullopt);
+ tempSpoofAction(dq->dq, &result);
}
void dnsdist_ffi_dnsquestion_spoof_addrs(dnsdist_ffi_dnsquestion_t* dq, const dnsdist_ffi_raw_value_t* values, size_t valuesCount)
@@ -614,8 +640,8 @@ void dnsdist_ffi_dnsquestion_spoof_addrs(dnsdist_ffi_dnsquestion_t* dq, const dn
}
std::string result;
- SpoofAction sa(data);
- sa(dq->dq, &result);
+ SpoofAction tempSpoofAction(data);
+ tempSpoofAction(dq->dq, &result);
}
void dnsdist_ffi_dnsquestion_set_max_returned_ttl(dnsdist_ffi_dnsquestion_t* dq, uint32_t max)
@@ -749,7 +775,7 @@ bool dnsdist_ffi_dnsresponse_rebase(dnsdist_ffi_dnsresponse_t* dr, const char* i
}
// set qname to new one
- dr->dr->ids.qname = parsed;
+ dr->dr->ids.qname = std::move(parsed);
dr->dr->ids.skipCache = true;
}
catch (const std::exception& e) {
@@ -929,7 +955,8 @@ bool dnsdist_ffi_drop_from_async(uint16_t asyncID, uint16_t queryID)
struct timeval now;
gettimeofday(&now, nullptr);
- sender->notifyIOError(std::move(query->query.d_idstate), now);
+ TCPResponse tresponse(std::move(query->query));
+ sender->notifyIOError(now, std::move(tresponse));
return true;
}
@@ -949,11 +976,15 @@ bool dnsdist_ffi_set_answer_from_async(uint16_t asyncID, uint16_t queryID, const
return false;
}
- auto oldId = reinterpret_cast<const dnsheader*>(query->query.d_buffer.data())->id;
+ dnsheader_aligned alignedHeader(query->query.d_buffer.data());
+ auto oldID = alignedHeader->id;
query->query.d_buffer.clear();
query->query.d_buffer.insert(query->query.d_buffer.begin(), raw, raw + rawSize);
- reinterpret_cast<dnsheader*>(query->query.d_buffer.data())->id = oldId;
+ dnsdist::PacketMangling::editDNSHeaderFromPacket(query->query.d_buffer, [oldID](dnsheader& header) {
+ header.id = oldID;
+ return true;
+ });
query->query.d_idstate.skipCache = true;
return dnsdist::queueQueryResumptionEvent(std::move(query));
@@ -978,7 +1009,7 @@ const char* getLuaFFIWrappers()
void setupLuaLoadBalancingContext(LuaContext& luaCtx)
{
- setupLuaBindings(luaCtx, true);
+ setupLuaBindings(luaCtx, true, false);
setupLuaBindingsDNSQuestion(luaCtx);
setupLuaBindingsKVS(luaCtx, true);
setupLuaVars(luaCtx);
@@ -1202,7 +1233,11 @@ struct dnsdist_ffi_ring_entry_list_t
std::string qname;
std::string requestor;
std::string macAddr;
- size_t size;
+ std::string ds;
+ dnsheader dh;
+ double age;
+ unsigned int latency;
+ uint16_t size;
uint16_t qtype;
dnsdist::Protocol protocol;
bool isResponse;
@@ -1220,6 +1255,15 @@ bool dnsdist_ffi_ring_entry_is_response(const dnsdist_ffi_ring_entry_list_t* lis
return list->d_entries.at(idx).isResponse;
}
+double dnsdist_ffi_ring_entry_get_age(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+
+ return list->d_entries.at(idx).age;
+}
+
const char* dnsdist_ffi_ring_entry_get_name(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
{
if (list == nullptr || idx >= list->d_entries.size()) {
@@ -1236,7 +1280,6 @@ uint16_t dnsdist_ffi_ring_entry_get_type(const dnsdist_ffi_ring_entry_list_t* li
}
return list->d_entries.at(idx).qtype;
-
}
const char* dnsdist_ffi_ring_entry_get_requestor(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
@@ -1248,6 +1291,15 @@ const char* dnsdist_ffi_ring_entry_get_requestor(const dnsdist_ffi_ring_entry_li
return list->d_entries.at(idx).requestor.c_str();
}
+const char* dnsdist_ffi_ring_entry_get_backend(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return nullptr;
+ }
+
+ return list->d_entries.at(idx).ds.c_str();
+}
+
uint8_t dnsdist_ffi_ring_entry_get_protocol(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
{
if (list == nullptr || idx >= list->d_entries.size()) {
@@ -1264,7 +1316,87 @@ uint16_t dnsdist_ffi_ring_entry_get_size(const dnsdist_ffi_ring_entry_list_t* li
}
return list->d_entries.at(idx).size;
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_latency(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+
+ return list->d_entries.at(idx).latency;
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_id(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+ return ntohs(list->d_entries.at(idx).dh.id);
+}
+
+uint8_t dnsdist_ffi_ring_entry_get_rcode(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+
+ return list->d_entries.at(idx).dh.rcode;
+}
+
+bool dnsdist_ffi_ring_entry_get_aa(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return false;
+ }
+
+ return list->d_entries.at(idx).dh.aa == 1;
+}
+
+bool dnsdist_ffi_ring_entry_get_rd(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return false;
+ }
+
+ return list->d_entries.at(idx).dh.rd == 1;
+}
+
+bool dnsdist_ffi_ring_entry_get_tc(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return false;
+ }
+
+ return list->d_entries.at(idx).dh.tc == 1;
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_ancount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+
+ return ntohs(list->d_entries.at(idx).dh.ancount);
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_nscount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+
+ return ntohs(list->d_entries.at(idx).dh.nscount);
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_arcount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+ if (list == nullptr || idx >= list->d_entries.size()) {
+ return 0;
+ }
+
+ return ntohs(list->d_entries.at(idx).dh.arcount);
}
bool dnsdist_ffi_ring_entry_has_mac_address(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
@@ -1283,7 +1415,6 @@ const char* dnsdist_ffi_ring_entry_get_mac_address(const dnsdist_ffi_ring_entry_
}
return list->d_entries.at(idx).macAddr.data();
-
}
void dnsdist_ffi_ring_entry_list_free(dnsdist_ffi_ring_entry_list_t* list)
@@ -1291,22 +1422,23 @@ void dnsdist_ffi_ring_entry_list_free(dnsdist_ffi_ring_entry_list_t* list)
delete list;
}
-template<typename T> static void addRingEntryToList(std::unique_ptr<dnsdist_ffi_ring_entry_list_t>& list, const T& entry)
+template<typename T> static void addRingEntryToList(std::unique_ptr<dnsdist_ffi_ring_entry_list_t>& list, const struct timespec& now, const T& entry)
{
+ auto age = DiffTime(entry.when, now);
+
constexpr bool response = std::is_same_v<T, Rings::Response>;
-#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
if constexpr (!response) {
- dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toString(), entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string(), entry.size, entry.qtype, entry.protocol, response};
+#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
+ dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string(), std::string(), entry.dh, age, 0, entry.size, entry.qtype, entry.protocol, response};
+#else
+ dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), std::string(), entry.dh, age, 0, entry.size, entry.qtype, entry.protocol, response};
+#endif
list->d_entries.push_back(std::move(tmp));
}
else {
- dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toString(), std::string(), entry.size, entry.qtype, entry.protocol, response};
+ dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), entry.ds.toStringWithPort(), entry.dh, age, entry.usec, entry.size, entry.qtype, entry.protocol, response};
list->d_entries.push_back(std::move(tmp));
}
-#else
- dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toString(), std::string(), entry.size, entry.qtype, entry.protocol, response};
- list->d_entries.push_back(std::move(tmp));
-#endif
}
size_t dnsdist_ffi_ring_get_entries(dnsdist_ffi_ring_entry_list_t** out)
@@ -1315,18 +1447,22 @@ size_t dnsdist_ffi_ring_get_entries(dnsdist_ffi_ring_entry_list_t** out)
return 0;
}
auto list = std::make_unique<dnsdist_ffi_ring_entry_list_t>();
+ struct timespec now
+ {
+ };
+ gettime(&now);
for (const auto& shard : g_rings.d_shards) {
{
auto ql = shard->queryRing.lock();
for (const auto& entry : *ql) {
- addRingEntryToList(list, entry);
+ addRingEntryToList(list, now, entry);
}
}
{
auto rl = shard->respRing.lock();
for (const auto& entry : *rl) {
- addRingEntryToList(list, entry);
+ addRingEntryToList(list, now, entry);
}
}
}
@@ -1357,6 +1493,10 @@ size_t dnsdist_ffi_ring_get_entries_by_addr(const char* addr, dnsdist_ffi_ring_e
}
auto list = std::make_unique<dnsdist_ffi_ring_entry_list_t>();
+ struct timespec now
+ {
+ };
+ gettime(&now);
auto compare = ComboAddress::addressOnlyEqual();
for (const auto& shard : g_rings.d_shards) {
@@ -1367,7 +1507,7 @@ size_t dnsdist_ffi_ring_get_entries_by_addr(const char* addr, dnsdist_ffi_ring_e
continue;
}
- addRingEntryToList(list, entry);
+ addRingEntryToList(list, now, entry);
}
}
{
@@ -1377,7 +1517,7 @@ size_t dnsdist_ffi_ring_get_entries_by_addr(const char* addr, dnsdist_ffi_ring_e
continue;
}
- addRingEntryToList(list, entry);
+ addRingEntryToList(list, now, entry);
}
}
}
@@ -1399,6 +1539,10 @@ size_t dnsdist_ffi_ring_get_entries_by_mac(const char* addr, dnsdist_ffi_ring_en
return 0;
#else
auto list = std::make_unique<dnsdist_ffi_ring_entry_list_t>();
+ struct timespec now
+ {
+ };
+ gettime(&now);
for (const auto& shard : g_rings.d_shards) {
auto ql = shard->queryRing.lock();
@@ -1407,7 +1551,7 @@ size_t dnsdist_ffi_ring_get_entries_by_mac(const char* addr, dnsdist_ffi_ring_en
continue;
}
- addRingEntryToList(list, entry);
+ addRingEntryToList(list, now, entry);
}
}
@@ -1607,17 +1751,14 @@ bool dnsdist_ffi_metric_declare(const char* name, size_t nameLen, const char* ty
if (name == nullptr || nameLen == 0 || type == nullptr || description == nullptr) {
return false;
}
- auto result = dnsdist::metrics::declareCustomMetric(name, type, description, customName ? std::optional<std::string>(customName) : std::nullopt);
- if (result) {
- return false;
- }
- return true;
+ auto result = dnsdist::metrics::declareCustomMetric(name, type, description, customName != nullptr ? std::optional<std::string>(customName) : std::nullopt);
+ return !result;
}
void dnsdist_ffi_metric_inc(const char* metricName, size_t metricNameLen)
{
auto result = dnsdist::metrics::incrementCustomCounter(std::string_view(metricName, metricNameLen), 1U);
- if (const auto* errorStr = std::get_if<dnsdist::metrics::Error>(&result)) {
+ if (std::get_if<dnsdist::metrics::Error>(&result) != nullptr) {
return;
}
}
@@ -1625,7 +1766,7 @@ void dnsdist_ffi_metric_inc(const char* metricName, size_t metricNameLen)
void dnsdist_ffi_metric_inc_by(const char* metricName, size_t metricNameLen, uint64_t value)
{
auto result = dnsdist::metrics::incrementCustomCounter(std::string_view(metricName, metricNameLen), value);
- if (const auto* errorStr = std::get_if<dnsdist::metrics::Error>(&result)) {
+ if (std::get_if<dnsdist::metrics::Error>(&result) != nullptr) {
return;
}
}
@@ -1633,7 +1774,7 @@ void dnsdist_ffi_metric_inc_by(const char* metricName, size_t metricNameLen, uin
void dnsdist_ffi_metric_dec(const char* metricName, size_t metricNameLen)
{
auto result = dnsdist::metrics::decrementCustomCounter(std::string_view(metricName, metricNameLen), 1U);
- if (const auto* errorStr = std::get_if<dnsdist::metrics::Error>(&result)) {
+ if (std::get_if<dnsdist::metrics::Error>(&result) != nullptr) {
return;
}
}
@@ -1641,7 +1782,7 @@ void dnsdist_ffi_metric_dec(const char* metricName, size_t metricNameLen)
void dnsdist_ffi_metric_set(const char* metricName, size_t metricNameLen, double value)
{
auto result = dnsdist::metrics::setCustomGauge(std::string_view(metricName, metricNameLen), value);
- if (const auto* errorStr = std::get_if<dnsdist::metrics::Error>(&result)) {
+ if (std::get_if<dnsdist::metrics::Error>(&result) != nullptr) {
return;
}
}
@@ -1649,7 +1790,7 @@ void dnsdist_ffi_metric_set(const char* metricName, size_t metricNameLen, double
double dnsdist_ffi_metric_get(const char* metricName, size_t metricNameLen, bool isCounter)
{
auto result = dnsdist::metrics::getCustomMetric(std::string_view(metricName, metricNameLen));
- if (const auto* errorStr = std::get_if<dnsdist::metrics::Error>(&result)) {
+ if (std::get_if<dnsdist::metrics::Error>(&result) != nullptr) {
return 0.;
}
return std::get<double>(result);
@@ -1678,3 +1819,200 @@ 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 {
+ ComboAddress clientIPCA;
+ try {
+ clientIPCA = ComboAddress(address);
+ }
+ catch (const std::exception& exp) {
+ errlog("dnsdist_ffi_dynamic_blocks_add: Unable to parse '%s': %s", address, exp.what());
+ return false;
+ }
+ catch (const PDNSException& exp) {
+ errlog("dnsdist_ffi_dynamic_blocks_add: Unable to parse '%s': %s", address, exp.reason);
+ return false;
+ }
+
+ AddressAndPortRange target(clientIPCA, clientIPMask, clientIPPortMask);
+
+ struct timespec now
+ {
+ };
+ gettime(&now);
+ auto slow = g_dynblockNMG.getCopy();
+ if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, message, duration, static_cast<DNSAction::Action>(action), false, false)) {
+ g_dynblockNMG.setState(slow);
+ return true;
+ }
+ }
+ catch (const std::exception& exp) {
+ errlog("Exception in dnsdist_ffi_dynamic_blocks_add: %s", exp.what());
+ }
+ catch (const PDNSException& exp) {
+ errlog("Exception in dnsdist_ffi_dynamic_blocks_add: %s", exp.reason);
+ }
+ catch (...) {
+ errlog("Exception in dnsdist_ffi_dynamic_blocks_add");
+ }
+ return false;
+}
+
+bool dnsdist_ffi_dynamic_blocks_smt_add(const char* suffix, const char* message, uint8_t action, unsigned int duration)
+{
+ try {
+ DNSName domain;
+ try {
+ domain = DNSName(suffix);
+ domain.makeUsLowerCase();
+ }
+ catch (const std::exception& exp) {
+ errlog("dnsdist_ffi_dynamic_blocks_smt_add: Unable to parse '%s': %s", suffix, exp.what());
+ return false;
+ }
+ catch (const PDNSException& exp) {
+ errlog("dnsdist_ffi_dynamic_blocks_smt_add: Unable to parse '%s': %s", suffix, exp.reason);
+ return false;
+ }
+
+ struct timespec now
+ {
+ };
+ gettime(&now);
+ auto slow = g_dynblockSMT.getCopy();
+ if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, domain, message, duration, static_cast<DNSAction::Action>(action), false)) {
+ g_dynblockSMT.setState(slow);
+ return true;
+ }
+ }
+ catch (const std::exception& exp) {
+ errlog("Exception in dnsdist_ffi_dynamic_blocks_smt_add: %s", exp.what());
+ }
+ catch (const PDNSException& exp) {
+ errlog("Exception in dnsdist_ffi_dynamic_blocks_smt_add: %s", exp.reason);
+ }
+ catch (...) {
+ errlog("Exception in dnsdist_ffi_dynamic_blocks_smt_add");
+ }
+ 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;
+}
+
+size_t dnsdist_ffi_dynamic_blocks_smt_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_dynblockSMT.getCopy();
+ fullCopy.visit([&now, &list](const SuffixMatchTree<DynBlock>& node) {
+ if (!(now < node.d_value.until)) {
+ return;
+ }
+ auto entry = node.d_value;
+ string key("empty");
+ if (!entry.domain.empty()) {
+ key = entry.domain.toString();
+ }
+ if (entry.action == DNSAction::Action::None) {
+ entry.action = g_dynBlockAction;
+ }
+ list->d_entries.push_back({strdup(key.c_str()), strdup(entry.reason.c_str()), entry.blocks, static_cast<uint64_t>(entry.until.tv_sec - now.tv_sec), static_cast<uint8_t>(entry.action), entry.bpf, entry.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) {
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc): this is a C API, RAII is not an option
+ free(entry.key);
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc): this is a C API, RAII is not an option
+ free(entry.reason);
+ }
+
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): this is a C API, RAII is not an option
+ delete list;
+}
+
+#endif /* DISABLE_DYNBLOCKS */
+
+uint32_t dnsdist_ffi_hash(uint32_t seed, const unsigned char* data, size_t dataSize, bool caseInsensitive)
+{
+ if (data == nullptr || dataSize == 0) {
+ return seed;
+ }
+
+ if (caseInsensitive) {
+ return burtleCI(data, dataSize, seed);
+ }
+
+ return burtle(data, dataSize, seed);
+}