From c1e20fbac9d422dbfea257fb286f2c7f67a2d4f7 Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Fri, 24 Aug 2018 18:11:40 +0000 Subject: [PATCH] Dump the throttle map --- pdns/rec_channel_rec.cc | 31 +++++++++++++++++++ .../docs/manpages/rec_control.1.rst | 14 +++++++++ pdns/syncres.cc | 20 ++++++++++++ pdns/syncres.hh | 14 +++++++++ 4 files changed, 79 insertions(+) diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index ad3cfdfdf..2dc540262 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -194,6 +194,11 @@ static uint64_t* pleaseDumpNSSpeeds(int fd) return new uint64_t(SyncRes::doDumpNSSpeeds(fd)); } +static uint64_t* pleaseDumpThrottleMap(int fd) +{ + return new uint64_t(SyncRes::doDumpThrottleMap(fd)); +} + template string doDumpNSSpeeds(T begin, T end) { @@ -305,6 +310,28 @@ string doDumpRPZ(T begin, T end) return "done\n"; } +template +string doDumpThrottleMap(T begin, T end) +{ + T i=begin; + string fname; + + if(i!=end) + fname=*i; + + int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660); + if(fd < 0) + return "Error opening dump file for writing: "+string(strerror(errno))+"\n"; + uint64_t total = 0; + try { + total = broadcastAccFunction(boost::bind(pleaseDumpThrottleMap, fd)); + } + catch(...){} + + close(fd); + return "dumped "+std::to_string(total)+" records\n"; +} + uint64_t* pleaseWipeCache(const DNSName& canon, bool subtree) { return new uint64_t(t_RC->doWipeCache(canon, subtree)); @@ -1250,6 +1277,7 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP "dump-edns [status] dump EDNS status to the named file\n" "dump-nsspeeds dump nsspeeds statistics to the named file\n" "dump-rpz dump the content of a RPZ zone to the named file\n" +"dump-throttlemap dump the contents of the throttle to the named file\n" "get [key1] [key2] .. get specific statistics\n" "get-all get all statistics\n" "get-ntas get all configured Negative Trust Anchors\n" @@ -1321,6 +1349,9 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP return doDumpRPZ(begin, end); } + if(cmd=="dump-throttlemap") + return doDumpThrottleMap(begin, end); + if(cmd=="wipe-cache" || cmd=="flushname") return doWipeCache(begin, end); diff --git a/pdns/recursordist/docs/manpages/rec_control.1.rst b/pdns/recursordist/docs/manpages/rec_control.1.rst index cc4b1cd7a..fb3b1d230 100644 --- a/pdns/recursordist/docs/manpages/rec_control.1.rst +++ b/pdns/recursordist/docs/manpages/rec_control.1.rst @@ -123,6 +123,20 @@ dump-rpz *ZONE NAME* *FILE NAME* rec_control dump-rpz ZONE_NAME /tmp/file mv /proc/$(pidof pdns_recursor)/root/tmp/file /tmp/filename +dump-throttlemap *FILENAME* + Dump the contents of the throttle map to the *FILENAME* mentioned. + This file should not exist already, PowerDNS will refuse to + overwrite it otherwise. While dumping, the recursor will not answer + questions. + + .. note:: + + :program:`pdns_recursor` often runs in a chroot. You can + retrieve the file using:: + + rec_control dump-rpz ZONE_NAME /tmp/file + mv /proc/$(pidof pdns_recursor)/root/tmp/file /tmp/filename + get *STATISTIC* [*STATISTIC*]... Retrieve a statistic. For items that can be queried, see :doc:`../metrics` diff --git a/pdns/syncres.cc b/pdns/syncres.cc index fd2d0dfab..c473ff03d 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -388,6 +388,26 @@ uint64_t SyncRes::doDumpNSSpeeds(int fd) return count; } +uint64_t SyncRes::doDumpThrottleMap(int fd) +{ + FILE* fp=fdopen(dup(fd), "w"); + if(!fp) + return 0; + fprintf(fp, "; throttle map dump follows\n"); + fprintf(fp, "; remote IP, DNSName, QType\n"); + uint64_t count=0; + + for(const auto& i : t_sstorage.throttle.getThrottleTuples()) + { + count++; + // remote IP, dns name, qtype + fprintf(fp, "%s %s %d", i.get<0>().toLogString().c_str(), i.get<1>().toString().c_str(), i.get<2>()); + fprintf(fp, "\n"); + } + fclose(fp); + return count; +} + /* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records so that if there are RRSIGs for a name, we'll have them. diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 3fc515d79..94859b600 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -120,10 +120,23 @@ public: return (unsigned int)d_cont.size(); } + typedef std::vector > throttles_t; + throttles_t getThrottleTuples() { + throttles_t ret; + ret.reserve(d_cont.size()); + + for(const auto& i : d_cont) { + ret.push_back(i.first); + } + + return ret; + } + void clear() { d_cont.clear(); } + private: unsigned int d_limit; time_t d_ttl; @@ -393,6 +406,7 @@ public: } static void doEDNSDumpAndClose(int fd); static uint64_t doDumpNSSpeeds(int fd); + static uint64_t doDumpThrottleMap(int fd); static int getRootNS(struct timeval now, asyncresolve_t asyncCallback); static void clearDelegationOnly() { -- 2.40.0