]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec_control trace-regex: trace to a file or stdout instead of the general log.
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 23 Jan 2023 13:02:09 +0000 (14:02 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 1 Feb 2023 09:08:19 +0000 (10:08 +0100)
--trace stil traces to log

pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/rec_channel_rec.cc
pdns/recursordist/rec_control.cc
pdns/recursordist/syncres.hh

index b9420e7455e9b7afe0cc0ad24cec48e4d5a6ddcf..6eea0fd44411299d549a9b7213c545150abd8198 100644 (file)
@@ -42,6 +42,7 @@
 
 thread_local std::shared_ptr<RecursorLua4> t_pdl;
 thread_local std::shared_ptr<Regex> t_traceRegex;
+thread_local int t_tracefd = -1;
 thread_local ProtobufServersInfo t_protobufServers;
 thread_local ProtobufServersInfo t_outgoingProtobufServers;
 
@@ -837,6 +838,37 @@ static bool isEnabledForUDRs(const std::shared_ptr<std::vector<std::unique_ptr<F
 }
 #endif // HAVE_FSTRM
 
+static void dumpTrace(const string& trace)
+{
+  if (trace.empty()) {
+    return;
+  }
+  int traceFd = dup(t_tracefd);
+  if (traceFd == -1) {
+    int err = errno;
+    SLOG(g_log << Logger::Error << "Could not dup trace file: " << stringerror(err) << endl,
+         g_slog->withName("trace")->error(Logr::Error, err, "Could not dup trace file"));
+    return;
+  }
+  auto filep = std::unique_ptr<FILE, decltype(&fclose)>(fdopen(traceFd, "a"), &fclose);
+  if (!filep) {
+    int err = errno;
+    SLOG(g_log << Logger::Error << "Could not write to trace file: " << stringerror(err) << endl,
+         g_slog->withName("trace")->error(Logr::Error, err, "Could not write to trace file"));
+    close(traceFd);
+    return;
+  }
+  vector<string> lines;
+  boost::split(lines, trace, boost::is_any_of("\n"));
+  int count = 0;
+  for (const string& line : lines) {
+    if (!line.empty())
+      fprintf(filep.get(), "%04d %s\n", ++count, line.c_str());
+  }
+  fprintf(filep.get(), "\n");
+  // fclose by unique_ptr does implicit flush
+}
+
 void startDoResolve(void* p)
 {
   auto dc = std::unique_ptr<DNSComboWriter>(reinterpret_cast<DNSComboWriter*>(p));
@@ -1281,15 +1313,7 @@ void startDoResolve(void* p)
 
   haveAnswer:;
     if (tracedQuery || res == -1 || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail) {
-      string trace(sr.getTrace());
-      if (!trace.empty()) {
-        vector<string> lines;
-        boost::split(lines, trace, boost::is_any_of("\n"));
-        for (const string& line : lines) {
-          if (!line.empty())
-            g_log << Logger::Warning << line << endl;
-        }
-      }
+      dumpTrace(sr.getTrace());
     }
 
     if (res == -1) {
index 4e0b2392f13b8a5815c5f3e3be20df260b4d5c09..3acf1bfb62878ace714ae992220eca816980688d 100644 (file)
@@ -3091,24 +3091,35 @@ RecursorControlChannel::Answer doQueueReloadLuaScript(vector<string>::const_iter
   return broadcastAccFunction<RecursorControlChannel::Answer>(doReloadLuaScript);
 }
 
-static string* pleaseUseNewTraceRegex(const std::string& newRegex)
-try {
-  if (newRegex.empty()) {
-    t_traceRegex.reset();
-    return new string("unset\n");
-  }
-  else {
+static string* pleaseUseNewTraceRegex(const std::string& newRegex, int file)
+{
+  try {
+    if (newRegex.empty()) {
+      t_traceRegex.reset();
+      close(t_tracefd);
+      t_tracefd = -1;
+      return new string("unset\n");
+    }
+    if (file == -1) {
+      return new string("could not dup file\n");
+    }
+    if (t_tracefd != -1) {
+      close(t_tracefd);
+    }
     t_traceRegex = std::make_shared<Regex>(newRegex);
+    t_tracefd = file;
     return new string("ok\n");
   }
-}
-catch (PDNSException& ae) {
-  return new string(ae.reason + "\n");
+  catch (PDNSException& ae) {
+    return new string(ae.reason + "\n");
+  }
 }
 
-string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end)
+string doTraceRegex(FDWrapper file, vector<string>::const_iterator begin, vector<string>::const_iterator end)
 {
-  return broadcastAccFunction<string>([=] { return pleaseUseNewTraceRegex(begin != end ? *begin : ""); });
+  int fileno = dup(file);
+  // Potential dup failure handled in pleaseUseNewTraceRegex()
+  return broadcastAccFunction<string>([=] { return pleaseUseNewTraceRegex(begin != end ? *begin : "", fileno); });
 }
 
 static uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree, uint16_t qtype)
index 9416f4a8d7e7db83d006f7ac98a87c982ff02510..58ee029e2e3461f206c1442fd3691c6d7b564783 100644 (file)
@@ -227,6 +227,7 @@ extern std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to
 extern std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
 extern std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
 extern thread_local std::shared_ptr<Regex> t_traceRegex;
+extern thread_local int t_tracefd;
 extern string g_programname;
 extern string g_pidfname;
 extern RecursorControlChannel g_rcc; // only active in the handler thread
@@ -548,6 +549,7 @@ void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcpSockets
 void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t&);
 
 void makeUDPServerSockets(deferredAdd_t& deferredAdds, Logr::log_t);
+string doTraceRegex(FDWrapper file, vector<string>::const_iterator begin, vector<string>::const_iterator end);
 
 #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10"
 #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10"
index dd8f7f266a20c39b7546025e58bcdd4b7588689c..36dcfb1db2f6bc16802cbb0816649b715f052bfe 100644 (file)
@@ -2215,7 +2215,7 @@ RecursorControlChannel::Answer RecursorControlParser::getAnswer(int s, const str
     return {0, doSetCarbonServer(begin, end)};
   }
   if (cmd == "trace-regex") {
-    return {0, doTraceRegex(begin, end)};
+    return {0, doTraceRegex(begin == end ? FDWrapper(-1) : getfd(s), begin, end)};
   }
   if (cmd == "unload-lua-script") {
     vector<string> empty;
index 2c81aafbad6d9caf30824e8eb57c9ef5c85dfc39..6e2ae91dc191ca769085aa634d86dfa51bc5216f 100644 (file)
@@ -98,6 +98,7 @@ int main(int argc, char** argv)
     "dump-non-resolving",
     "dump-saved-parent-ns-sets",
     "dump-dot-probe-map",
+    "trace-regex",
   };
   try {
     initArguments(argc, argv);
@@ -145,16 +146,22 @@ int main(int argc, char** argv)
         command += " ";
       }
       command += commands[i];
-      if (fileCommands.count(commands[i]) > 0) {
+
+      // special case: trace-regex with no arguments is clear regex
+      auto traceregexClear = command == "trace-regex" && commands.size() == 1;
+
+      if (fileCommands.count(commands[i]) > 0 && !traceregexClear) {
         if (i + 1 < commands.size()) {
           // dump-rpz is different, it also has a zonename as argument
-          if (commands[i] == "dump-rpz") {
+          // trace-regex is different, it also has a regexp as argument
+          if (commands[i] == "dump-rpz" || commands[i] == "trace-regex") {
             if (i + 2 < commands.size()) {
               ++i;
-              command += " " + commands[i]; // add rpzname and continue with filename
+              command += " ";
+              command += commands[i]; // add rpzname/regex and continue with filename
             }
             else {
-              throw PDNSException("Command needs a zone and file argument");
+              throw PDNSException("Command needs two arguments");
             }
           }
           ++i;
index 9e7dd3111c33b5bde52559f804f2d06ca2bef876..50af5bf25ba02d755c39130710435fee10e8c878 100644 (file)
@@ -890,7 +890,6 @@ extern thread_local std::unique_ptr<addrringbuf_t> t_servfailremotes, t_largeans
 extern thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t>>> t_queryring, t_servfailqueryring, t_bogusqueryring;
 extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
 extern thread_local std::shared_ptr<NetmaskGroup> t_allowNotifyFrom;
-string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end);
 extern unsigned int g_networkTimeoutMsec;
 extern uint16_t g_outgoingEDNSBufsize;
 extern std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries;