Skip to content

Commit

Permalink
dnsdist: Make dynamic rules holders static
Browse files Browse the repository at this point in the history
  • Loading branch information
rgacogne committed Jul 5, 2024
1 parent f0a0605 commit 2f64f13
Show file tree
Hide file tree
Showing 22 changed files with 305 additions and 277 deletions.
3 changes: 1 addition & 2 deletions pdns/dnsdistdist/dnsdist-async.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,8 @@ bool resumeQuery(std::unique_ptr<CrossProtocolQuery>&& query)
}

DNSQuestion dnsQuestion = query->getDQ();
LocalHolders holders;

auto result = processQueryAfterRules(dnsQuestion, holders, query->downstream);
auto result = processQueryAfterRules(dnsQuestion, query->downstream);
if (result == ProcessQueryResult::Drop) {
/* easy */
return true;
Expand Down
92 changes: 70 additions & 22 deletions pdns/dnsdistdist/dnsdist-dynblocks.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

#include "dnsdist.hh"
#include "dnsdist-dynblocks.hh"
#include "dnsdist-metrics.hh"
#include "sholder.hh"

GlobalStateHolder<NetmaskTree<DynBlock, AddressAndPortRange>> g_dynblockNMG;
GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
static GlobalStateHolder<ClientAddressDynamicRules> s_dynblockNMG;
static GlobalStateHolder<SuffixDynamicRules> s_dynblockSMT;

#ifndef DISABLE_DYNBLOCKS
void DynBlockRulesGroup::apply(const timespec& now)
Expand All @@ -28,7 +28,7 @@ void DynBlockRulesGroup::apply(const timespec& now)
return;
}

boost::optional<NetmaskTree<DynBlock, AddressAndPortRange>> blocks;
boost::optional<ClientAddressDynamicRules> blocks;
bool updated = false;

for (const auto& entry : counts) {
Expand Down Expand Up @@ -114,7 +114,7 @@ void DynBlockRulesGroup::apply(const timespec& now)
}

if (updated && blocks) {
g_dynblockNMG.setState(std::move(*blocks));
s_dynblockNMG.setState(std::move(*blocks));
}

