namespace dnsdist::DynamicBlocks
{
-bool addOrRefreshBlock(NetmaskTree<DynBlock, AddressAndPortRange>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const std::string& reason, unsigned int duration, DNSAction::Action action, bool warning, bool beQuiet, std::shared_ptr<DynBlock::TagSettings> tagSettings)
+bool addOrRefreshBlock(NetmaskTree<DynBlock, AddressAndPortRange>& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet)
{
unsigned int count = 0;
bool expired = false;
bool wasWarning = false;
bool bpf = false;
- struct timespec until = now;
- until.tv_sec += duration;
-
- DynBlock dblock{reason, until, DNSName(), warning ? DNSAction::Action::NoOp : action};
- dblock.warning = warning;
const auto& got = blocks.lookup(requestor);
if (got != nullptr) {
bpf = got->second.bpf;
- if (warning && !got->second.warning) {
+ if (dblock.warning && !got->second.warning) {
/* we have an existing entry which is not a warning,
don't override it */
return false;
}
- if (!warning && got->second.warning) {
+ if (!dblock.warning && got->second.warning) {
wasWarning = true;
}
else {
- if (until < got->second.until) {
+ if (dblock.until < got->second.until) {
// had a longer policy
return false;
}
}
dblock.blocks = count;
- if (action == DNSAction::Action::SetTag) {
- dblock.tagSettings = std::move(tagSettings);
- }
if (got == nullptr || expired || wasWarning) {
const auto actualAction = getActualAction(dblock);
}
if (!beQuiet) {
- warnlog("Inserting %s%sdynamic block for %s for %d seconds: %s", warning ? "(warning) " : "", bpf ? "eBPF " : "", requestor.toString(), duration, reason);
+ warnlog("Inserting %s%sdynamic block for %s for %d seconds: %s", dblock.warning ? "(warning) " : "", bpf ? "eBPF " : "", requestor.toString(), dblock.until.tv_sec - now.tv_sec, dblock.reason);
}
}
return true;
}
-bool addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const struct timespec& now, const DNSName& name, const std::string& reason, unsigned int duration, DNSAction::Action action, bool beQuiet, std::shared_ptr<DynBlock::TagSettings> tagSettings)
+bool addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet)
{
- struct timespec until = now;
- until.tv_sec += duration;
unsigned int count = 0;
- DynBlock dblock{reason, until, name.makeLowerCase(), action};
/* be careful, if you try to insert a longer suffix
lookup() might return a shorter one if it is
already in the tree as a final node */
- const DynBlock* got = blocks.lookup(name);
- if (got != nullptr && got->domain != name) {
+ const DynBlock* got = blocks.lookup(dblock.domain);
+ if (got != nullptr && got->domain != dblock.domain) {
got = nullptr;
}
bool expired = false;
if (got != nullptr) {
- if (until < got->until) {
+ if (dblock.until < got->until) {
// had a longer policy
return false;
}
}
dblock.blocks = count;
- if (action == DNSAction::Action::SetTag) {
- dblock.tagSettings = std::move(tagSettings);
- }
if (!beQuiet && (got == nullptr || expired)) {
- warnlog("Inserting dynamic block for %s for %d seconds: %s", name, duration, reason);
+ warnlog("Inserting dynamic block for %s for %d seconds: %s", dblock.domain, dblock.until.tv_sec - now.tv_sec, dblock.reason);
}
- blocks.add(name, std::move(dblock));
+ blocks.add(dblock.domain, std::move(dblock));
return true;
}
}
return;
}
+ timespec until{now};
+ until.tv_sec += rule.d_blockDuration;
+ DynBlock dblock{rule.d_blockReason, until, DNSName(), warning ? DNSAction::Action::NoOp : rule.d_action};
+ dblock.warning = warning;
+ if (!warning && rule.d_action == DNSAction::Action::SetTag) {
+ dblock.tagSettings = rule.d_tagSettings;
+ }
if (!blocks) {
blocks = g_dynblockNMG.getCopy();
}
- updated = dnsdist::DynamicBlocks::addOrRefreshBlock(*blocks, now, requestor, rule.d_blockReason, rule.d_blockDuration, rule.d_action, warning, d_beQuiet, rule.d_tagSettings);
+ updated = dnsdist::DynamicBlocks::addOrRefreshBlock(*blocks, now, requestor, std::move(dblock), 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);
return;
}
- updated = dnsdist::DynamicBlocks::addOrRefreshBlockSMT(blocks, now, name, rule.d_blockReason, rule.d_blockDuration, rule.d_action, d_beQuiet, rule.d_tagSettings);
+ timespec until{now};
+ until.tv_sec += rule.d_blockDuration;
+ DynBlock dblock{rule.d_blockReason, until, name.makeLowerCase(), rule.d_action};
+ if (rule.d_action == DNSAction::Action::SetTag) {
+ dblock.tagSettings = rule.d_tagSettings;
+ }
+ updated = dnsdist::DynamicBlocks::addOrRefreshBlockSMT(blocks, now, std::move(dblock), 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);
namespace dnsdist::DynamicBlocks
{
-bool addOrRefreshBlock(NetmaskTree<DynBlock, AddressAndPortRange>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const std::string& reason, unsigned int duration, DNSAction::Action action, bool warning, bool beQuiet, std::shared_ptr<DynBlock::TagSettings> tagSettings);
-bool addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const struct timespec& now, const DNSName& name, const std::string& reason, unsigned int duration, DNSAction::Action action, bool beQuiet, std::shared_ptr<DynBlock::TagSettings> tagSettings);
+bool addOrRefreshBlock(NetmaskTree<DynBlock, AddressAndPortRange>& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet);
+bool addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet);
}
#endif /* DISABLE_DYNBLOCKS */
timespec now{};
gettime(&now);
+ timespec until{now};
+ until.tv_sec += duration;
+ DynBlock dblock{message, until, DNSName(), static_cast<DNSAction::Action>(action)};
auto slow = g_dynblockNMG.getCopy();
#warning FIXME: need to handle tags
- if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, message, duration, static_cast<DNSAction::Action>(action), false, false, nullptr)) {
+ if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, std::move(dblock), false)) {
g_dynblockNMG.setState(slow);
return true;
}
timespec now{};
gettime(&now);
+ timespec until{now};
+ until.tv_sec += duration;
+ DynBlock dblock{message, until, domain, static_cast<DNSAction::Action>(action)};
auto slow = g_dynblockSMT.getCopy();
#warning FIXME: need to handle tags
- if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, domain, message, duration, static_cast<DNSAction::Action>(action), false, nullptr)) {
+ if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, std::move(dblock), false)) {
g_dynblockSMT.setState(slow);
return true;
}
luaCtx.registerMember("action", &DynBlock::action);
luaCtx.registerMember("warning", &DynBlock::warning);
luaCtx.registerMember("bpf", &DynBlock::bpf);
+
+ luaCtx.writeFunction("addDynBlockSMT",
+ [](const LuaArray<std::string>& names, const std::string& msg, boost::optional<int> seconds, boost::optional<DNSAction::Action> action, DynamicActionOptionalParameters optionalParameters) {
+ if (names.empty()) {
+ return;
+ }
+ setLuaSideEffect();
+ timespec now{};
+ gettime(&now);
+ unsigned int actualSeconds = seconds ? *seconds : 10;
+ DynBlockRulesGroup::DynBlockRule rule;
+ parseDynamicActionOptionalParameters("addDynBlockSMT", rule, action, optionalParameters);
+
+ bool needUpdate = false;
+ auto slow = g_dynblockSMT.getCopy();
+ for (const auto& capair : names) {
+ DNSName domain(capair.second);
+ domain.makeUsLowerCase();
+ timespec until{now};
+ until.tv_sec += actualSeconds;
+ DynBlock dblock{msg, until, std::move(domain), action ? *action : DNSAction::Action::None};
+ dblock.tagSettings = rule.d_tagSettings;
+ if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, std::move(dblock), false)) {
+ needUpdate = true;
+ }
+ }
+
+ if (needUpdate) {
+ g_dynblockSMT.setState(slow);
+ }
+ });
+
+ luaCtx.writeFunction("addDynamicBlock",
+ [](const boost::variant<ComboAddress, std::string>& clientIP, const std::string& msg, const boost::optional<DNSAction::Action> action, const boost::optional<int> seconds, boost::optional<uint8_t> clientIPMask, boost::optional<uint8_t> clientIPPortMask, DynamicActionOptionalParameters optionalParameters) {
+ setLuaSideEffect();
+
+ ComboAddress clientIPCA;
+ if (clientIP.type() == typeid(ComboAddress)) {
+ clientIPCA = boost::get<ComboAddress>(clientIP);
+ }
+ else {
+ const auto& clientIPStr = boost::get<std::string>(clientIP);
+ try {
+ clientIPCA = ComboAddress(clientIPStr);
+ }
+ catch (const std::exception& exp) {
+ errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.what());
+ return;
+ }
+ catch (const PDNSException& exp) {
+ errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.reason);
+ return;
+ }
+ }
+ AddressAndPortRange target(clientIPCA, clientIPMask ? *clientIPMask : (clientIPCA.isIPv4() ? 32 : 128), clientIPPortMask ? *clientIPPortMask : 0);
+ unsigned int actualSeconds = seconds ? *seconds : 10;
+ DynBlockRulesGroup::DynBlockRule rule;
+ parseDynamicActionOptionalParameters("addDynBlockSMT", rule, action, optionalParameters);
+
+ timespec now{};
+ gettime(&now);
+ timespec until{now};
+ until.tv_sec += actualSeconds;
+ DynBlock dblock{msg, until, DNSName(), action ? *action : DNSAction::Action::None};
+ dblock.tagSettings = rule.d_tagSettings;
+
+ auto slow = g_dynblockNMG.getCopy();
+ if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, std::move(dblock), false)) {
+ g_dynblockNMG.setState(slow);
+ }
+ });
#endif /* DISABLE_DYNBLOCKS */
}
});
#endif /* DISABLE_DEPRECATED_DYNBLOCK */
- luaCtx.writeFunction("addDynBlockSMT",
- [](const LuaArray<std::string>& names, const std::string& msg, boost::optional<int> seconds, boost::optional<DNSAction::Action> action) {
- if (names.empty()) {
- return;
- }
- setLuaSideEffect();
- timespec now{};
- gettime(&now);
- unsigned int actualSeconds = seconds ? *seconds : 10;
-
- bool needUpdate = false;
- auto slow = g_dynblockSMT.getCopy();
- for (const auto& capair : names) {
- DNSName domain(capair.second);
- domain.makeUsLowerCase();
-#warning FIXME: need to handle tags
- if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, domain, msg, actualSeconds, action ? *action : DNSAction::Action::None, false, nullptr)) {
- needUpdate = true;
- }
- }
-
- if (needUpdate) {
- g_dynblockSMT.setState(slow);
- }
- });
-
- luaCtx.writeFunction("addDynamicBlock",
- [](const boost::variant<ComboAddress, std::string>& clientIP, const std::string& msg, const boost::optional<DNSAction::Action> action, const boost::optional<int> seconds, boost::optional<uint8_t> clientIPMask, boost::optional<uint8_t> clientIPPortMask) {
- setLuaSideEffect();
-
- ComboAddress clientIPCA;
- if (clientIP.type() == typeid(ComboAddress)) {
- clientIPCA = boost::get<ComboAddress>(clientIP);
- }
- else {
- const auto& clientIPStr = boost::get<std::string>(clientIP);
- try {
- clientIPCA = ComboAddress(clientIPStr);
- }
- catch (const std::exception& exp) {
- errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.what());
- return;
- }
- catch (const PDNSException& exp) {
- errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.reason);
- return;
- }
- }
- AddressAndPortRange target(clientIPCA, clientIPMask ? *clientIPMask : (clientIPCA.isIPv4() ? 32 : 128), clientIPPortMask ? *clientIPPortMask : 0);
- unsigned int actualSeconds = seconds ? *seconds : 10;
-
- timespec now{};
- gettime(&now);
- auto slow = g_dynblockNMG.getCopy();
-#warning FIXME: need to handle tags
- if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, msg, actualSeconds, action ? *action : DNSAction::Action::None, false, false, nullptr)) {
- g_dynblockNMG.setState(slow);
- }
- });
-
luaCtx.writeFunction("setDynBlocksPurgeInterval", [](uint64_t interval) {
DynBlockMaintenance::s_expiredDynBlocksPurgeInterval = static_cast<time_t>(interval);
});