]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/rec_channel_rec.cc
Be consistent with reload-zones and clear all caches on (N)TA changes.
[thirdparty/pdns.git] / pdns / rec_channel_rec.cc
index 2d086f1ed426a405248d600698df118106a60688..8420c21cf4e7f41be5ba8d1bf10ef5a7a319d10e 100644 (file)
@@ -1,6 +1,7 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+#include "syncres.hh"
 #include "utility.hh"
 #include "rec_channel.hh"
 #include <boost/bind.hpp>
@@ -10,7 +11,6 @@
 #endif
 #include "misc.hh"
 #include "recursor_cache.hh"
-#include "syncres.hh"
 #include "negcache.hh"
 #include <boost/function.hpp>
 #include <boost/optional.hpp>
 #include "namespaces.hh"
 pthread_mutex_t g_carbon_config_lock=PTHREAD_MUTEX_INITIALIZER;
 
-map<string, const uint32_t*> d_get32bitpointers;
-map<string, const uint64_t*> d_get64bitpointers;
-map<string, const std::atomic<uint64_t>*> d_getatomics;
-map<string, function< uint64_t() > >  d_get64bitmembers;
-pthread_mutex_t d_dynmetricslock = PTHREAD_MUTEX_INITIALIZER;
-map<string, std::atomic<unsigned long>* > d_dynmetrics;
-void addGetStat(const string& name, const uint32_t* place)
+static map<string, const uint32_t*> d_get32bitpointers;
+static map<string, const uint64_t*> d_get64bitpointers;
+static map<string, const std::atomic<uint64_t>*> d_getatomics;
+static map<string, function< uint64_t() > >  d_get64bitmembers;
+static pthread_mutex_t d_dynmetricslock = PTHREAD_MUTEX_INITIALIZER;
+static map<string, std::atomic<unsigned long>* > d_dynmetrics;
+
+static void addGetStat(const string& name, const uint32_t* place)
 {
   d_get32bitpointers[name]=place;
 }
-void addGetStat(const string& name, const uint64_t* place)
-{
-  d_get64bitpointers[name]=place;
-}
 
-void addGetStat(const string& name, const std::atomic<uint64_t>* place)
+static void addGetStat(const string& name, const std::atomic<uint64_t>* place)
 {
   d_getatomics[name]=place;
 }
 
-
-void addGetStat(const string& name, function<uint64_t ()> f ) 
+static void addGetStat(const string& name, function<uint64_t ()> f )
 {
   d_get64bitmembers[name]=f;
 }
 
-
 std::atomic<unsigned long>* getDynMetric(const std::string& str)
 {
   Lock l(&d_dynmetricslock);
@@ -215,7 +210,16 @@ string doDumpNSSpeeds(T begin, T end)
   try {
     total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpNSSpeeds, fd));
   }
-  catch(...){}
+  catch(std::exception& e)
+  {
+    close(fd);
+    return "error dumping NS speeds: "+string(e.what())+"\n";
+  }
+  catch(PDNSException& e)
+  {
+    close(fd);
+    return "error dumping NS speeds: "+e.reason+"\n";
+  }
 
   close(fd);
   return "dumped "+std::to_string(total)+" records\n";
@@ -261,6 +265,46 @@ string doDumpEDNSStatus(T begin, T end)
   return "done\n";
 }
 
+template<typename T>
+string doDumpRPZ(T begin, T end)
+{
+  T i=begin;
+
+  if (i == end) {
+    return "No zone name specified\n";
+  }
+  string zoneName = *i;
+  i++;
+
+  if (i == end) {
+    return "No file name specified\n";
+  }
+  string fname = *i;
+
+  auto luaconf = g_luaconfs.getLocal();
+  const auto zone = luaconf->dfe.getZone(zoneName);
+  if (!zone) {
+    return "No RPZ zone named "+zoneName+"\n";
+  }
+
+  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";
+  }
+
+  FILE* fp = fdopen(fd, "w");
+  if (!fp) {
+    close(fd);
+    return "Error converting file descriptor: "+string(strerror(errno))+"\n";
+  }
+
+  zone->dump(fp);
+  fclose(fp);
+
+  return "done\n";
+}
+
 uint64_t* pleaseWipeCache(const DNSName& canon, bool subtree)
 {
   return new uint64_t(t_RC->doWipeCache(canon, subtree));
@@ -391,7 +435,9 @@ string doAddNTA(T begin, T end)
   g_luaconfs.modify([who, why](LuaConfigItems& lci) {
       lci.negAnchors[who] = why;
       });
+  broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, who, true));
   broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true));
+  broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, who, true));
   return "Added Negative Trust Anchor for " + who.toLogString() + " with reason '" + why + "'\n";
 }
 
