const std::vector<ConsoleKeyword> g_consoleKeywords{
/* keyword, function, parameters, description */
{ "addACL", true, "netmask", "add to the ACL set who can use this server" },
- { "addAction", true, "DNS rule, DNS action", "add a rule" },
+ { "addAction", true, "DNS rule, DNS action [, {uuid=\"UUID\"}]", "add a rule" },
{ "addDNSCryptBind", true, "\"127.0.0.1:8443\", \"provider name\", \"/path/to/resolver.cert\", \"/path/to/resolver.key\", {reusePort=false, tcpFastOpenSize=0, interface=\"\", cpus={}}", "listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of `provider name`, using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The fifth optional parameter is a table of parameters" },
{ "addDynBlocks", true, "addresses, message[, seconds[, action]]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" },
{ "addLocal", true, "addr [, {doTCP=true, reusePort=false, tcpFastOpenSize=0, interface=\"\", cpus={}}]", "add `addr` to the list of addresses we listen on" },
{ "addLuaAction", true, "x, func", "where 'x' is all the combinations from `addAction`, and func is a function with the parameter `dq`, which returns an action to be taken on this packet. Good for rare packets but where you want to do a lot of processing" },
{ "addLuaResponseAction", true, "x, func", "where 'x' is all the combinations from `addAction`, and func is a function with the parameter `dr`, which returns an action to be taken on this response packet. Good for rare packets but where you want to do a lot of processing" },
- { "addCacheHitResponseAction", true, "DNS rule, DNS response action", "add a cache hit response rule" },
- { "addResponseAction", true, "DNS rule, DNS response action", "add a response rule" },
+ { "addCacheHitResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\"}]", "add a cache hit response rule" },
+ { "addResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\"}]", "add a response rule" },
{ "addTLSLocal", true, "addr, certFile, keyFile[,params]", "listen to incoming DNS over TLS queries on the specified address using the specified certificate and key. The last parameter is a table" },
{ "AllowAction", true, "", "let these packets go through" },
{ "AllowResponseAction", true, "", "let these packets go through" },
{ "newPacketCache", true, "maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true]", "return a new Packet Cache" },
{ "newQPSLimiter", true, "rate, burst", "configure a QPS limiter with that rate and that burst capacity" },
{ "newRemoteLogger", true, "address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1]", "create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`" },
- { "newRuleAction", true, "DNS rule, DNS action", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" },
+ { "newRuleAction", true, "DNS rule, DNS action [, {uuid=\"UUID\"}]", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" },
{ "newServer", true, "{address=\"ip:port\", qps=1000, order=1, weight=10, pool=\"abuse\", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName=\"a.root-servers.net.\", checkType=\"A\", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source=\"address|interface name|address@interface\"}", "instantiate a server" },
{ "newServerPolicy", true, "name, function", "create a policy object from a Lua function" },
{ "newSuffixMatchNode", true, "", "returns a new SuffixMatchNode" },
{ "registerDynBPFFilter", true, "DynBPFFilter", "register this dynamic BPF filter into the web interface so that its counters are displayed" },
{ "RemoteLogAction", true, "RemoteLogger [, alterFunction]", "send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes" },
{ "RemoteLogResponseAction", true, "RemoteLogger [,alterFunction [,includeCNAME]]", "send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records" },
- { "rmCacheHitResponseRule", true, "n", "remove cache hit response rule n" },
- { "rmResponseRule", true, "n", "remove response rule n" },
- { "rmRule", true, "n", "remove rule n" },
+ { "rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
+ { "rmResponseRule", true, "id", "remove response rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
+ { "rmRule", true, "id", "remove rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
{ "rmServer", true, "n", "remove server with index n" },
{ "roundrobin", false, "", "Simple round robin over available servers" },
{ "QNameLabelsCountRule", true, "min, max", "matches if the qname has less than `min` or more than `max` labels" },
{ "show", true, "string", "outputs `string`" },
{ "showACL", true, "", "show our ACL set" },
{ "showBinds", true, "", "show listening addresses (frontends)" },
- { "showCacheHitResponseRules", true, "", "show all defined cache hit response rules" },
+ { "showCacheHitResponseRules", true, "[showUUIDs]", "show all defined cache hit response rules, optionally with their UUIDs" },
{ "showDNSCryptBinds", true, "", "display the currently configured DNSCrypt binds" },
{ "showDynBlocks", true, "", "show dynamic blocks in force" },
{ "showPools", true, "", "show the available pools" },
{ "showPoolServerPolicy", true, "pool", "show server selection policy for this pool" },
{ "showResponseLatency", true, "", "show a plot of the response time latency distribution" },
- { "showResponseRules", true, "", "show all defined response rules" },
- { "showRules", true, "", "show all defined rules" },
+ { "showResponseRules", true, "[showUUIDs]", "show all defined response rules, optionally with their UUIDs" },
+ { "showRules", true, "[showUUIDs]", "show all defined rules, optionally with their UUIDs" },
{ "showServerPolicy", true, "", "show name of currently operational server selection policy" },
{ "showServers", true, "", "output all servers" },
{ "showTCPStats", true, "", "show some statistics regarding TCP" },
void setupLuaActions()
{
- g_lua.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr<DNSAction> action) {
+ g_lua.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr<DNSAction> action, boost::optional<luaruleparams_t> params) {
+ boost::uuids::uuid uuid;
+ parseRuleParams(params, uuid);
+
auto rule=makeRule(dnsrule);
- return std::make_shared<std::pair< luadnsrule_t, std::shared_ptr<DNSAction> > >(rule, action);
+ DNSDistRuleAction ra({rule, action, uuid});
+ return std::make_shared<DNSDistRuleAction>(ra);
});
- g_lua.writeFunction("addAction", [](luadnsrule_t var, boost::variant<std::shared_ptr<DNSAction>, std::shared_ptr<DNSResponseAction> > era) {
+ g_lua.writeFunction("addAction", [](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<DNSResponseAction>)) {
throw std::runtime_error("addAction() can only be called with query-related actions, not response-related ones. Are you looking for addResponseAction()?");
}
+ boost::uuids::uuid uuid;
+ parseRuleParams(params, uuid);
+
auto ea = *boost::get<std::shared_ptr<DNSAction>>(&era);
setLuaSideEffect();
auto rule=makeRule(var);
- g_rulactions.modify([rule, ea](decltype(g_rulactions)::value_type& rulactions){
- rulactions.push_back({rule, ea});
+ g_rulactions.modify([rule, ea, uuid](decltype(g_rulactions)::value_type& rulactions){
+ rulactions.push_back({rule, ea, uuid});
});
});
- g_lua.writeFunction("addLuaAction", [](luadnsrule_t var, LuaAction::func_t func)
- {
- setLuaSideEffect();
- auto rule=makeRule(var);
- g_rulactions.modify([rule,func](decltype(g_rulactions)::value_type& rulactions){
- rulactions.push_back({rule,
- std::make_shared<LuaAction>(func)});
- });
- });
+ g_lua.writeFunction("addLuaAction", [](luadnsrule_t var, LuaAction::func_t func) {
+ setLuaSideEffect();
+ auto rule=makeRule(var);
+ g_rulactions.modify([rule,func](decltype(g_rulactions)::value_type& rulactions){
+ rulactions.push_back({
+ rule,
+ std::make_shared<LuaAction>(func),
+ t_uuidGenerator() });
+ });
+ });
g_lua.writeFunction("addLuaResponseAction", [](luadnsrule_t var, LuaResponseAction::func_t func) {
setLuaSideEffect();
auto rule=makeRule(var);
g_resprulactions.modify([rule,func](decltype(g_resprulactions)::value_type& rulactions){
- rulactions.push_back({rule,
- std::make_shared<LuaResponseAction>(func)});
+ rulactions.push_back({
+ rule,
+ std::make_shared<LuaResponseAction>(func),
+ t_uuidGenerator() });
});
});
- g_lua.writeFunction("addResponseAction", [](luadnsrule_t var, boost::variant<std::shared_ptr<DNSAction>, std::shared_ptr<DNSResponseAction> > era) {
+ g_lua.writeFunction("addResponseAction", [](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("addResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
}
auto ea = *boost::get<std::shared_ptr<DNSResponseAction>>(&era);
+ boost::uuids::uuid uuid;
+ parseRuleParams(params, uuid);
setLuaSideEffect();
auto rule=makeRule(var);
- g_resprulactions.modify([rule, ea](decltype(g_resprulactions)::value_type& rulactions){
- rulactions.push_back({rule, ea});
+ g_resprulactions.modify([rule, ea, uuid](decltype(g_resprulactions)::value_type& rulactions){
+ rulactions.push_back({rule, ea, uuid});
});
});
- g_lua.writeFunction("addCacheHitResponseAction", [](luadnsrule_t var, std::shared_ptr<DNSResponseAction> ea) {
+ g_lua.writeFunction("addCacheHitResponseAction", [](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("addCacheHitResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
+ }
+
setLuaSideEffect();
auto rule=makeRule(var);
- g_cachehitresprulactions.modify([rule, ea](decltype(g_cachehitresprulactions)::value_type& rulactions){
- rulactions.push_back({rule, ea});
+
+ boost::uuids::uuid uuid;
+ parseRuleParams(params, uuid);
+
+ auto ea = *boost::get<std::shared_ptr<DNSResponseAction>>(&era);
+ g_cachehitresprulactions.modify([rule, ea, uuid](decltype(g_cachehitresprulactions)::value_type& rulactions){
+ rulactions.push_back({rule, ea, uuid});
});
});
boost::optional<std::shared_ptr<DNSAction>> ret;
auto rulactions = g_rulactions.getCopy();
if(num < rulactions.size())
- ret=rulactions[num].second;
+ ret=rulactions[num].d_action;
return ret;
});
return std::make_shared<NetmaskGroupRule>(nmg, true);
}
+static boost::uuids::uuid getRuleID(std::string& id)
+{
+ if (id.empty()) {
+ return t_uuidGenerator();
+ }
+
+ boost::uuids::string_generator gen;
+ return gen(id);
+}
+
+void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid)
+{
+ string uuidStr;
+
+ if (params) {
+ if (params->count("uuid")) {
+ uuidStr = boost::get<std::string>((*params)["uuid"]);
+ }
+ }
+
+ uuid = getRuleID(uuidStr);
+}
+
void setupLuaRules()
{
g_lua.writeFunction("makeRule", makeRule);
g_lua.registerFunction<string(std::shared_ptr<DNSRule>::*)()>("toString", [](const std::shared_ptr<DNSRule>& rule) { return rule->toString(); });
- g_lua.writeFunction("showResponseRules", []() {
+ g_lua.writeFunction("showResponseRules", [](boost::optional<bool> showUUIDs) {
setLuaNoSideEffect();
- boost::format fmt("%-3d %9d %-50s %s\n");
- g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
int num=0;
- for(const auto& lim : g_resprulactions.getCopy()) {
- string name = lim.first->toString();
- g_outputBuffer += (fmt % num % lim.first->d_matches % name % lim.second->toString()).str();
- ++num;
+ if (showUUIDs.get_value_or(false)) {
+ boost::format fmt("%-3d %-38s %9d %-50s %s\n");
+ g_outputBuffer += (fmt % "#" % "UUID" % "Matches" % "Rule" % "Action").str();
+ for(const auto& lim : g_resprulactions.getCopy()) {
+ string name = lim.d_rule->toString();
+ g_outputBuffer += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ ++num;
+ }
+ }
+ else {
+ boost::format fmt("%-3d %9d %-50s %s\n");
+ g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
+ for(const auto& lim : g_resprulactions.getCopy()) {
+ string name = lim.d_rule->toString();
+ g_outputBuffer += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ ++num;
+ }
}
});
- g_lua.writeFunction("rmResponseRule", [](unsigned int num) {
+ g_lua.writeFunction("rmResponseRule", [](boost::variant<unsigned int, std::string> num) {
setLuaSideEffect();
auto rules = g_resprulactions.getCopy();
- if(num >= rules.size()) {
- g_outputBuffer = "Error: attempt to delete non-existing rule\n";
- return;
+ if (auto str = boost::get<std::string>(&num)) {
+ boost::uuids::string_generator gen;
+ const auto uuid = gen(*str);
+ rules.erase(std::remove_if(rules.begin(),
+ rules.end(),
+ [uuid](const DNSDistResponseRuleAction& a) { return a.d_id == uuid; }),
+ rules.end());
+ }
+ else if (auto pos = boost::get<unsigned int>(&num)) {
+ if (*pos >= rules.size()) {
+ g_outputBuffer = "Error: attempt to delete non-existing rule\n";
+ return;
+ }
+ rules.erase(rules.begin()+*pos);
}
- rules.erase(rules.begin()+num);
g_resprulactions.setState(rules);
});
g_resprulactions.setState(rules);
});
- g_lua.writeFunction("showCacheHitResponseRules", []() {
+ g_lua.writeFunction("showCacheHitResponseRules", [](boost::optional<bool> showUUIDs) {
setLuaNoSideEffect();
- boost::format fmt("%-3d %9d %-50s %s\n");
- g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
int num=0;
- for(const auto& lim : g_cachehitresprulactions.getCopy()) {
- string name = lim.first->toString();
- g_outputBuffer += (fmt % num % lim.first->d_matches % name % lim.second->toString()).str();
- ++num;
+ if (showUUIDs.get_value_or(false)) {
+ boost::format fmt("%-3d %-38s %9d %-50s %s\n");
+ g_outputBuffer += (fmt % "#" % "UUID" % "Matches" % "Rule" % "Action").str();
+ for(const auto& lim : g_cachehitresprulactions.getCopy()) {
+ string name = lim.d_rule->toString();
+ g_outputBuffer += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ ++num;
+ }
+ }
+ else {
+ boost::format fmt("%-3d %9d %-50s %s\n");
+ g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
+ for(const auto& lim : g_cachehitresprulactions.getCopy()) {
+ string name = lim.d_rule->toString();
+ g_outputBuffer += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ ++num;
+ }
}
});
- g_lua.writeFunction("rmCacheHitResponseRule", [](unsigned int num) {
+ g_lua.writeFunction("rmCacheHitResponseRule", [](boost::variant<unsigned int, std::string> num) {
setLuaSideEffect();
auto rules = g_cachehitresprulactions.getCopy();
- if(num >= rules.size()) {
- g_outputBuffer = "Error: attempt to delete non-existing rule\n";
- return;
+ if (auto str = boost::get<std::string>(&num)) {
+ boost::uuids::string_generator gen;
+ const auto uuid = gen(*str);
+ rules.erase(std::remove_if(rules.begin(),
+ rules.end(),
+ [uuid](const DNSDistResponseRuleAction& a) { return a.d_id == uuid; }),
+ rules.end());
+ }
+ else if (auto pos = boost::get<unsigned int>(&num)) {
+ if (*pos >= rules.size()) {
+ g_outputBuffer = "Error: attempt to delete non-existing rule\n";
+ return;
+ }
+ rules.erase(rules.begin()+*pos);
}
- rules.erase(rules.begin()+num);
g_cachehitresprulactions.setState(rules);
});
g_cachehitresprulactions.setState(rules);
});
- g_lua.writeFunction("rmRule", [](unsigned int num) {
+ g_lua.writeFunction("rmRule", [](boost::variant<unsigned int, std::string> num) {
setLuaSideEffect();
auto rules = g_rulactions.getCopy();
- if(num >= rules.size()) {
- g_outputBuffer = "Error: attempt to delete non-existing rule\n";
- return;
+ if (auto str = boost::get<std::string>(&num)) {
+ boost::uuids::string_generator gen;
+ const auto uuid = gen(*str);
+ rules.erase(std::remove_if(rules.begin(),
+ rules.end(),
+ [uuid](const DNSDistRuleAction& a) { return a.d_id == uuid; }),
+ rules.end());
+ }
+ else if (auto pos = boost::get<unsigned int>(&num)) {
+ if (*pos >= rules.size()) {
+ g_outputBuffer = "Error: attempt to delete non-existing rule\n";
+ return;
+ }
+ rules.erase(rules.begin()+*pos);
}
- rules.erase(rules.begin()+num);
g_rulactions.setState(rules);
});
});
});
- g_lua.writeFunction("setRules", [](std::vector< std::pair<int, std::shared_ptr<std::pair<luadnsrule_t, std::shared_ptr<DNSAction> > > > > newruleactions) {
+ g_lua.writeFunction("setRules", [](std::vector<DNSDistRuleAction>& newruleactions) {
setLuaSideEffect();
g_rulactions.modify([newruleactions](decltype(g_rulactions)::value_type& gruleactions) {
gruleactions.clear();
for (const auto& newruleaction : newruleactions) {
- if (newruleaction.second) {
- auto rule=makeRule(newruleaction.second->first);
- gruleactions.push_back({rule, newruleaction.second->second});
+ if (newruleaction.d_action) {
+ auto rule=makeRule(newruleaction.d_rule);
+ gruleactions.push_back({rule, newruleaction.d_action, newruleaction.d_id});
}
}
});
return std::shared_ptr<DNSRule>(new ERCodeRule(rcode));
});
- g_lua.writeFunction("showRules", []() {
- setLuaNoSideEffect();
- boost::format fmt("%-3d %9d %-50s %s\n");
- g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
- int num=0;
- for(const auto& lim : g_rulactions.getCopy()) {
- string name = lim.first->toString();
- g_outputBuffer += (fmt % num % lim.first->d_matches % name % lim.second->toString()).str();
- ++num;
+ g_lua.writeFunction("showRules", [](boost::optional<bool> showUUIDs) {
+ setLuaNoSideEffect();
+ int num=0;
+ if (showUUIDs.get_value_or(false)) {
+ boost::format fmt("%-3d %-38s %9d %-56s %s\n");
+ g_outputBuffer += (fmt % "#" % "UUID" % "Matches" % "Rule" % "Action").str();
+ for(const auto& lim : g_rulactions.getCopy()) {
+ string name = lim.d_rule->toString();
+ g_outputBuffer += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ ++num;
+ }
+ }
+ else {
+ boost::format fmt("%-3d %9d %-50s %s\n");
+ g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
+ for(const auto& lim : g_rulactions.getCopy()) {
+ string name = lim.d_rule->toString();
+ g_outputBuffer += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ ++num;
+ }
}
});
#else
g_outputBuffer="Error: DNSCrypt support is not enabled.\n";
#endif
+
});
g_lua.writeFunction("showDNSCryptBinds", []() {
typedef boost::variant<string, vector<pair<int, string>>, std::shared_ptr<DNSRule>, DNSName, vector<pair<int, DNSName> > > luadnsrule_t;
std::shared_ptr<DNSRule> makeRule(const luadnsrule_t& var);
+typedef std::unordered_map<std::string, boost::variant<std::string> > luaruleparams_t;
+void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid);
typedef NetmaskTree<DynBlock> nmts_t;
for(const auto& a : localRules) {
Json::object rule{
{"id", num++},
- {"matches", (double)a.first->d_matches},
- {"rule", a.first->toString()},
- {"action", a.second->toString()},
- {"action-stats", a.second->getStats()}
+ {"uuid", boost::uuids::to_string(a.d_id)},
+ {"matches", (double)a.d_rule->d_matches},
+ {"rule", a.d_rule->toString()},
+ {"action", a.d_action->toString()},
+ {"action-stats", a.d_action->getStats()}
};
rules.push_back(rule);
}
for(const auto& a : localResponseRules) {
Json::object rule{
{"id", num++},
- {"matches", (double)a.first->d_matches},
- {"rule", a.first->toString()},
- {"action", a.second->toString()},
+ {"uuid", boost::uuids::to_string(a.d_id)},
+ {"matches", (double)a.d_rule->d_matches},
+ {"rule", a.d_rule->toString()},
+ {"action", a.d_action->toString()},
};
responseRules.push_back(rule);
}
for(const auto& a : localCacheHitResponseRules) {
Json::object rule{
{"id", num++},
- {"matches", (double)a.first->d_matches},
- {"rule", a.first->toString()},
- {"action", a.second->toString()},
+ {"uuid", boost::uuids::to_string(a.d_id)},
+ {"matches", (double)a.d_rule->d_matches},
+ {"rule", a.d_rule->toString()},
+ {"action", a.d_action->toString()},
};
cacheHitResponseRules.push_back(rule);
}
#include <systemd/sd-daemon.h>
#endif
-#ifdef HAVE_PROTOBUF
thread_local boost::uuids::random_generator t_uuidGenerator;
-#endif
/* Known sins:
If all downstreams are over QPS, we pick the fastest server */
-GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > > g_rulactions;
-GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > g_resprulactions;
-GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > g_cachehitresprulactions;
+GlobalStateHolder<vector<DNSDistRuleAction> > g_rulactions;
+GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_resprulactions;
+GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cachehitresprulactions;
+
Rings g_rings;
QueryCount g_qcount;
DNSAction::Action action=DNSAction::Action::None;
string ruleresult;
for(const auto& lr : *holders.rulactions) {
- if(lr.first->matches(&dq)) {
- lr.first->d_matches++;
- action=(*lr.second)(&dq, &ruleresult);
+ if(lr.d_rule->matches(&dq)) {
+ lr.d_rule->d_matches++;
+ action=(*lr.d_action)(&dq, &ruleresult);
switch(action) {
case DNSAction::Action::Allow:
return true;
}
-bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSResponse& dr, int* delayMsec)
+bool processResponse(LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, int* delayMsec)
{
DNSResponseAction::Action action=DNSResponseAction::Action::None;
std::string ruleresult;
for(const auto& lr : *localRespRulactions) {
- if(lr.first->matches(&dr)) {
- lr.first->d_matches++;
- action=(*lr.second)(&dr, &ruleresult);
+ if(lr.d_rule->matches(&dr)) {
+ lr.d_rule->d_matches++;
+ action=(*lr.d_action)(&dr, &ruleresult);
switch(action) {
case DNSResponseAction::Action::Allow:
return true;
#include <unordered_map>
#include "tcpiohandler.hh"
-#ifdef HAVE_PROTOBUF
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
-#endif
+#include <boost/uuid/uuid_io.hpp>
void* carbonDumpThread();
uint64_t uptimeOfProcess(const std::string& str);
static constexpr char const *strSep = "\t";
};
-#ifdef HAVE_PROTOBUF
extern thread_local boost::uuids::random_generator t_uuidGenerator;
-#endif
struct DNSQuestion
{
EDNS_HEADER_FLAG_DO = 32768
};
+struct DNSDistRuleAction
+{
+ std::shared_ptr<DNSRule> d_rule;
+ std::shared_ptr<DNSAction> d_action;
+ boost::uuids::uuid d_id;
+};
+
+struct DNSDistResponseRuleAction
+{
+ std::shared_ptr<DNSRule> d_rule;
+ std::shared_ptr<DNSResponseAction> d_action;
+ boost::uuids::uuid d_id;
+};
+
extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
extern DNSAction::Action g_dynBlockAction;
extern GlobalStateHolder<ServerPolicy> g_policy;
extern GlobalStateHolder<servers_t> g_dstates;
extern GlobalStateHolder<pools_t> g_pools;
-extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > > g_rulactions;
-extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > g_resprulactions;
-extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > g_cachehitresprulactions;
+extern GlobalStateHolder<vector<DNSDistRuleAction> > g_rulactions;
+extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_resprulactions;
+extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cachehitresprulactions;
extern GlobalStateHolder<NetmaskGroup> g_ACL;
extern ComboAddress g_serverControl; // not changed during runtime
LocalStateHolder<NetmaskGroup> acl;
LocalStateHolder<ServerPolicy> policy;
- LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > > rulactions;
- LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > cacheHitRespRulactions;
+ LocalStateHolder<vector<DNSDistRuleAction> > rulactions;
+ LocalStateHolder<vector<DNSDistResponseRuleAction> > cacheHitRespRulactions;
LocalStateHolder<servers_t> servers;
LocalStateHolder<NetmaskTree<DynBlock> > dynNMGBlock;
LocalStateHolder<SuffixMatchTree<DynBlock> > dynSMTBlock;
bool responseContentMatches(const char* response, const uint16_t responseLen, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote);
bool processQuery(LocalHolders& holders, DNSQuestion& dq, string& poolname, int* delayMsec, const struct timespec& now);
-bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSResponse& dr, int* delayMsec);
+bool processResponse(LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, int* delayMsec);
bool fixUpResponse(char** response, uint16_t* responseLen, size_t* responseSize, const DNSName& qname, uint16_t origFlags, bool ednsAdded, bool ecsAdded, std::vector<uint8_t>& rewrittenResponse, uint16_t addRoom);
void restoreFlags(struct dnsheader* dh, uint16_t origFlags);
bool checkQueryHeaders(const struct dnsheader* dh);
PDNS_CHECK_NETWORK_LIBS
PDNS_CHECK_PTHREAD_NP
-boost_required_version=1.35
PDNS_WITH_PROTOBUF
-AS_IF([test "x$PROTOBUF_LIBS" != "x" -a x"$PROTOC" != "x"],
- # The protobuf code needs boost::uuid, which is available from 1.42 onward
- [AC_MSG_WARN([Bumping minimal Boost requirement to 1.42. To keep the requirement at 1.35, disable protobuf support])
- boost_required_version=1.42]
-)
+boost_required_version=1.42
BOOST_REQUIRE([$boost_required_version])
PDNS_ENABLE_UNIT_TESTS
:property string action: The action taken when the rule matches (e.g. "to pool abuse")
:property dict action-stats: A list of statistics whose content varies depending on the kind of rule
- :property integer id: The identifier (or order) of this rule
+ :property integer id: The order of this rule
:property integer matches: How many times this rule was hit
:property string rule: The matchers for the packet (e.g. "qname==bad-domain1.example., bad-domain2.example.")
+ :property string uuid: The UUID of this rule
.. json:object:: ResponseRule
For Rules related to the incoming query:
-.. function:: addAction(DNSrule, action)
+.. function:: addAction(DNSrule, action [, options])
+
+ .. versionchanged:: 1.3.0
+ Added the optional parameter ``options``.
Add a Rule and Action to the existing rules.
:param DNSrule rule: A 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.
.. function:: clearRules()
:param int from: Rule number to move
:param int to: Location to more the Rule to
-.. function:: newRuleAction(rule, action)
+.. function:: newRuleAction(rule, action[, options])
+
+ .. versionchanged:: 1.3.0
+ Added the optional parameter ``options``.
Return a pair of DNS Rule and DNS Action, to be used with :func:`setRules`.
:param Rule rule: A `Rule <#traffic-matching>`_
:param Action action: The `Action <#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.
.. function:: setRules(rules)
:param [RuleAction] rules: A list of RuleActions
-.. function:: showRules()
+.. function:: showRules([showUUIDs])
+
+ Show all defined rules for queries, optionally displaying their UUIDs.
- Show all defined rules for queries.
+ :param bool showUUIDs: Whether to display the UUIDs, defaults to false
.. function:: topRule()
.. function:: rmRule(n)
- Remove rule ``n``.
+ .. versionchanged:: 1.3.0
+ ``id`` can now be an UUID.
- :param int n: Rule number to remove
+ Remove rule ``id``.
+
+ :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
For Rules related to responses:
-.. function:: addResponseAction(DNSRule, action)
+.. function:: addResponseAction(DNSRule, action [, options])
+
+ .. versionchanged:: 1.3.0
+ Added the optional parameter ``options``.
Add a Rule and Action for responses to the existing rules.
:param DNSRule: A 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.
.. function:: mvResponseRule(from, to)
.. function:: rmResponseRule(n)
- Remove response rule ``n``.
+ .. versionchanged:: 1.3.0
+ ``id`` can now be an UUID.
- :param int n: Rule number to remove
+ Remove response rule ``id``.
+
+ :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
+
+.. function:: showResponseRules([showUUIDs])
-.. function:: showResponseRules()
+ Show all defined response rules, optionally displaying their UUIDs.
- Show all defined response rules.
+ :param bool showUUIDs: Whether to display the UUIDs, defaults to false
.. function:: topResponseRule()
Functions for manipulation Cache Hit Rules:
-.. function:: addCacheHitAction(DNSRule, action)
+.. function:: addCacheHitResponseAction(DNSRule, action)
.. versionadded:: 1.2.0
- Add a Rule and Action for Cache Hits to the existing rules.
+ .. versionchanged:: 1.3.0
+ Added the optional parameter ``options``.
+
+ Add a Rule and ResponseAction for Cache Hits to the existing rules.
:param DNSRule: A 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.
.. function:: mvCacheHitResponseRule(from, to)
:param int from: Rule number to move
:param int to: Location to more the Rule to
-.. function:: rmCacheHitResponseRule(n)
+.. function:: rmCacheHitResponseRule(id)
.. versionadded:: 1.2.0
- Remove cache hit response rule ``n``.
+ .. versionchanged:: 1.3.0
+ ``id`` can now be an UUID.
+
+ :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
:param int n: Rule number to remove
-.. function:: showCacheHitResponseRules()
+.. function:: showCacheHitResponseRules([showUUIDs])
.. versionadded:: 1.2.0
- Show all defined cache hit response rules.
+ Show all defined cache hit response rules, optionally displaying their UUIDs.
+
+ :param bool showUUIDs: Whether to display the UUIDs, defaults to false
.. function:: topCacheHitResponseRule()
self.assertIn(key, content)
for rule in content['rules']:
- for key in ['id', 'matches', 'rule', 'action']:
+ for key in ['id', 'matches', 'rule', 'action', 'uuid']:
self.assertIn(key, rule)
for key in ['id', 'matches']:
self.assertTrue(rule[key] >= 0)
for rule in content['response-rules']:
- for key in ['id', 'matches', 'rule', 'action']:
+ for key in ['id', 'matches', 'rule', 'action', 'uuid']:
self.assertIn(key, rule)
for key in ['id', 'matches']:
self.assertTrue(rule[key] >= 0)