applySMT(now, statNodeRoot);
Expand Down Expand Up @@ -156,7 +156,7 @@ void DynBlockRulesGroup::applySMT(const struct timespec& now, StatNode& statNode

if (!namesToBlock.empty()) {
updated = false;
SuffixMatchTree<DynBlock> smtBlocks = g_dynblockSMT.getCopy();
auto smtBlocks = dnsdist::DynamicBlocks::getSuffixDynamicRulesCopy();
for (auto& [name, parameters] : namesToBlock) {
if (parameters.d_reason || parameters.d_action) {
DynBlockRule rule(d_suffixMatchRule);
Expand All @@ -173,7 +173,7 @@ void DynBlockRulesGroup::applySMT(const struct timespec& now, StatNode& statNode
}
}
if (updated) {
g_dynblockSMT.setState(std::move(smtBlocks));
s_dynblockSMT.setState(std::move(smtBlocks));
}
}
}
Expand Down Expand Up @@ -213,7 +213,7 @@ static DNSAction::Action getActualAction(const DynBlock& block)

namespace dnsdist::DynamicBlocks
{
bool addOrRefreshBlock(NetmaskTree<DynBlock, AddressAndPortRange>& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet)
bool addOrRefreshBlock(ClientAddressDynamicRules& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet)
{
unsigned int count = 0;
bool expired = false;
Expand Down Expand Up @@ -278,7 +278,7 @@ bool addOrRefreshBlock(NetmaskTree<DynBlock, AddressAndPortRange>& blocks, const
return true;
}

bool addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet)
bool addOrRefreshBlockSMT(SuffixDynamicRules& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet)
{
unsigned int count = 0;
/* be careful, if you try to insert a longer suffix
Expand Down Expand Up @@ -316,7 +316,7 @@ bool addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const timespec& now
}
}

void DynBlockRulesGroup::addOrRefreshBlock(boost::optional<NetmaskTree<DynBlock, AddressAndPortRange>>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated, bool warning)
void DynBlockRulesGroup::addOrRefreshBlock(boost::optional<ClientAddressDynamicRules>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated, bool warning)
{
/* network exclusions are address-based only (no port) */
if (d_excludedSubnets.match(requestor.getNetwork())) {
Expand All @@ -332,7 +332,7 @@ void DynBlockRulesGroup::addOrRefreshBlock(boost::optional<NetmaskTree<DynBlock,
dblock.tagSettings = rule.d_tagSettings;
}
if (!blocks) {
blocks = g_dynblockNMG.getCopy();
blocks = dnsdist::DynamicBlocks::getClientAddressDynamicRulesCopy();
}

updated = dnsdist::DynamicBlocks::addOrRefreshBlock(*blocks, now, requestor, std::move(dblock), d_beQuiet);
Expand All @@ -346,7 +346,7 @@ void DynBlockRulesGroup::addOrRefreshBlock(boost::optional<NetmaskTree<DynBlock,
}
}

void DynBlockRulesGroup::addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const struct timespec& now, const DNSName& name, const DynBlockRule& rule, bool& updated)
void DynBlockRulesGroup::addOrRefreshBlockSMT(SuffixDynamicRules& blocks, const struct timespec& now, const DNSName& name, const DynBlockRule& rule, bool& updated)
{
if (d_excludedDomains.check(name)) {
/* do not add a block for excluded domains */
Expand Down Expand Up @@ -493,7 +493,7 @@ void DynBlockMaintenance::purgeExpired(const struct timespec& now)
// since the block happens in kernel space.
uint64_t bpfBlocked = 0;
{
auto blocks = g_dynblockNMG.getLocal();
auto blocks = s_dynblockNMG.getLocal();
std::vector<AddressAndPortRange> toRemove;
for (const auto& entry : *blocks) {
if (!(now < entry.second.until)) {
Expand All @@ -516,29 +516,29 @@ void DynBlockMaintenance::purgeExpired(const struct timespec& now)
}
}
if (!toRemove.empty()) {
auto updated = g_dynblockNMG.getCopy();
auto updated = dnsdist::DynamicBlocks::getClientAddressDynamicRulesCopy();
for (const auto& entry : toRemove) {
updated.erase(entry);
}
g_dynblockNMG.setState(std::move(updated));
s_dynblockNMG.setState(std::move(updated));
dnsdist::metrics::g_stats.dynBlocked += bpfBlocked;
}
}

{
std::vector<DNSName> toRemove;
auto blocks = g_dynblockSMT.getLocal();
blocks->visit([&toRemove, now](const SuffixMatchTree<DynBlock>& node) {
auto blocks = s_dynblockSMT.getLocal();
blocks->visit([&toRemove, now](const SuffixDynamicRules& node) {
if (!(now < node.d_value.until)) {
toRemove.push_back(node.d_value.domain);
}
});
if (!toRemove.empty()) {
auto updated = g_dynblockSMT.getCopy();
auto updated = dnsdist::DynamicBlocks::getSuffixDynamicRulesCopy();
for (const auto& entry : toRemove) {
updated.remove(entry);
}
g_dynblockSMT.setState(std::move(updated));
s_dynblockSMT.setState(std::move(updated));
}
}
}
Expand All @@ -550,7 +550,7 @@ std::map<std::string, std::list<std::pair<AddressAndPortRange, unsigned int>>> D
return results;
}

auto blocks = g_dynblockNMG.getLocal();
auto blocks = s_dynblockNMG.getLocal();
for (const auto& entry : *blocks) {
auto& topsForReason = results[entry.second.reason];
uint64_t value = entry.second.blocks.load();
Expand Down Expand Up @@ -583,8 +583,8 @@ std::map<std::string, std::list<std::pair<DNSName, unsigned int>>> DynBlockMaint
return results;
}

auto blocks = g_dynblockSMT.getLocal();
blocks->visit([&results, topN](const SuffixMatchTree<DynBlock>& node) {
auto blocks = s_dynblockSMT.getLocal();
blocks->visit([&results, topN](const SuffixDynamicRules& node) {
auto& topsForReason = results[node.d_value.reason];
if (topsForReason.size() < topN || topsForReason.front().second < node.d_value.blocks) {
auto newEntry = std::pair(node.d_value.domain, node.d_value.blocks.load());
Expand Down Expand Up @@ -992,4 +992,52 @@ std::string DynBlockRulesGroup::DynBlockCacheMissRatioRule::toString() const
return result.str();
}

namespace dnsdist::DynamicBlocks
{
const ClientAddressDynamicRules& getClientAddressDynamicRules()
{
static thread_local auto t_localRules = s_dynblockNMG.getLocal();
return *t_localRules;
}

ClientAddressDynamicRules getClientAddressDynamicRulesCopy()
{
return s_dynblockNMG.getCopy();
}

const SuffixDynamicRules& getSuffixDynamicRules()
{
static thread_local auto t_localRules = s_dynblockSMT.getLocal();
return *t_localRules;
}

SuffixDynamicRules getSuffixDynamicRulesCopy()
{
return s_dynblockSMT.getCopy();
}

void setClientAddressDynamicRules(ClientAddressDynamicRules&& rules)
{
s_dynblockNMG.setState(std::move(rules));
}

void setSuffixDynamicRules(SuffixDynamicRules&& rules)
{
s_dynblockSMT.setState(std::move(rules));
}

void clearClientAddressDynamicRules()
{
ClientAddressDynamicRules emptyNMG;
setClientAddressDynamicRules(std::move(emptyNMG));
}

void clearSuffixDynamicRules()
{
SuffixDynamicRules emptySMT;
setSuffixDynamicRules(std::move(emptySMT));
}

}

#endif /* DISABLE_DYNBLOCKS */
23 changes: 17 additions & 6 deletions pdns/dnsdistdist/dnsdist-dynblocks.hh
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ struct dnsdist_ffi_stat_node_t
};

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)>;
using ClientAddressDynamicRules = NetmaskTree<DynBlock, AddressAndPortRange>;
using SuffixDynamicRules = SuffixMatchTree<DynBlock>;

class DynBlockRulesGroup
{
Expand Down Expand Up @@ -290,15 +292,15 @@ private:
void applySMT(const struct timespec& now, StatNode& statNodeRoot);
bool checkIfQueryTypeMatches(const Rings::Query& query);
bool checkIfResponseCodeMatches(const Rings::Response& response);
void addOrRefreshBlock(boost::optional<NetmaskTree<DynBlock, AddressAndPortRange>>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated, bool warning);
void addOrRefreshBlockSMT(SuffixMatchTree<DynBlock>& blocks, const struct timespec& now, const DNSName& name, const DynBlockRule& rule, bool& updated);
void addOrRefreshBlock(boost::optional<ClientAddressDynamicRules>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated, bool warning);
void addOrRefreshBlockSMT(SuffixDynamicRules& blocks, const struct timespec& now, const DNSName& name, const DynBlockRule& rule, bool& updated);

void addBlock(boost::optional<NetmaskTree<DynBlock, AddressAndPortRange>>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated)
void addBlock(boost::optional<ClientAddressDynamicRules>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated)
{
addOrRefreshBlock(blocks, now, requestor, rule, updated, false);
}

void handleWarning(boost::optional<NetmaskTree<DynBlock, AddressAndPortRange>>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated)
void handleWarning(boost::optional<ClientAddressDynamicRules>& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const DynBlockRule& rule, bool& updated)
{
addOrRefreshBlock(blocks, now, requestor, rule, updated, true);
}
Expand Down Expand Up @@ -383,7 +385,16 @@ private:

namespace dnsdist::DynamicBlocks
{
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);
bool addOrRefreshBlock(ClientAddressDynamicRules& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet);
bool addOrRefreshBlockSMT(SuffixDynamicRules& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet);

const ClientAddressDynamicRules& getClientAddressDynamicRules();
const SuffixDynamicRules& getSuffixDynamicRules();
ClientAddressDynamicRules getClientAddressDynamicRulesCopy();
SuffixDynamicRules getSuffixDynamicRulesCopy();
void setClientAddressDynamicRules(ClientAddressDynamicRules&& rules);
void setSuffixDynamicRules(SuffixDynamicRules&& rules);
void clearClientAddressDynamicRules();
void clearSuffixDynamicRules();
}
#endif /* DISABLE_DYNBLOCKS */
29 changes: 13 additions & 16 deletions pdns/dnsdistdist/dnsdist-lua-ffi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1860,16 +1860,17 @@ bool dnsdist_ffi_dynamic_blocks_add(const char* address, const char* message, ui
timespec until{now};
until.tv_sec += duration;
DynBlock dblock{message, until, DNSName(), static_cast<DNSAction::Action>(action)};
auto slow = g_dynblockNMG.getCopy();

auto dynamicRules = dnsdist::DynamicBlocks::getClientAddressDynamicRulesCopy();
if (dblock.action == DNSAction::Action::SetTag && tagKey != nullptr) {
dblock.tagSettings = std::make_shared<DynBlock::TagSettings>();
dblock.tagSettings->d_name = tagKey;
if (tagValue != nullptr) {
dblock.tagSettings->d_value = tagValue;
}
}
if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, std::move(dblock), false)) {
g_dynblockNMG.setState(slow);
if (dnsdist::DynamicBlocks::addOrRefreshBlock(dynamicRules, now, target, std::move(dblock), false)) {
dnsdist::DynamicBlocks::setClientAddressDynamicRules(std::move(dynamicRules));
return true;
}
}
Expand Down Expand Up @@ -1907,16 +1908,16 @@ bool dnsdist_ffi_dynamic_blocks_smt_add(const char* suffix, const char* message,
timespec until{now};
until.tv_sec += duration;
DynBlock dblock{message, until, domain, static_cast<DNSAction::Action>(action)};
auto slow = g_dynblockSMT.getCopy();
auto smtBlocks = dnsdist::DynamicBlocks::getSuffixDynamicRulesCopy();
if (dblock.action == DNSAction::Action::SetTag && tagKey != nullptr) {
dblock.tagSettings = std::make_shared<DynBlock::TagSettings>();
dblock.tagSettings->d_name = tagKey;
if (tagValue != nullptr) {
dblock.tagSettings->d_value = tagValue;
}
}
if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, std::move(dblock), false)) {
g_dynblockSMT.setState(slow);
if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(smtBlocks, now, std::move(dblock), false)) {
dnsdist::DynamicBlocks::setSuffixDynamicRules(std::move(smtBlocks));
return true;
}
}
Expand Down Expand Up @@ -1945,13 +1946,11 @@ size_t dnsdist_ffi_dynamic_blocks_get_entries(dnsdist_ffi_dynamic_blocks_list_t*

auto list = std::make_unique<dnsdist_ffi_dynamic_blocks_list_t>();

struct timespec now
{
};
timespec now{};
gettime(&now);

auto fullCopy = g_dynblockNMG.getCopy();
for (const auto& entry : fullCopy) {
const auto& dynamicRules = dnsdist::DynamicBlocks::getClientAddressDynamicRules();
for (const auto& entry : dynamicRules) {
const auto& client = entry.first;
const auto& details = entry.second;
if (!(now < details.until)) {
Expand All @@ -1978,14 +1977,12 @@ size_t dnsdist_ffi_dynamic_blocks_smt_get_entries(dnsdist_ffi_dynamic_blocks_lis

auto list = std::make_unique<dnsdist_ffi_dynamic_blocks_list_t>();

struct timespec now
{
};
timespec now{};
gettime(&now);

const auto defaultAction = dnsdist::configuration::getCurrentRuntimeConfiguration().d_dynBlockAction;
auto fullCopy = g_dynblockSMT.getCopy();
fullCopy.visit([&now, &list, defaultAction](const SuffixMatchTree<DynBlock>& node) {
const auto& smtBlocks = dnsdist::DynamicBlocks::getSuffixDynamicRules();
smtBlocks.visit([&now, &list, defaultAction](const SuffixMatchTree<DynBlock>& node) {
if (!(now < node.d_value.until)) {
return;
}
Expand Down
12 changes: 6 additions & 6 deletions pdns/dnsdistdist/dnsdist-lua-inspection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1071,21 +1071,21 @@ void setupLuaInspection(LuaContext& luaCtx)
parseDynamicActionOptionalParameters("addDynBlockSMT", rule, action, optionalParameters);

bool needUpdate = false;
auto slow = g_dynblockSMT.getCopy();
auto smtBlocks = dnsdist::DynamicBlocks::getSuffixDynamicRulesCopy();
for (const auto& capair : names) {
DNSName domain(capair.second);
domain.makeUsLowerCase();
timespec until{now};
until.tv_sec += actualSeconds;
DynBlock dblock{msg, until, domain, action ? *action : DNSAction::Action::None};
dblock.tagSettings = rule.d_tagSettings;
if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, std::move(dblock), false)) {
if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(smtBlocks, now, std::move(dblock), false)) {
needUpdate = true;
}
}

if (needUpdate) {
g_dynblockSMT.setState(slow);
dnsdist::DynamicBlocks::setSuffixDynamicRules(std::move(smtBlocks));
}
});

Expand Down Expand Up @@ -1124,9 +1124,9 @@ void setupLuaInspection(LuaContext& luaCtx)
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);
auto dynamicRules = dnsdist::DynamicBlocks::getClientAddressDynamicRulesCopy();
if (dnsdist::DynamicBlocks::addOrRefreshBlock(dynamicRules, now, target, std::move(dblock), false)) {
dnsdist::DynamicBlocks::setClientAddressDynamicRules(std::move(dynamicRules));
}
});
#endif /* DISABLE_DYNBLOCKS */
Expand Down
Loading

0 comments on commit 2f64f13

Please sign in to comment.