@@ -437,7 +483,9 @@ string doClearNTA(T begin, T end)
     g_luaconfs.modify([entry](LuaConfigItems& lci) {
         lci.negAnchors.erase(entry);
       });
+    broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, entry, true));
     broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, entry, true));
+    broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, entry, true));
     if (!first) {
       first = false;
       removed += ",";
@@ -492,7 +540,9 @@ string doAddTA(T begin, T end)
       auto ds = unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what)));
       lci.dsAnchors[who].insert(*ds);
       });
+    broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, who, true));
     broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true));
+    broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, who, true));
     L<<Logger::Warning<<endl;
     return "Added Trust Anchor for " + who.toStringRootDot() + " with data " + what + "\n";
   }
@@ -536,7 +586,9 @@ string doClearTA(T begin, T end)
     g_luaconfs.modify([entry](LuaConfigItems& lci) {
         lci.dsAnchors.erase(entry);
       });
+    broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, entry, true));
     broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, entry, true));
+    broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, entry, true));
     if (!first) {
       first = false;
       removed += ",";
@@ -572,6 +624,24 @@ string setMinimumTTL(T begin, T end)
   return "New minimum TTL: " + std::to_string(SyncRes::s_minimumTTL) + "\n";
 }
 
+template<typename T>
+string setMaxCacheEntries(T begin, T end)
+{
+  if(end-begin != 1) 
+    return "Need to supply new cache size\n";
+  g_maxCacheEntries = pdns_stou(*begin);
+  return "New max cache entries: " + std::to_string(g_maxCacheEntries) + "\n";
+}
+
+template<typename T>
+string setMaxPacketCacheEntries(T begin, T end)
+{
+  if(end-begin != 1) 
+    return "Need to supply new packet cache size\n";
+  g_maxPacketCacheEntries = pdns_stou(*begin);
+  return "New max packetcache entries: " + std::to_string(g_maxPacketCacheEntries) + "\n";
+}
+
 
 static uint64_t getSysTimeMsec()
 {
@@ -775,10 +845,9 @@ extern ResponseStats g_rs;
 
 void registerAllStats()
 {
-  static bool s_init = false;
-  if(s_init)
+  static std::atomic_flag s_init = ATOMIC_FLAG_INIT;
+  if(s_init.test_and_set())
     return;
-  s_init=true;
 
   addGetStat("questions", &g_stats.qcounter);
   addGetStat("ipv6-questions", &g_stats.ipv6qcounter);
@@ -786,7 +855,9 @@ void registerAllStats()
 
   addGetStat("cache-hits", doGetCacheHits);
   addGetStat("cache-misses", doGetCacheMisses); 
-  addGetStat("cache-entries", doGetCacheSize); 
+  addGetStat("cache-entries", doGetCacheSize);
+  addGetStat("max-cache-entries", []() { return g_maxCacheEntries.load(); });
+  addGetStat("max-packetcache-entries", []() { return g_maxPacketCacheEntries.load();}); 
   addGetStat("cache-bytes", doGetCacheBytes); 
   
   addGetStat("packetcache-hits", doGetPacketCacheHits);
@@ -807,6 +878,7 @@ void registerAllStats()
   addGetStat("client-parse-errors", &g_stats.clientParseError);
   addGetStat("server-parse-errors", &g_stats.serverParseError);
   addGetStat("too-old-drops", &g_stats.tooOldDrops);
+  addGetStat("query-pipe-full-drops", &g_stats.queryPipeFullDrops);
 
   addGetStat("answers0-1", &g_stats.answers0_1);
   addGetStat("answers1-10", &g_stats.answers1_10);
@@ -814,6 +886,14 @@ void registerAllStats()
   addGetStat("answers100-1000", &g_stats.answers100_1000);
   addGetStat("answers-slow", &g_stats.answersSlow);
 
+  addGetStat("x-ourtime0-1", &g_stats.ourtime0_1);
+  addGetStat("x-ourtime1-2", &g_stats.ourtime1_2);
+  addGetStat("x-ourtime2-4", &g_stats.ourtime2_4);
+  addGetStat("x-ourtime4-8", &g_stats.ourtime4_8);
+  addGetStat("x-ourtime8-16", &g_stats.ourtime8_16);
+  addGetStat("x-ourtime16-32", &g_stats.ourtime16_32);
+  addGetStat("x-ourtime-slow", &g_stats.ourtimeSlow);
+
   addGetStat("auth4-answers0-1", &g_stats.auth4Answers0_1);
   addGetStat("auth4-answers1-10", &g_stats.auth4Answers1_10);
   addGetStat("auth4-answers10-100", &g_stats.auth4Answers10_100);
@@ -828,6 +908,7 @@ void registerAllStats()
 
 
   addGetStat("qa-latency", doGetAvgLatencyUsec);
+  addGetStat("x-our-latency", []() { return g_stats.avgLatencyOursUsec; });
   addGetStat("unexpected-packets", &g_stats.unexpectedCount);
   addGetStat("case-mismatches", &g_stats.caseMismatchCount);
   addGetStat("spoof-prevents", &g_stats.spoofCount);
@@ -853,6 +934,7 @@ void registerAllStats()
   addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts);
   addGetStat("outgoing4-timeouts", &SyncRes::s_outgoing4timeouts);
   addGetStat("outgoing6-timeouts", &SyncRes::s_outgoing6timeouts);
+  addGetStat("auth-zone-queries", &SyncRes::s_authzonequeries);
   addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries);
   addGetStat("all-outqueries", &SyncRes::s_outqueries);
   addGetStat("ipv6-outqueries", &g_stats.ipv6queries);
