}
};
-typedef std::function<bool(dnsdist_ffi_stat_node_t*)> dnsdist_ffi_stat_node_visitor_t;
+using dnsdist_ffi_stat_node_visitor_t = std::function<bool(dnsdist_ffi_stat_node_t*)>;
struct dnsdist_ffi_stat_node_t
{
std::optional<std::string>& reason;
};
+using dnsdist_ffi_dynamic_block_inserted_hook = std::function<void(uint8_t type, const char* key, const char* reason, uint8_t action, uint64_t duration, bool warning)>;
+
class DynBlockRulesGroup
{
private:
d_smtVisitorFFI = std::move(visitor);
}
+ void setNewBlockHook(dnsdist_ffi_dynamic_block_inserted_hook& callback)
+ {
+ d_newBlockHook = std::move(callback);
+ }
+
void setMasks(uint8_t v4, uint8_t v6, uint8_t port)
{
d_v4Mask = v4;
SuffixMatchNode d_excludedDomains;
smtVisitor_t d_smtVisitor;
dnsdist_ffi_stat_node_visitor_t d_smtVisitorFFI;
+ dnsdist_ffi_dynamic_block_inserted_hook d_newBlockHook;
uint8_t d_v6Mask{128};
uint8_t d_v4Mask{32};
uint8_t d_portMask{0};
group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor));
}
});
+ luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(dnsdist_ffi_dynamic_block_inserted_hook)>("setNewBlockInsertedHook", [](std::shared_ptr<DynBlockRulesGroup>& group, dnsdist_ffi_dynamic_block_inserted_hook hook) {
+ if (group) {
+ group->setNewBlockHook(hook);
+ }
+ });
luaCtx.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);
}
updated = dnsdist::DynamicBlocks::addOrRefreshBlock(*blocks, now, requestor, rule.d_blockReason, rule.d_blockDuration, rule.d_action, warning, d_beQuiet);
+ if (updated && d_newBlockHook) {
+ try {
+ d_newBlockHook(dnsdist_ffi_dynamic_block_type_nmt, requestor.toString().c_str(), rule.d_blockReason.c_str(), static_cast<uint8_t>(rule.d_action), rule.d_blockDuration, warning);
+ }
+ catch (const std::exception& exp) {
+ warnlog("Error calling the Lua hook after a dynamic block insertion: %s", exp.what());
+ }
+ }
}
void DynBlockRulesGroup::addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const struct timespec& now, const DNSName& name, const DynBlockRule& rule, bool& updated)
}
updated = dnsdist::DynamicBlocks::addOrRefreshBlockSMT(blocks, now, name, rule.d_blockReason, rule.d_blockDuration, rule.d_action, d_beQuiet);
+ if (updated && d_newBlockHook) {
+ try {
+ d_newBlockHook(dnsdist_ffi_dynamic_block_type_smt, name.toString().c_str(), rule.d_blockReason.c_str(), static_cast<uint8_t>(rule.d_action), rule.d_blockDuration, false);
+ }
+ catch (const std::exception& exp) {
+ warnlog("Error calling the Lua hook after a dynamic block insertion: %s", exp.what());
+ }
+ }
}
void DynBlockRulesGroup::processQueryRules(counts_t& counts, const struct timespec& now)
void dnsdist_ffi_state_node_set_reason(dnsdist_ffi_stat_node_t* node, const char* reason, size_t reasonSize) __attribute__ ((visibility ("default")));
+typedef enum {
+ dnsdist_ffi_dynamic_block_type_nmt = 0,
+ dnsdist_ffi_dynamic_block_type_smt = 1,
+} dnsdist_ffi_dynamic_block_type;
:param int action: The action to take when the dynamic block matches, see :ref:`DNSAction <DNSAction>`. (default to the one set with :func:`setDynBlocksAction`)
:param int warningRate: If set to a non-zero value, the rate above which a warning message will be issued and a no-op block inserted
+ .. method:: DynBlockRulesGroup:setNewBlockInsertedHook(hook)
+
+ .. versionadded:: 1.9.0
+
+ Set a Lua function that will be called everytime a new dynamic block is inserted. The function receives:
+
+ * an integer whose value is 0 if the block is Netmask-based one (Client IP or range) and 1 instead (Domain name suffix)
+ * the key (Client IP/range or domain suffix) as a string
+ * the reason of the block as a string
+ * the action of the block as an integer
+ * the duration of the block in seconds
+ * whether this is a warning block (true) or not (false)
+
.. method:: DynBlockRulesGroup:setRCodeRate(rcode, rate, seconds, reason, blockingTime [, action [, warningRate]])
Adds a rate-limiting rule for responses of code ``rcode``, equivalent to: