From bc282425088455198a7a99511c75914477d4ed32 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 23:14:51 +0200 Subject: Merging upstream version 1.9.3. Signed-off-by: Daniel Baumann --- dnsdist-lua-rules.cc | 216 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 176 insertions(+), 40 deletions(-) (limited to 'dnsdist-lua-rules.cc') diff --git a/dnsdist-lua-rules.cc b/dnsdist-lua-rules.cc index da309e5..f53b98b 100644 --- a/dnsdist-lua-rules.cc +++ b/dnsdist-lua-rules.cc @@ -22,40 +22,51 @@ #include "dnsdist.hh" #include "dnsdist-lua.hh" #include "dnsdist-rules.hh" +#include "dns_random.hh" -std::shared_ptr makeRule(const luadnsrule_t& var) +std::shared_ptr makeRule(const luadnsrule_t& var, const std::string& calledFrom) { - if (var.type() == typeid(std::shared_ptr)) + if (var.type() == typeid(std::shared_ptr)) { return *boost::get>(&var); + } + bool suffixSeen = false; SuffixMatchNode smn; NetmaskGroup nmg; - auto add=[&](string src) { + auto add = [&nmg, &smn, &suffixSeen](const string& src) { try { nmg.addMask(src); // need to try mask first, all masks are domain names! - } catch(...) { + } catch (...) { + suffixSeen = true; smn.add(DNSName(src)); } }; - if (var.type() == typeid(string)) + if (var.type() == typeid(string)) { add(*boost::get(&var)); - - else if (var.type() == typeid(LuaArray)) - for(const auto& a : *boost::get>(&var)) - add(a.second); - - else if (var.type() == typeid(DNSName)) + } + else if (var.type() == typeid(LuaArray)) { + for (const auto& str : *boost::get>(&var)) { + add(str.second); + } + } + else if (var.type() == typeid(DNSName)) { smn.add(*boost::get(&var)); + } + else if (var.type() == typeid(LuaArray)) { + smn = SuffixMatchNode(); + for (const auto& name : *boost::get>(&var)) { + smn.add(name.second); + } + } - else if (var.type() == typeid(LuaArray)) - for(const auto& a : *boost::get>(&var)) - smn.add(a.second); - - if(nmg.empty()) + if (nmg.empty()) { return std::make_shared(smn); - else - return std::make_shared(nmg, true); + } + if (suffixSeen) { + warnlog("At least one parameter to %s has been parsed as a domain name amongst network masks, and will be ignored!", calledFrom); + } + return std::make_shared(nmg, true); } static boost::uuids::uuid makeRuleID(std::string& id) @@ -83,7 +94,7 @@ void parseRuleParams(boost::optional& params, boost::uuids::uui typedef LuaAssociativeTable > > ruleparams_t; template -static std::string rulesToString(const std::vector& rules, boost::optional vars) +static std::string rulesToString(const std::vector& rules, boost::optional& vars) { int num = 0; bool showUUIDs = false; @@ -116,7 +127,7 @@ static std::string rulesToString(const std::vector& rules, boost::optional -static void showRules(GlobalStateHolder > *someRuleActions, boost::optional vars) { +static void showRules(GlobalStateHolder > *someRuleActions, boost::optional& vars) { setLuaNoSideEffect(); auto rules = someRuleActions->getLocal(); @@ -124,7 +135,7 @@ static void showRules(GlobalStateHolder > *someRuleActions, boost::opt } template -static void rmRule(GlobalStateHolder > *someRuleActions, boost::variant id) { +static void rmRule(GlobalStateHolder > *someRuleActions, const boost::variant& id) { setLuaSideEffect(); auto rules = someRuleActions->getCopy(); if (auto str = boost::get(&id)) { @@ -227,12 +238,93 @@ static std::vector getTopRules(const std::vector& rules, unsigned int top) return results; } +template +static LuaArray toLuaArray(std::vector&& rules) +{ + LuaArray results; + results.reserve(rules.size()); + + size_t pos = 1; + for (auto& rule : rules) { + results.emplace_back(pos, std::move(rule)); + pos++; + } + + return results; +} + +template +static boost::optional getRuleFromSelector(const std::vector& rules, const boost::variant& selector) +{ + if (auto str = boost::get(&selector)) { + /* let's see if this a UUID */ + try { + const auto uuid = getUniqueID(*str); + for (const auto& rule : rules) { + if (rule.d_id == uuid) { + return rule; + } + } + } + catch (const std::exception& e) { + /* a name, then */ + for (const auto& rule : rules) { + if (rule.d_name == *str) { + return rule; + } + } + } + } + else if (auto pos = boost::get(&selector)) { + /* this will throw a std::out_of_range exception if the + supplied position is out of bounds, this is fine */ + return rules.at(*pos); + } + return boost::none; +} + +namespace +{ +std::shared_ptr qnameSuffixRule(const boost::variant> names, boost::optional quiet) +{ + if (names.type() == typeid(string)) { + SuffixMatchNode smn; + smn.add(DNSName(*boost::get(&names))); + return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); + } + + if (names.type() == typeid(LuaArray)) { + SuffixMatchNode smn; + for (const auto& str : *boost::get>(&names)) { + smn.add(DNSName(str.second)); + } + return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); + } + + const auto& smn = *boost::get(&names); + return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); +} +} + +// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold void setupLuaRules(LuaContext& luaCtx) { - luaCtx.writeFunction("makeRule", makeRule); + luaCtx.writeFunction("makeRule", [](const luadnsrule_t& var) -> std::shared_ptr { + return makeRule(var, "makeRule"); + }); luaCtx.registerFunction::*)()const>("toString", [](const std::shared_ptr& rule) { return rule->toString(); }); + luaCtx.registerFunction::*)()const>("getMatches", [](const std::shared_ptr& rule) { return rule->d_matches.load(); }); + + luaCtx.registerFunction(DNSDistRuleAction::*)()const>("getSelector", [](const DNSDistRuleAction& rule) { return rule.d_rule; }); + + luaCtx.registerFunction(DNSDistRuleAction::*)()const>("getAction", [](const DNSDistRuleAction& rule) { return rule.d_action; }); + + luaCtx.registerFunction(DNSDistResponseRuleAction::*)()const>("getSelector", [](const DNSDistResponseRuleAction& rule) { return rule.d_rule; }); + + luaCtx.registerFunction(DNSDistResponseRuleAction::*)()const>("getAction", [](const DNSDistResponseRuleAction& rule) { return rule.d_action; }); + luaCtx.writeFunction("showResponseRules", [](boost::optional vars) { showRules(&g_respruleactions, vars); }); @@ -323,17 +415,22 @@ void setupLuaRules(LuaContext& luaCtx) for (const auto& pair : newruleactions) { const auto& newruleaction = pair.second; if (newruleaction->d_action) { - auto rule = makeRule(newruleaction->d_rule); + 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", [](boost::variant selector) -> boost::optional { + auto rules = g_ruleactions.getLocal(); + return getRuleFromSelector(*rules, selector); + }); + luaCtx.writeFunction("getTopRules", [](boost::optional top) { setLuaNoSideEffect(); auto rules = g_ruleactions.getLocal(); - return getTopRules(*rules, (top ? *top : 10)); + return toLuaArray(getTopRules(*rules, (top ? *top : 10))); }); luaCtx.writeFunction("topRules", [](boost::optional top, boost::optional vars) { @@ -342,10 +439,15 @@ void setupLuaRules(LuaContext& luaCtx) return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars); }); + luaCtx.writeFunction("getCacheHitResponseRule", [](boost::variant selector) -> boost::optional { + auto rules = g_cachehitrespruleactions.getLocal(); + return getRuleFromSelector(*rules, selector); + }); + luaCtx.writeFunction("getTopCacheHitResponseRules", [](boost::optional top) { setLuaNoSideEffect(); auto rules = g_cachehitrespruleactions.getLocal(); - return getTopRules(*rules, (top ? *top : 10)); + return toLuaArray(getTopRules(*rules, (top ? *top : 10))); }); luaCtx.writeFunction("topCacheHitResponseRules", [](boost::optional top, boost::optional vars) { @@ -354,10 +456,15 @@ void setupLuaRules(LuaContext& luaCtx) return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars); }); + luaCtx.writeFunction("getCacheInsertedResponseRule", [](boost::variant selector) -> boost::optional { + auto rules = g_cacheInsertedRespRuleActions.getLocal(); + return getRuleFromSelector(*rules, selector); + }); + luaCtx.writeFunction("getTopCacheInsertedResponseRules", [](boost::optional top) { setLuaNoSideEffect(); auto rules = g_cacheInsertedRespRuleActions.getLocal(); - return getTopRules(*rules, (top ? *top : 10)); + return toLuaArray(getTopRules(*rules, (top ? *top : 10))); }); luaCtx.writeFunction("topCacheInsertedResponseRules", [](boost::optional top, boost::optional vars) { @@ -366,10 +473,15 @@ void setupLuaRules(LuaContext& luaCtx) return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars); }); + luaCtx.writeFunction("getResponseRule", [](boost::variant selector) -> boost::optional { + auto rules = g_respruleactions.getLocal(); + return getRuleFromSelector(*rules, selector); + }); + luaCtx.writeFunction("getTopResponseRules", [](boost::optional top) { setLuaNoSideEffect(); auto rules = g_respruleactions.getLocal(); - return getTopRules(*rules, (top ? *top : 10)); + return toLuaArray(getTopRules(*rules, (top ? *top : 10))); }); luaCtx.writeFunction("topResponseRules", [](boost::optional top, boost::optional vars) { @@ -378,10 +490,15 @@ void setupLuaRules(LuaContext& luaCtx) return rulesToString(getTopRules(*rules, (top ? *top : 10)), vars); }); + luaCtx.writeFunction("getSelfAnsweredResponseRule", [](boost::variant selector) -> boost::optional { + auto rules = g_selfansweredrespruleactions.getLocal(); + return getRuleFromSelector(*rules, selector); + }); + luaCtx.writeFunction("getTopSelfAnsweredResponseRules", [](boost::optional top) { setLuaNoSideEffect(); auto rules = g_selfansweredrespruleactions.getLocal(); - return getTopRules(*rules, (top ? *top : 10)); + return toLuaArray(getTopRules(*rules, (top ? *top : 10))); }); luaCtx.writeFunction("topSelfAnsweredResponseRules", [](boost::optional top, boost::optional vars) { @@ -427,13 +544,26 @@ void setupLuaRules(LuaContext& luaCtx) return std::shared_ptr(new SNIRule(name)); }); - luaCtx.writeFunction("SuffixMatchNodeRule", [](const SuffixMatchNode& smn, boost::optional quiet) { - return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); - }); + luaCtx.writeFunction("SuffixMatchNodeRule", qnameSuffixRule); - luaCtx.writeFunction("NetmaskGroupRule", [](const NetmaskGroup& nmg, boost::optional src, boost::optional quiet) { + luaCtx.writeFunction("NetmaskGroupRule", [](const boost::variant> netmasks, boost::optional src, boost::optional quiet) { + if (netmasks.type() == typeid(string)) { + NetmaskGroup nmg; + nmg.addMask(*boost::get(&netmasks)); return std::shared_ptr(new NetmaskGroupRule(nmg, src ? *src : true, quiet ? *quiet : false)); - }); + } + + if (netmasks.type() == typeid(LuaArray)) { + NetmaskGroup nmg; + for (const auto& str : *boost::get>(&netmasks)) { + nmg.addMask(str.second); + } + return std::shared_ptr(new NetmaskGroupRule(nmg, src ? *src : true, quiet ? *quiet : false)); + } + + const auto& nmg = *boost::get(&netmasks); + return std::shared_ptr(new NetmaskGroupRule(nmg, src ? *src : true, quiet ? *quiet : false)); + }); luaCtx.writeFunction("benchRule", [](std::shared_ptr rule, boost::optional times_, boost::optional suffix_) { setLuaNoSideEffect(); @@ -447,9 +577,9 @@ void setupLuaRules(LuaContext& luaCtx) items.reserve(1000); for (int n = 0; n < 1000; ++n) { struct item i; - i.ids.qname = DNSName(std::to_string(random())); + i.ids.qname = DNSName(std::to_string(dns_random_uint32())); i.ids.qname += suffix; - i.ids.qtype = random() % 0xff; + i.ids.qtype = dns_random(0xff); i.ids.qclass = QClass::IN; i.ids.protocol = dnsdist::Protocol::DoUDP; i.ids.origRemote = ComboAddress("127.0.0.1"); @@ -472,7 +602,7 @@ void setupLuaRules(LuaContext& luaCtx) } } double udiff = sw.udiff(); - g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f usec\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str(); + g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f us\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str(); }); @@ -488,6 +618,8 @@ void setupLuaRules(LuaContext& luaCtx) return std::shared_ptr(new QNameRule(DNSName(qname))); }); + luaCtx.writeFunction("QNameSuffixRule", qnameSuffixRule); + luaCtx.writeFunction("QTypeRule", [](boost::variant str) { uint16_t qtype; if (auto dir = boost::get(&str)) { @@ -596,7 +728,7 @@ void setupLuaRules(LuaContext& luaCtx) }); luaCtx.writeFunction("TagRule", [](const std::string& tag, boost::optional value) { - return std::shared_ptr(new TagRule(tag, value)); + return std::shared_ptr(new TagRule(tag, std::move(value))); }); luaCtx.writeFunction("TimedIPSetRule", []() { @@ -653,10 +785,14 @@ void setupLuaRules(LuaContext& luaCtx) }); luaCtx.writeFunction("LuaFFIPerThreadRule", [](const std::string& code) { - return std::shared_ptr(new LuaFFIPerThreadRule(code)); - }); + return std::shared_ptr(new LuaFFIPerThreadRule(code)); + }); luaCtx.writeFunction("ProxyProtocolValueRule", [](uint8_t type, boost::optional value) { - return std::shared_ptr(new ProxyProtocolValueRule(type, value)); + return std::shared_ptr(new ProxyProtocolValueRule(type, std::move(value))); + }); + + luaCtx.writeFunction("PayloadSizeRule", [](const std::string& comparison, uint16_t size) { + return std::shared_ptr(new PayloadSizeRule(comparison, size)); }); } -- cgit v1.2.3