diff options
Diffstat (limited to '')
-rw-r--r-- | dnsdist-lua-inspection.cc | 158 |
1 files changed, 106 insertions, 52 deletions
diff --git a/dnsdist-lua-inspection.cc b/dnsdist-lua-inspection.cc index 4fac0e3..ba7dfdb 100644 --- a/dnsdist-lua-inspection.cc +++ b/dnsdist-lua-inspection.cc @@ -19,6 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include <fcntl.h> + #include "dnsdist.hh" #include "dnsdist-lua.hh" #include "dnsdist-dynblocks.hh" @@ -136,17 +138,13 @@ static void statNodeRespRing(statvisitor_t visitor, uint64_t seconds) continue; } - bool hit = c.ds.sin4.sin_family == 0; - if (!hit && c.ds.isIPv4() && c.ds.sin4.sin_addr.s_addr == 0 && c.ds.sin4.sin_port == 0) { - hit = true; - } - + const bool hit = c.isACacheHit(); root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, hit, boost::none); } } StatNode::Stat node; - root.visit([visitor](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) { + root.visit([visitor = std::move(visitor)](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) { visitor(*node_, self, children);}, node); } @@ -408,38 +406,59 @@ void setupLuaInspection(LuaContext& luaCtx) } }); - luaCtx.writeFunction("grepq", [](LuaTypeOrArrayOf<std::string> inp, boost::optional<unsigned int> limit) { + luaCtx.writeFunction("grepq", [](LuaTypeOrArrayOf<std::string> inp, boost::optional<unsigned int> limit, boost::optional<LuaAssociativeTable<std::string>> options) { setLuaNoSideEffect(); boost::optional<Netmask> nm; boost::optional<DNSName> dn; - int msec=-1; + int msec = -1; + pdns::UniqueFilePtr outputFile{nullptr}; + + if (options) { + std::string outputFileName; + if (getOptionalValue<std::string>(options, "outputFile", outputFileName) > 0) { + int fd = open(outputFileName.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0600); + if (fd < 0) { + g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n"; + return; + } + outputFile = pdns::UniqueFilePtr(fdopen(fd, "w")); + if (outputFile == nullptr) { + g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n"; + close(fd); + return; + } + } + checkAllParametersConsumed("grepq", options); + } vector<string> vec; - auto str=boost::get<string>(&inp); - if(str) + auto str = boost::get<string>(&inp); + if (str) { vec.push_back(*str); + } else { auto v = boost::get<LuaArray<std::string>>(inp); - for(const auto& a: v) + for (const auto& a: v) { vec.push_back(a.second); + } } - for(const auto& s : vec) { - try - { + for (const auto& s : vec) { + try { nm = Netmask(s); - } - catch(...) { - if(boost::ends_with(s,"ms") && sscanf(s.c_str(), "%ums", &msec)) { + } + catch (...) { + if (boost::ends_with(s,"ms") && sscanf(s.c_str(), "%ums", &msec)) { ; } else { - try { dn=DNSName(s); } - catch(...) - { - g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask"; - return; - } + try { + dn = DNSName(s); + } + catch (...) { + g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask"; + return; + } } } } @@ -477,12 +496,19 @@ void setupLuaInspection(LuaContext& luaCtx) std::multimap<struct timespec, string> out; - boost::format fmt("%-7.1f %-47s %-12s %-12s %-5d %-25s %-5s %-6.1f %-2s %-2s %-2s %-s\n"); - g_outputBuffer+= (fmt % "Time" % "Client" % "Protocol" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str(); + boost::format fmt("%-7.1f %-47s %-12s %-12s %-5d %-25s %-5s %-6.1f %-2s %-2s %-2s %-s\n"); + const auto headLine = (fmt % "Time" % "Client" % "Protocol" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str(); + if (!outputFile) { + g_outputBuffer += headLine; + } + else { + fprintf(outputFile.get(), "%s", headLine.c_str()); + } - if(msec==-1) { - for(const auto& c : qr) { - bool nmmatch=true, dnmatch=true; + if (msec == -1) { + for (const auto& c : qr) { + bool nmmatch = true; + bool dnmatch = true; if (nm) { nmmatch = nm->match(c.requestor); } @@ -502,17 +528,19 @@ void setupLuaInspection(LuaContext& luaCtx) } out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % dnsdist::Protocol(c.protocol).toString() % "" % htons(c.dh.id) % c.name.toString() % qt.toString() % "" % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % ("Question" + extra)).str()); - if(limit && *limit==++num) + if (limit && *limit == ++num) { break; + } } } } - num=0; - + num = 0; string extra; - for(const auto& c : rr) { - bool nmmatch=true, dnmatch=true, msecmatch=true; + for (const auto& c : rr) { + bool nmmatch = true; + bool dnmatch = true; + bool msecmatch = true; if (nm) { nmmatch = nm->match(c.requestor); } @@ -525,13 +553,13 @@ void setupLuaInspection(LuaContext& luaCtx) } } if (msec != -1) { - msecmatch=(c.usec/1000 > (unsigned int)msec); + msecmatch = (c.usec/1000 > (unsigned int)msec); } if (nmmatch && dnmatch && msecmatch) { QType qt(c.qtype); if (!c.dh.rcode) { - extra=". " +std::to_string(htons(c.dh.ancount))+ " answers"; + extra = ". " +std::to_string(htons(c.dh.ancount)) + " answers"; } else { extra.clear(); @@ -556,8 +584,13 @@ void setupLuaInspection(LuaContext& luaCtx) } } - for(const auto& p : out) { - g_outputBuffer+=p.second; + for (const auto& p : out) { + if (!outputFile) { + g_outputBuffer += p.second; + } + else { + fprintf(outputFile.get(), "%s", p.second.c_str()); + } } }); @@ -596,14 +629,14 @@ void setupLuaInspection(LuaContext& luaCtx) return; } - g_outputBuffer = (boost::format("Average response latency: %.02f msec\n") % (0.001*totlat/size)).str(); + g_outputBuffer = (boost::format("Average response latency: %.02f ms\n") % (0.001*totlat/size)).str(); double highest=0; for(auto iter = histo.cbegin(); iter != histo.cend(); ++iter) { highest=std::max(highest, iter->second*1.0); } boost::format fmt("%7.2f\t%s\n"); - g_outputBuffer += (fmt % "msec" % "").str(); + g_outputBuffer += (fmt % "ms" % "").str(); for(auto iter = histo.cbegin(); iter != histo.cend(); ++iter) { int stars = (70.0 * iter->second/highest); @@ -669,7 +702,7 @@ void setupLuaInspection(LuaContext& luaCtx) errorCounters = &f->tlsFrontend->d_tlsCounters; } else if (f->dohFrontend != nullptr) { - errorCounters = &f->dohFrontend->d_tlsCounters; + errorCounters = &f->dohFrontend->d_tlsContext.d_tlsCounters; } if (errorCounters == nullptr) { continue; @@ -691,7 +724,9 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.writeFunction("requestDoHStatesDump", [] { setLuaNoSideEffect(); +#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2) g_dohStatesDumpRequested += g_dohClientThreads->getThreadsCount(); +#endif }); luaCtx.writeFunction("dumpStats", [] { @@ -700,7 +735,7 @@ void setupLuaInspection(LuaContext& luaCtx) boost::format fmt("%-35s\t%+11s"); g_outputBuffer.clear(); - auto entries = *g_stats.entries.read_lock(); + auto entries = *dnsdist::metrics::g_stats.entries.read_lock(); sort(entries.begin(), entries.end(), [](const decltype(entries)::value_type& a, const decltype(entries)::value_type& b) { return a.d_name < b.d_name; @@ -708,16 +743,16 @@ void setupLuaInspection(LuaContext& luaCtx) boost::format flt(" %9.1f"); for (const auto& entry : entries) { string second; - if (const auto& val = boost::get<pdns::stat_t*>(&entry.d_value)) { + if (const auto& val = std::get_if<pdns::stat_t*>(&entry.d_value)) { second = std::to_string((*val)->load()); } - else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&entry.d_value)) { + else if (const auto& adval = std::get_if<pdns::stat_t_trait<double>*>(&entry.d_value)) { second = (flt % (*adval)->load()).str(); } - else if (const auto& dval = boost::get<double*>(&entry.d_value)) { + else if (const auto& dval = std::get_if<double*>(&entry.d_value)) { second = (flt % (**dval)).str(); } - else if (const auto& func = boost::get<DNSDistStats::statfunction_t>(&entry.d_value)) { + else if (const auto& func = std::get_if<dnsdist::metrics::Stats::statfunction_t>(&entry.d_value)) { second = std::to_string((*func)(entry.d_name)); } @@ -780,10 +815,10 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.writeFunction("getRespRing", getRespRing); /* StatNode */ - luaCtx.registerFunction<StatNode, unsigned int()>("numChildren", - [](StatNode& sn) -> unsigned int { - return sn.children.size(); - } ); + luaCtx.registerFunction<unsigned int(StatNode::*)()const>("numChildren", + [](const StatNode& sn) -> unsigned int { + return sn.children.size(); + } ); luaCtx.registerMember("fullname", &StatNode::fullname); luaCtx.registerMember("labelsCount", &StatNode::labelsCount); luaCtx.registerMember("servfails", &StatNode::Stat::servfails); @@ -795,7 +830,7 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.registerMember("hits", &StatNode::Stat::hits); luaCtx.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional<uint64_t> seconds) { - statNodeRespRing(visitor, seconds ? *seconds : 0U); + statNodeRespRing(std::move(visitor), seconds ? *seconds : 0U); }); #endif /* DISABLE_DEPRECATED_DYNBLOCK */ @@ -813,12 +848,17 @@ void setupLuaInspection(LuaContext& luaCtx) }); luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(unsigned int, const std::string&, unsigned int, boost::optional<DNSAction::Action>, DynBlockRulesGroup::smtVisitor_t)>("setSuffixMatchRule", [](std::shared_ptr<DynBlockRulesGroup>& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional<DNSAction::Action> action, DynBlockRulesGroup::smtVisitor_t visitor) { if (group) { - group->setSuffixMatchRule(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, visitor); + group->setSuffixMatchRule(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); } }); luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(unsigned int, const std::string&, unsigned int, boost::optional<DNSAction::Action>, dnsdist_ffi_stat_node_visitor_t)>("setSuffixMatchRuleFFI", [](std::shared_ptr<DynBlockRulesGroup>& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional<DNSAction::Action> action, dnsdist_ffi_stat_node_visitor_t visitor) { if (group) { - group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, visitor); + group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); + } + }); + luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(const dnsdist_ffi_dynamic_block_inserted_hook&)>("setNewBlockInsertedHook", [](std::shared_ptr<DynBlockRulesGroup>& group, const dnsdist_ffi_dynamic_block_inserted_hook& hook) { + if (group) { + group->setNewBlockHook(hook); } }); luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional<DNSAction::Action>, boost::optional<unsigned int>)>("setRCodeRate", [](std::shared_ptr<DynBlockRulesGroup>& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional<DNSAction::Action> action, boost::optional<unsigned int> warningRate) { @@ -836,6 +876,11 @@ void setupLuaInspection(LuaContext& luaCtx) group->setQTypeRate(qtype, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); } }); + luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(double, unsigned int, const std::string&, unsigned int, size_t, double, boost::optional<DNSAction::Action>, boost::optional<double>)>("setCacheMissRatio", [](std::shared_ptr<DynBlockRulesGroup>& group, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, double minimumGlobalCacheHitRatio, boost::optional<DNSAction::Action> action, boost::optional<double> warningRatio) { + if (group) { + group->setCacheMissRatio(ratio, warningRatio ? *warningRatio : 0.0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, minimumNumberOfResponses, minimumGlobalCacheHitRatio); + } + }); luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(uint8_t, uint8_t, uint8_t)>("setMasks", [](std::shared_ptr<DynBlockRulesGroup>& group, uint8_t v4, uint8_t v6, uint8_t port) { if (group) { if (v4 > 32) { @@ -907,5 +952,14 @@ void setupLuaInspection(LuaContext& luaCtx) }); luaCtx.registerFunction("setQuiet", &DynBlockRulesGroup::setQuiet); luaCtx.registerFunction("toString", &DynBlockRulesGroup::toString); + + /* DynBlock object accessors */ + luaCtx.registerMember("reason", &DynBlock::reason); + luaCtx.registerMember("domain", &DynBlock::domain); + luaCtx.registerMember("until", &DynBlock::until); + luaCtx.registerMember<DynBlock, unsigned int>("blocks", [](const DynBlock& block) { return block.blocks.load(); }, [](DynBlock& block, [[maybe_unused]] unsigned int blocks) { }); + luaCtx.registerMember("action", &DynBlock::action); + luaCtx.registerMember("warning", &DynBlock::warning); + luaCtx.registerMember("bpf", &DynBlock::bpf); #endif /* DISABLE_DYNBLOCKS */ } |