return std::make_shared<dnsdist::rules::RuleAction>(ruleaction);
});
- luaCtx.writeFunction("addAction", [](const luadnsrule_t& var, boost::variant<std::shared_ptr<DNSAction>, std::shared_ptr<DNSResponseAction>> era, boost::optional<luaruleparams_t> params) {
- if (era.type() != typeid(std::shared_ptr<DNSAction>)) {
- throw std::runtime_error("addAction() can only be called with query-related actions, not response-related ones. Are you looking for addResponseAction()?");
- }
+ for (const auto& chain : dnsdist::rules::getRuleChains()) {
+ auto fullName = std::string("add") + chain.prefix + std::string("Action");
+ luaCtx.writeFunction(fullName, [&fullName, &chain](const luadnsrule_t& var, boost::variant<std::shared_ptr<DNSAction>, std::shared_ptr<DNSResponseAction>> era, boost::optional<luaruleparams_t> params) {
+ if (era.type() != typeid(std::shared_ptr<DNSAction>)) {
+ throw std::runtime_error(fullName + "() can only be called with query-related actions, not response-related ones. Are you looking for addResponseAction()?");
+ }
- addAction(&dnsdist::rules::g_ruleactions, var, boost::get<std::shared_ptr<DNSAction>>(era), params);
- });
+ addAction(&chain.holder, var, boost::get<std::shared_ptr<DNSAction>>(era), params);
+ });
+ fullName = std::string("get") + chain.prefix + std::string("Action");
+ luaCtx.writeFunction(fullName, [&chain](unsigned int num) {
+ setLuaNoSideEffect();
+ boost::optional<std::shared_ptr<DNSAction>> ret;
+ auto ruleactions = chain.holder.getCopy();
+ if (num < ruleactions.size()) {
+ ret = ruleactions[num].d_action;
+ }
+ return ret;
+ });
+ }
for (const auto& chain : dnsdist::rules::getResponseRuleChains()) {
const auto fullName = std::string("add") + chain.prefix + std::string("ResponseAction");
}
});
- luaCtx.writeFunction("getAction", [](unsigned int num) {
- setLuaNoSideEffect();
- boost::optional<std::shared_ptr<DNSAction>> ret;
- auto ruleactions = dnsdist::rules::g_ruleactions.getCopy();
- if (num < ruleactions.size()) {
- ret = ruleactions[num].d_action;
- }
- return ret;
- });
-
luaCtx.registerFunction("getStats", &DNSAction::getStats);
luaCtx.registerFunction("reload", &DNSAction::reload);
luaCtx.registerFunction("reload", &DNSResponseAction::reload);
auto rules = chain.holder.getLocal();
return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars);
});
+
+ luaCtx.writeFunction("clear" + chain.prefix + "ResponseRules", [&chain]() {
+ setLuaSideEffect();
+ chain.holder.modify([](std::remove_reference_t<decltype(chain.holder)>::value_type& ruleactions) {
+ ruleactions.clear();
+ });
+ });
}
- luaCtx.writeFunction("rmRule", [](const boost::variant<unsigned int, std::string>& identifier) {
- rmRule(&dnsdist::rules::g_ruleactions, identifier);
- });
+ for (const auto& chain : dnsdist::rules::getRuleChains()) {
+ luaCtx.writeFunction("show" + chain.prefix + "Rules", [&chain](boost::optional<ruleparams_t> vars) {
+ showRules(&chain.holder, vars);
+ });
+ luaCtx.writeFunction("rm" + chain.prefix + "Rule", [&chain](const boost::variant<unsigned int, std::string>& identifier) {
+ rmRule(&chain.holder, identifier);
+ });
+ luaCtx.writeFunction("mv" + chain.prefix + "RuleToTop", [&chain]() {
+ moveRuleToTop(&chain.holder);
+ });
+ luaCtx.writeFunction("mv" + chain.prefix + "Rule", [&chain](unsigned int from, unsigned int dest) {
+ mvRule(&chain.holder, from, dest);
+ });
+ luaCtx.writeFunction("get" + chain.prefix + "Rule", [&chain](const boost::variant<int, std::string>& selector) -> boost::optional<dnsdist::rules::RuleAction> {
+ auto rules = chain.holder.getLocal();
+ return getRuleFromSelector(*rules, selector);
+ });
- luaCtx.writeFunction("mvRuleToTop", []() {
- moveRuleToTop(&dnsdist::rules::g_ruleactions);
- });
+ luaCtx.writeFunction("getTop" + chain.prefix + "Rules", [&chain](boost::optional<unsigned int> top) {
+ setLuaNoSideEffect();
+ auto rules = chain.holder.getLocal();
+ return toLuaArray(getTopRules(*rules, (top ? *top : 10)));
+ });
- luaCtx.writeFunction("mvRule", [](unsigned int from, unsigned int dest) {
- mvRule(&dnsdist::rules::g_ruleactions, from, dest);
- });
+ luaCtx.writeFunction("top" + chain.prefix + "Rules", [&chain](boost::optional<unsigned int> top, boost::optional<ruleparams_t> vars) {
+ setLuaNoSideEffect();
+ auto rules = chain.holder.getLocal();
+ return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars);
+ });
- luaCtx.writeFunction("clearRules", []() {
- setLuaSideEffect();
- dnsdist::rules::g_ruleactions.modify([](decltype(dnsdist::rules::g_ruleactions)::value_type& ruleactions) {
- ruleactions.clear();
+ luaCtx.writeFunction("clear" + chain.prefix + "Rules", [&chain]() {
+ setLuaSideEffect();
+ chain.holder.modify([](std::remove_reference_t<decltype(chain.holder)>::value_type& ruleactions) {
+ ruleactions.clear();
+ });
});
- });
- luaCtx.writeFunction("setRules", [](const LuaArray<std::shared_ptr<dnsdist::rules::RuleAction>>& newruleactions) {
- setLuaSideEffect();
- dnsdist::rules::g_ruleactions.modify([newruleactions](decltype(dnsdist::rules::g_ruleactions)::value_type& gruleactions) {
- gruleactions.clear();
- for (const auto& pair : newruleactions) {
- const auto& newruleaction = pair.second;
- if (newruleaction->d_action) {
- auto rule = newruleaction->d_rule;
- gruleactions.push_back({std::move(rule), newruleaction->d_action, newruleaction->d_name, newruleaction->d_id, newruleaction->d_creationOrder});
+ luaCtx.writeFunction("set" + chain.prefix + "Rules", [&chain](const LuaArray<std::shared_ptr<dnsdist::rules::RuleAction>>& newruleactions) {
+ setLuaSideEffect();
+ chain.holder.modify([newruleactions](std::remove_reference_t<decltype(chain.holder)>::value_type& gruleactions) {
+ gruleactions.clear();
+ for (const auto& pair : newruleactions) {
+ const auto& newruleaction = pair.second;
+ if (newruleaction->d_action) {
+ auto rule = newruleaction->d_rule;
+ gruleactions.push_back({std::move(rule), newruleaction->d_action, newruleaction->d_name, newruleaction->d_id, newruleaction->d_creationOrder});
+ }
}
- }
+ });
});
- });
-
- luaCtx.writeFunction("getRule", [](const boost::variant<int, std::string>& selector) -> boost::optional<dnsdist::rules::RuleAction> {
- auto rules = dnsdist::rules::g_ruleactions.getLocal();
- return getRuleFromSelector(*rules, selector);
- });
-
- luaCtx.writeFunction("getTopRules", [](boost::optional<unsigned int> top) {
- setLuaNoSideEffect();
- auto rules = dnsdist::rules::g_ruleactions.getLocal();
- return toLuaArray(getTopRules(*rules, (top ? *top : 10)));
- });
-
- luaCtx.writeFunction("topRules", [](boost::optional<unsigned int> top, boost::optional<ruleparams_t> vars) {
- setLuaNoSideEffect();
- auto rules = dnsdist::rules::g_ruleactions.getLocal();
- return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars);
- });
+ }
luaCtx.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional<unsigned int> ipv4trunc, boost::optional<unsigned int> ipv6trunc, boost::optional<unsigned int> burst, boost::optional<unsigned int> expiration, boost::optional<unsigned int> cleanupDelay, boost::optional<unsigned int> scanFraction, boost::optional<unsigned int> shards) {
return std::shared_ptr<DNSRule>(new MaxQPSIPRule(qps, (burst ? *burst : qps), (ipv4trunc ? *ipv4trunc : 32), (ipv6trunc ? *ipv6trunc : 64), (expiration ? *expiration : 300), (cleanupDelay ? *cleanupDelay : 60), (scanFraction ? *scanFraction : 10), (shards ? *shards : 10)));
return std::shared_ptr<DNSRule>(new EDNSOptionRule(optcode));
});
- luaCtx.writeFunction("showRules", [](boost::optional<ruleparams_t> vars) {
- showRules(&dnsdist::rules::g_ruleactions, vars);
- });
-
luaCtx.writeFunction("RDRule", []() {
return std::shared_ptr<DNSRule>(new RDRule());
});
namespace dnsdist::rules
{
-GlobalStateHolder<std::vector<RuleAction>> g_ruleactions;
+GlobalStateHolder<std::vector<RuleAction>> s_ruleActions;
+GlobalStateHolder<std::vector<RuleAction>> s_cacheMissRuleActions;
GlobalStateHolder<std::vector<ResponseRuleAction>> s_respruleactions;
GlobalStateHolder<std::vector<ResponseRuleAction>> s_cachehitrespruleactions;
GlobalStateHolder<std::vector<ResponseRuleAction>> s_selfansweredrespruleactions;
{
return s_responseRuleChains.at(static_cast<size_t>(chain)).holder;
}
+
+static const std::vector<RuleChainDescription> s_ruleChains{
+ {"", "rules", s_ruleActions},
+ {"CacheMiss", "cache-miss-rules", s_cacheMissRuleActions},
+};
+
+const std::vector<RuleChainDescription>& getRuleChains()
+{
+ return s_ruleChains;
+}
+
+GlobalStateHolder<std::vector<RuleAction>>& getRuleChainHolder(RuleChain chain)
+{
+ return s_ruleChains.at(static_cast<size_t>(chain)).holder;
+}
}
namespace dnsdist::rules
{
-enum class ResponseRuleChain : uint8_t
-{
- ResponseRules = 0,
- CacheHitResponseRules = 1,
- CacheInsertedResponseRules = 2,
- SelfAnsweredResponseRules = 3,
- XFRResponseRules = 4,
-};
-
struct RuleAction
{
std::shared_ptr<DNSRule> d_rule;
uint64_t d_creationOrder;
};
+struct RuleChainDescription
+{
+ std::string prefix;
+ std::string metricName;
+ GlobalStateHolder<std::vector<RuleAction>>& holder;
+};
+
+enum class RuleChain : uint8_t
+{
+ Rules = 0,
+ CacheMissRules = 1,
+};
+
+const std::vector<RuleChainDescription>& getRuleChains();
+GlobalStateHolder<std::vector<RuleAction>>& getRuleChainHolder(RuleChain chain);
+
struct ResponseRuleAction
{
std::shared_ptr<DNSRule> d_rule;
uint64_t d_creationOrder;
};
+enum class ResponseRuleChain : uint8_t
+{
+ ResponseRules = 0,
+ CacheHitResponseRules = 1,
+ CacheInsertedResponseRules = 2,
+ SelfAnsweredResponseRules = 3,
+ XFRResponseRules = 4,
+};
+
struct ResponseRuleChainDescription
{
std::string prefix;
GlobalStateHolder<std::vector<ResponseRuleAction>>& holder;
};
-extern GlobalStateHolder<std::vector<RuleAction>> g_ruleactions;
-
const std::vector<ResponseRuleChainDescription>& getResponseRuleChains();
GlobalStateHolder<std::vector<ResponseRuleAction>>& getResponseRuleChainHolder(ResponseRuleChain chain);
output << "# HELP dnsdist_rule_hits " << "Number of hits of that rule" << "\n";
output << "# TYPE dnsdist_rule_hits " << "counter" << "\n";
- addRulesToPrometheusOutput(output, dnsdist::rules::g_ruleactions);
+ for (const auto& chain : dnsdist::rules::getRuleChains()) {
+ addRulesToPrometheusOutput(output, chain.holder);
+ }
for (const auto& chain : dnsdist::rules::getResponseRuleChains()) {
addRulesToPrometheusOutput(output, chain.holder);
}
}
}
- Json::array rules;
- /* unfortunately DNSActions have getStats(),
- and DNSResponseActions do not. */
- {
- auto localRules = dnsdist::rules::g_ruleactions.getLocal();
- num = 0;
- rules.reserve(localRules->size());
- for (const auto& lrule : *localRules) {
- Json::object rule{
- {"id", num++},
- {"creationOrder", (double)lrule.d_creationOrder},
- {"uuid", boost::uuids::to_string(lrule.d_id)},
- {"name", lrule.d_name},
- {"matches", (double)lrule.d_rule->d_matches},
- {"rule", lrule.d_rule->toString()},
- {"action", lrule.d_action->toString()},
- {"action-stats", lrule.d_action->getStats()}};
- rules.emplace_back(std::move(rule));
- }
- }
-
string acl;
{
auto aclEntries = g_ACL.getLocal()->toStringVector();
{"servers", std::move(servers)},
{"frontends", std::move(frontends)},
{"pools", std::move(pools)},
- {"rules", std::move(rules)},
{"acl", std::move(acl)},
{"local", std::move(localaddressesStr)},
{"dohFrontends", std::move(dohs)},
{"statistics", std::move(stats)}};
+ /* unfortunately DNSActions have getStats(),
+ and DNSResponseActions do not. */
+ for (const auto& chain : dnsdist::rules::getRuleChains()) {
+ Json::array rules;
+ auto localRules = chain.holder.getLocal();
+ num = 0;
+ rules.reserve(localRules->size());
+ for (const auto& lrule : *localRules) {
+ Json::object rule{
+ {"id", num++},
+ {"creationOrder", (double)lrule.d_creationOrder},
+ {"uuid", boost::uuids::to_string(lrule.d_id)},
+ {"name", lrule.d_name},
+ {"matches", (double)lrule.d_rule->d_matches},
+ {"rule", lrule.d_rule->toString()},
+ {"action", lrule.d_action->toString()},
+ {"action-stats", lrule.d_action->getStats()}};
+ rules.emplace_back(std::move(rule));
+ }
+ responseObject[chain.metricName] = std::move(rules);
+ }
+
for (const auto& chain : dnsdist::rules::getResponseRuleChains()) {
auto responseRules = someResponseRulesToJson(&chain.holder);
responseObject[chain.metricName] = std::move(responseRules);
return false;
}
-static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dnsQuestion, const struct timespec& now)
+static bool applyRulesChainToQuery(const std::vector<dnsdist::rules::RuleAction>& rules, DNSQuestion& dnsQuestion)
+{
+ DNSAction::Action action = DNSAction::Action::None;
+ string ruleresult;
+ bool drop = false;
+
+ for (const auto& rule : rules) {
+ if (!rule.d_rule->matches(&dnsQuestion)) {
+ continue;
+ }
+
+ rule.d_rule->d_matches++;
+ action = (*rule.d_action)(&dnsQuestion, &ruleresult);
+ if (processRulesResult(action, dnsQuestion, ruleresult, drop)) {
+ break;
+ }
+ }
+
+ return !drop;
+}
+
+static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dnsQuestion, const timespec& now)
{
if (g_rings.shouldRecordQueries()) {
g_rings.insertQuery(now, dnsQuestion.ids.origRemote, dnsQuestion.ids.qname, dnsQuestion.ids.qtype, dnsQuestion.getData().size(), *dnsQuestion.getHeader(), dnsQuestion.getProtocol());
}
#endif /* DISABLE_DYNBLOCKS */
- DNSAction::Action action = DNSAction::Action::None;
- string ruleresult;
- bool drop = false;
- for (const auto& rule : *holders.ruleactions) {
- if (rule.d_rule->matches(&dnsQuestion)) {
- rule.d_rule->d_matches++;
- action = (*rule.d_action)(&dnsQuestion, &ruleresult);
- if (processRulesResult(action, dnsQuestion, ruleresult, drop)) {
- break;
- }
- }
- }
-
- return !drop;
+ return applyRulesChainToQuery(*holders.ruleactions, dnsQuestion);
}
ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& backend, const int socketDesc, const PacketBuffer& request, bool healthCheck)
return true;
}
+static ProcessQueryResult handleQueryTurnedIntoSelfAnsweredResponse(DNSQuestion& dnsQuestion, LocalHolders& holders)
+{
+ fixUpQueryTurnedResponse(dnsQuestion, dnsQuestion.ids.origFlags);
+
+ if (!prepareOutgoingResponse(holders, *dnsQuestion.ids.cs, dnsQuestion, false)) {
+ return ProcessQueryResult::Drop;
+ }
+
+ const auto rcode = dnsQuestion.getHeader()->rcode;
+ if (rcode == RCode::NXDomain) {
+ ++dnsdist::metrics::g_stats.ruleNXDomain;
+ }
+ else if (rcode == RCode::Refused) {
+ ++dnsdist::metrics::g_stats.ruleRefused;
+ }
+ else if (rcode == RCode::ServFail) {
+ ++dnsdist::metrics::g_stats.ruleServFail;
+ }
+
+ ++dnsdist::metrics::g_stats.selfAnswered;
+ ++dnsQuestion.ids.cs->responses;
+ return ProcessQueryResult::SendAnswer;
+}
+
+static void selectBackendForOutgoingQuery(DNSQuestion& dnsQuestion, const std::shared_ptr<ServerPool>& serverPool, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend)
+{
+ std::shared_ptr<ServerPolicy> poolPolicy = serverPool->policy;
+ const auto& policy = poolPolicy != nullptr ? *poolPolicy : *(holders.policy);
+ const auto servers = serverPool->getServers();
+ selectedBackend = policy.getSelectedBackend(*servers, dnsQuestion);
+}
+
ProcessQueryResult processQueryAfterRules(DNSQuestion& dnsQuestion, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend)
{
const uint16_t queryId = ntohs(dnsQuestion.getHeader()->id);
try {
if (dnsQuestion.getHeader()->qr) { // something turned it into a response
- fixUpQueryTurnedResponse(dnsQuestion, dnsQuestion.ids.origFlags);
-
- if (!prepareOutgoingResponse(holders, *dnsQuestion.ids.cs, dnsQuestion, false)) {
- return ProcessQueryResult::Drop;
- }
-
- const auto rcode = dnsQuestion.getHeader()->rcode;
- if (rcode == RCode::NXDomain) {
- ++dnsdist::metrics::g_stats.ruleNXDomain;
- }
- else if (rcode == RCode::Refused) {
- ++dnsdist::metrics::g_stats.ruleRefused;
- }
- else if (rcode == RCode::ServFail) {
- ++dnsdist::metrics::g_stats.ruleServFail;
- }
-
- ++dnsdist::metrics::g_stats.selfAnswered;
- ++dnsQuestion.ids.cs->responses;
- return ProcessQueryResult::SendAnswer;
+ return handleQueryTurnedIntoSelfAnsweredResponse(dnsQuestion, holders);
}
std::shared_ptr<ServerPool> serverPool = getPool(*holders.pools, dnsQuestion.ids.poolName);
- std::shared_ptr<ServerPolicy> poolPolicy = serverPool->policy;
dnsQuestion.ids.packetCache = serverPool->packetCache;
- const auto& policy = poolPolicy != nullptr ? *poolPolicy : *(holders.policy);
- const auto servers = serverPool->getServers();
- selectedBackend = policy.getSelectedBackend(*servers, dnsQuestion);
+ selectBackendForOutgoingQuery(dnsQuestion, serverPool, holders, selectedBackend);
uint32_t allowExpired = selectedBackend ? 0 : g_staleCacheEntriesTTL;
vinfolog("Packet cache miss for query for %s|%s from %s (%s, %d bytes)", dnsQuestion.ids.qname.toLogString(), QType(dnsQuestion.ids.qtype).toString(), dnsQuestion.ids.origRemote.toStringWithPort(), dnsQuestion.ids.protocol.toString(), dnsQuestion.getData().size());
++dnsdist::metrics::g_stats.cacheMisses;
+
+ const auto existingPool = dnsQuestion.ids.poolName;
+ if (!applyRulesChainToQuery(*holders.cacheMissRuleActions, dnsQuestion)) {
+ return ProcessQueryResult::Drop;
+ }
+ if (dnsQuestion.getHeader()->qr) { // something turned it into a response
+ return handleQueryTurnedIntoSelfAnsweredResponse(dnsQuestion, holders);
+ }
+ /* let's be nice and allow the selection of a different pool,
+ but no second cache-lookup for you */
+ if (dnsQuestion.ids.poolName != existingPool) {
+ serverPool = getPool(*holders.pools, dnsQuestion.ids.poolName);
+ dnsQuestion.ids.packetCache = serverPool->packetCache;
+ selectBackendForOutgoingQuery(dnsQuestion, serverPool, holders, selectedBackend);
+ }
}
if (!selectedBackend) {
{
/* when our coverage mode is enabled, we need to make sure
that the Lua objects are destroyed before the Lua contexts. */
- dnsdist::rules::g_ruleactions.setState({});
+ for (const auto& chain : dnsdist::rules::getRuleChains()) {
+ chain.holder.setState({});
+ }
for (const auto& chain : dnsdist::rules::getResponseRuleChains()) {
chain.holder.setState({});
}
struct LocalHolders
{
LocalHolders() :
- acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(dnsdist::rules::g_ruleactions.getLocal()), cacheHitRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheHitResponseRules).getLocal()), cacheInsertedRespRuleActions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheInsertedResponseRules).getLocal()), selfAnsweredRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::SelfAnsweredResponseRules).getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal())
+ acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(dnsdist::rules::getRuleChainHolder(dnsdist::rules::RuleChain::Rules).getLocal()), cacheMissRuleActions(dnsdist::rules::getRuleChainHolder(dnsdist::rules::RuleChain::CacheMissRules).getLocal()), cacheHitRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheHitResponseRules).getLocal()), cacheInsertedRespRuleActions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheInsertedResponseRules).getLocal()), selfAnsweredRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::SelfAnsweredResponseRules).getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal())
{
}
LocalStateHolder<NetmaskGroup> acl;
LocalStateHolder<ServerPolicy> policy;
LocalStateHolder<vector<dnsdist::rules::RuleAction>> ruleactions;
+ LocalStateHolder<vector<dnsdist::rules::RuleAction>> cacheMissRuleActions;
LocalStateHolder<vector<dnsdist::rules::ResponseRuleAction>> cacheHitRespRuleactions;
LocalStateHolder<vector<dnsdist::rules::ResponseRuleAction>> cacheInsertedRespRuleActions;
LocalStateHolder<vector<dnsdist::rules::ResponseRuleAction>> selfAnsweredRespRuleactions;
:param int n: The rule number
-.. function:: getCacheHitResponseRule(selector) -> DNSDistResponseRuleAction
+.. function:: getRule(selector) -> DNSDistRuleAction
.. versionadded:: 1.9.0
- Return the cache-hit response rule corresponding to the selector, if any.
+ Return the rule corresponding to the selector, if any.
The selector can be the position of the rule in the list, as an integer,
its name as a string or its UUID as a string as well.
:param int or str selector: The position in the list, name or UUID of the rule to return.
-.. function:: getCacheInsertedResponseRule(selector) -> DNSDistResponseRuleAction
+.. function:: mvRule(from, to)
- .. versionadded:: 1.9.0
+ Move rule ``from`` to a position where it is in front of ``to``.
+ ``to`` can be one larger than the largest rule, in which case the rule will be moved to the last position.
- Return the cache-inserted response rule corresponding to the selector, if any.
- The selector can be the position of the rule in the list, as an integer,
- its name as a string or its UUID as a string as well.
+ :param int from: Rule number to move
+ :param int to: Location to more the Rule to
- :param int or str selector: The position in the list, name or UUID of the rule to return.
+.. function:: mvRuleToTop()
-.. function:: getResponseRule(selector) -> DNSDistResponseRuleAction
+ .. versionadded:: 1.6.0
- .. versionadded:: 1.9.0
+ This function moves the last rule to the first position. Before 1.6.0 this was handled by :func:`topRule`.
- Return the response rule corresponding to the selector, if any.
- The selector can be the position of the rule in the list, as an integer,
- its name as a string or its UUID as a string as well.
+.. function:: setRules(rules)
- :param int or str selector: The position in the list, name or UUID of the rule to return.
+ Replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see :func:`newRuleAction`)
-.. function:: getRule(selector) -> DNSDistRuleAction
+ :param [RuleAction] rules: A list of RuleActions
- .. versionadded:: 1.9.0
+.. function:: showRules([options])
- Return the rule corresponding to the selector, if any.
- The selector can be the position of the rule in the list, as an integer,
- its name as a string or its UUID as a string as well.
+ Show all defined rules for queries, optionally displaying their UUIDs.
- :param int or str selector: The position in the list, name or UUID of the rule to return.
+ :param table options: A table with key: value pairs with display options.
-.. function:: getSelfAnsweredResponseRule(selector) -> DNSDistResponseRuleAction
+ Options:
- .. versionadded:: 1.9.0
+ * ``showUUIDs=false``: bool - Whether to display the UUIDs, defaults to false.
+ * ``truncateRuleWidth=-1``: int - Truncate rules output to ``truncateRuleWidth`` size. Defaults to ``-1`` to display the full rule.
- Return the self-answered response rule corresponding to the selector, if any.
- The selector can be the position of the rule in the list, as an integer,
- its name as a string or its UUID as a string as well.
+.. function:: topRule()
- :param int or str selector: The position in the list, name or UUID of the rule to return.
+ .. versionchanged:: 1.6.0
+ Replaced by :func:`mvRuleToTop`
-.. function:: mvRule(from, to)
+ Before 1.6.0 this function used to move the last rule to the first position, which is now handled by :func:`mvRuleToTop`.
- Move rule ``from`` to a position where it is in front of ``to``.
- ``to`` can be one larger than the largest rule, in which case the rule will be moved to the last position.
+.. function:: rmRule(id)
- :param int from: Rule number to move
- :param int to: Location to more the Rule to
+ .. versionchanged:: 1.6.0
+ ``id`` can now be a string representing the name of the rule.
-.. function:: mvRuleToTop()
+ Remove rule ``id``.
- .. versionadded:: 1.6.0
+ :param int id: The position of the rule to remove if ``id`` is numerical, its UUID or name otherwise
- This function moves the last rule to the first position. Before 1.6.0 this was handled by :func:`topRule`.
+Cache misses
+------------
-.. function:: newRuleAction(rule, action[, options])
+For Rules related to the incoming query after a cache miss:
- .. versionchanged:: 1.6.0
- Added ``name`` to the ``options``.
+.. warning::
+ While all selectors and actions are available, some actions will no longer be honored at
+ this point. For example changing the backend pool will not trigger a second cache-lookup.
+ Switching from a backend pool that has EDNS Client Subnet enabled to one that doesn't
+ will result in the EDNS Client Subnet corresponding to the initial server pool to be
+ added to the query.
- Return a pair of DNS Rule and DNS Action, to be used with :func:`setRules`.
+.. function:: addCacheMissAction(DNSrule, action [, options])
- :param Rule rule: A Rule (see :doc:`selectors`)
- :param Action action: The Action (see :doc:`actions`) to apply to the matched traffic
+ .. versionadded:: 1.10
+
+ Add a Rule and Action to the existing cache miss rules.
+ If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`.
+
+ :param DNSrule rule: A :class:`DNSRule`, e.g. an :func:`AllRule`, or a compounded bunch of rules using e.g. :func:`AndRule`.
+ :param action: The action to take
:param table options: A table with key: value pairs with options.
Options:
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
* ``name``: string - Name to assign to the new rule.
-.. function:: setRules(rules)
+.. function:: clearCacheMissRules()
- Replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see :func:`newRuleAction`)
+ .. versionadded:: 1.10
+
+ Remove all current cache miss rules.
+
+.. function:: getCacheMissAction(n) -> DNSDistRuleAction
+
+ .. versionadded:: 1.10
+
+ Returns the :class:`DNSDistRuleAction` associated with cache miss rule ``n``.
+
+ :param int n: The rule number
+
+.. function:: getCacheMissRule(selector) -> DNSDistRuleAction
+
+ .. versionadded:: 1.10
+
+ Return the cache miss rule corresponding to the selector, if any.
+ The selector can be the position of the rule in the list, as an integer,
+ its name as a string or its UUID as a string as well.
+
+ :param int or str selector: The position in the list, name or UUID of the rule to return.
+
+.. function:: mvCacheMissRule(from, to)
+
+ .. versionadded:: 1.10
+
+ Move cache miss rule ``from`` to a position where it is in front of ``to``.
+ ``to`` can be one larger than the largest rule, in which case the rule will be moved to the last position.
+
+ :param int from: Rule number to move
+ :param int to: Location to more the Rule to
+
+.. function:: mvCacheMissRuleToTop()
+
+ .. versionadded:: 1.10
+
+ This function moves the last cache miss rule to the first position.
+
+.. function:: setCacheMissRules(rules)
+
+ .. versionadded:: 1.10
+
+ Replace the current cache miss rules with the supplied list of pairs of DNS Rules and DNS Actions (see :func:`newRuleAction`)
:param [RuleAction] rules: A list of RuleActions
-.. function:: showRules([options])
+.. function:: showCacheMissRules([options])
- Show all defined rules for queries, optionally displaying their UUIDs.
+ .. versionadded:: 1.10
+
+ Show all defined cache miss rules for queries, optionally displaying their UUIDs.
:param table options: A table with key: value pairs with display options.
* ``showUUIDs=false``: bool - Whether to display the UUIDs, defaults to false.
* ``truncateRuleWidth=-1``: int - Truncate rules output to ``truncateRuleWidth`` size. Defaults to ``-1`` to display the full rule.
-.. function:: topRule()
-
- .. versionchanged:: 1.6.0
- Replaced by :func:`mvRuleToTop`
-
- Before 1.6.0 this function used to move the last rule to the first position, which is now handled by :func:`mvRuleToTop`.
-
-.. function:: rmRule(id)
+.. function:: rmCacheMissRule(id)
- .. versionchanged:: 1.6.0
- ``id`` can now be a string representing the name of the rule.
+ .. versionadded:: 1.10
Remove rule ``id``.
- :param int id: The position of the rule to remove if ``id`` is numerical, its UUID or name otherwise
+ :param int id: The position of the cache miss rule to remove if ``id`` is numerical, its UUID or name otherwise
Responses
---------
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
* ``name``: string - Name to assign to the new rule.
+.. function:: clearResponseRules()
+
+ .. versionadded:: 1.10
+
+ Remove all current response rules.
+
+.. function:: getResponseRule(selector) -> DNSDistResponseRuleAction
+
+ .. versionadded:: 1.9.0
+
+ Return the response rule corresponding to the selector, if any.
+ The selector can be the position of the rule in the list, as an integer,
+ its name as a string or its UUID as a string as well.
+
+ :param int or str selector: The position in the list, name or UUID of the rule to return.
+
.. function:: mvResponseRule(from, to)
Move response rule ``from`` to a position where it is in front of ``to``.
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
* ``name``: string - Name to assign to the new rule.
+.. function:: clearCacheHitResponseRules()
+
+ .. versionadded:: 1.10
+
+ Remove all current cache-hit response rules.
+
+.. function:: getCacheHitResponseRule(selector) -> DNSDistResponseRuleAction
+
+ .. versionadded:: 1.9.0
+
+ Return the cache-hit response rule corresponding to the selector, if any.
+ The selector can be the position of the rule in the list, as an integer,
+ its name as a string or its UUID as a string as well.
+
+ :param int or str selector: The position in the list, name or UUID of the rule to return.
+
.. function:: mvCacheHitResponseRule(from, to)
Move cache hit response rule ``from`` to a position where it is in front of ``to``.
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
* ``name``: string - Name to assign to the new rule.
+.. function:: clearCacheInsertedResponseRules()
+
+ .. versionadded:: 1.10
+
+ Remove all current cache-inserted response rules.
+
+.. function:: getCacheInsertedResponseRule(selector) -> DNSDistResponseRuleAction
+
+ .. versionadded:: 1.9.0
+
+ Return the cache-inserted response rule corresponding to the selector, if any.
+ The selector can be the position of the rule in the list, as an integer,
+ its name as a string or its UUID as a string as well.
+
+ :param int or str selector: The position in the list, name or UUID of the rule to return.
+
.. function:: mvCacheInsertedResponseRule(from, to)
.. versionadded:: 1.8.0
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
* ``name``: string - Name to assign to the new rule.
+.. function:: clearSelfAnsweredResponseRules()
+
+ .. versionadded:: 1.10
+
+ Remove all current self-answered response rules.
+
+.. function:: getSelfAnsweredResponseRule(selector) -> DNSDistResponseRuleAction
+
+ .. versionadded:: 1.9.0
+
+ Return the self-answered response rule corresponding to the selector, if any.
+ The selector can be the position of the rule in the list, as an integer,
+ its name as a string or its UUID as a string as well.
+
+ :param int or str selector: The position in the list, name or UUID of the rule to return.
+
.. function:: mvSelfAnsweredResponseRule(from, to)
Move self answered response rule ``from`` to a position where it is in front of ``to``.
``makeRule("0.0.0.0/0")`` will for example match all IPv4 traffic, ``makeRule({"be","nl","lu"})`` will match all Benelux DNS traffic.
:param string rule: A string, or list of strings, to convert to a rule.
+
+.. function:: newRuleAction(rule, action[, options])
+
+ .. versionchanged:: 1.6.0
+ Added ``name`` to the ``options``.
+
+ Return a pair of DNS Rule and DNS Action, to be used with :func:`setRules`.
+
+ :param Rule rule: A Rule (see :doc:`selectors`)
+ :param Action action: The Action (see :doc:`actions`) to apply to the matched traffic
+ :param table options: A table with key: value pairs with options.
+
+ Options:
+
+ * ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
+ * ``name``: string - Name to assign to the new rule.
#include "dnsdist-tcp-upstream.hh"
GlobalStateHolder<NetmaskGroup> g_ACL;
-GlobalStateHolder<std::vector<dnsdist::rules::RuleAction> > g_ruleactions;
GlobalStateHolder<servers_t> g_dstates;
QueryCount g_qcount;