]> granicus.if.org Git - pdns/commitdiff
Dump the throttle map
authorphonedph1 <phoned@gmail.com>
Fri, 24 Aug 2018 18:11:40 +0000 (18:11 +0000)
committerphonedph1 <phoned@gmail.com>
Fri, 24 Aug 2018 18:11:40 +0000 (18:11 +0000)
pdns/rec_channel_rec.cc
pdns/recursordist/docs/manpages/rec_control.1.rst
pdns/syncres.cc
pdns/syncres.hh

index ad3cfdfdf0d99d1242b5c7ea3da5f4b6462a7ac0..2dc540262c68c669f0a9b1d5d95d9ab001264442 100644 (file)
@@ -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<typename T>
 string doDumpNSSpeeds(T begin, T end)
 {
@@ -305,6 +310,28 @@ string doDumpRPZ(T begin, T end)
   return "done\n";
 }
 
+template<typename T>
+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<uint64_t>(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] <filename>    dump EDNS status to the named file\n"
 "dump-nsspeeds <filename>         dump nsspeeds statistics to the named file\n"
 "dump-rpz <zone name> <filename>  dump the content of a RPZ zone to the named file\n"
+"dump-throttlemap <filename>      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);
 
index cc4b1cd7ae5605e93a18b81d9c44525c2c779344..fb3b1d2301692d8c29e05b06f1082e9dd86340aa 100644 (file)
@@ -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`
index fd2d0dfab2c0ad7380e1e99f1d1c47a1e6f76ae3..c473ff03d3b6c2f62fc745fb73d2d429ae185924 100644 (file)
@@ -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.
index 3fc515d79c66a809fd60698f3111ecec7cd5583b..94859b6007bbdabd1abc8e3f1366837b49484fd4 100644 (file)
@@ -120,10 +120,23 @@ public:
     return (unsigned int)d_cont.size();
   }
 
+  typedef std::vector<boost::tuple<ComboAddress,DNSName,uint16_t> > 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()
   {