@@ -1150,6 +1232,7 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
 "dump-cache <filename>            dump cache contents to the named file\n"
 "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"
 "get [key1] [key2] ..             get specific statistics\n"
 "get-all                          get all statistics\n"
 "get-ntas                         get all configured Negative Trust Anchors\n"
@@ -1165,6 +1248,8 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
 "reload-lua-script [filename]     (re)load Lua script\n"
 "reload-lua-config [filename]     (re)load Lua configuration file\n"
 "reload-zones                     reload all auth and forward zones\n"
+"set-max-cache-entries value      set new maximum cache size\n"
+"set-max-packetcache-entries val  set new maximum packet cache size\n"      
 "set-minimum-ttl value            set minimum-ttl-override\n"
 "set-carbon-server                set a carbon server for telemetry\n"
 "set-dnssec-log-bogus SETTING     enable (SETTING=yes) or disable (SETTING=no) logging of DNSSEC validation failures\n"
@@ -1183,10 +1268,10 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
   if(cmd=="get-all")
     return getAllStats();
 
-  if(cmd=="get") 
+  if(cmd=="get")
     return doGet(begin, end);
-  
-  if(cmd=="get-parameter") 
+
+  if(cmd=="get-parameter")
     return doGetParameter(begin, end);
 
   if(cmd=="quit") {
@@ -1197,25 +1282,29 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
   if(cmd=="version") {
     return getPDNSVersion()+"\n";
   }
-  
+
   if(cmd=="quit-nicely") {
     *command=&doExitNicely;
     return "bye nicely\n";
-  }  
+  }
 
-  if(cmd=="dump-cache") 
+  if(cmd=="dump-cache")
     return doDumpCache(begin, end);
 
-  if(cmd=="dump-ednsstatus" || cmd=="dump-edns") 
+  if(cmd=="dump-ednsstatus" || cmd=="dump-edns")
     return doDumpEDNSStatus(begin, end);
 
   if(cmd=="dump-nsspeeds")
     return doDumpNSSpeeds(begin, end);
 
-  if(cmd=="wipe-cache" || cmd=="flushname") 
+  if(cmd=="dump-rpz") {
+    return doDumpRPZ(begin, end);
+  }
+
+  if(cmd=="wipe-cache" || cmd=="flushname")
     return doWipeCache(begin, end);
 
-  if(cmd=="reload-lua-script") 
+  if(cmd=="reload-lua-script")
     return doQueueReloadLuaScript(begin, end);
 
   if(cmd=="reload-lua-config") {
@@ -1223,7 +1312,9 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
       ::arg().set("lua-config-file") = *begin;
 
     try {
-      loadRecursorLuaConfig(::arg()["lua-config-file"], false);
+      luaConfigDelayedThreads delayedLuaThreads;
+      loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads);
+      startLuaConfigDelayedThreads(delayedLuaThreads);
       L<<Logger::Warning<<"Reloaded Lua configuration file '"<<::arg()["lua-config-file"]<<"', requested via control channel"<<endl;
       return "Reloaded Lua configuration file '"+::arg()["lua-config-file"]+"'\n";
     }
@@ -1235,10 +1326,10 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
     }
   }
 
-  if(cmd=="set-carbon-server") 
+  if(cmd=="set-carbon-server")
     return doSetCarbonServer(begin, end);
 
-  if(cmd=="trace-regex") 
+  if(cmd=="trace-regex")
     return doTraceRegex(begin, end);
 
   if(cmd=="unload-lua-script") {
@@ -1308,6 +1399,13 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
     return reloadAuthAndForwards();
   }
 
+  if(cmd=="set-max-cache-entries") {
+    return setMaxCacheEntries(begin, end);
+  }
+  if(cmd=="set-max-packetcache-entries") {
+    return setMaxPacketCacheEntries(begin, end);
+  }
+  
   if(cmd=="set-minimum-ttl") {
     return setMinimumTTL(begin, end);
   }