]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Rough draft of fd passing for rec_control
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 14 Sep 2020 08:14:41 +0000 (10:14 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Mon, 15 Feb 2021 08:09:09 +0000 (09:09 +0100)
pdns/pdns_recursor.cc
pdns/rec_channel.cc
pdns/rec_channel.hh
pdns/rec_channel_rec.cc
pdns/rec_control.cc

index 1f5ee52e3e0cb8275b99cbc80c8025a11953c8f6..fda3a859d876fc8c47c8fbd8b8bed071e3d338c4 100644 (file)
@@ -3898,7 +3898,7 @@ static void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
     RecursorControlParser::func_t* command;
 
     g_log << Logger::Notice << "Received rec_control command '" << msg << "' from control socket" << endl;
-    string answer=rcp.getAnswer(msg, &command);
+    string answer=rcp.getAnswer(fd, msg, &command);
 
     // If we are inside a chroot, we need to strip
     if (!arg()["chroot"].empty()) {
index 303b40cbfa2f4b25a74f38ff9640c9ed724d1a12..8e77f20a6d666624f333bee75f4fe5172bbb5894 100644 (file)
@@ -144,7 +144,42 @@ void RecursorControlChannel::connect(const string& path, const string& fname)
   }
 }
 
-void RecursorControlChannel::send(const std::string& msg, const std::string* remote, unsigned int timeout)
+static void sendfd(int s, int fd, const string* remote)
+{
+  struct msghdr    msg;
+  struct cmsghdr  *cmsg;
+  union {
+    struct cmsghdr hdr;
+    unsigned char    buf[CMSG_SPACE(sizeof(int))];
+  } cmsgbuf;
+  struct iovec io_vector[1];
+  char ch = 'X';
+  io_vector[0].iov_base = &ch;
+  io_vector[0].iov_len = 1;
+
+  memset(&msg, 0, sizeof(msg));
+  if (remote) {
+    msg.msg_name = const_cast<char*>(remote->c_str());
+    msg.msg_namelen = remote->length();
+  }
+  msg.msg_control = &cmsgbuf.buf;
+  msg.msg_controllen = sizeof(cmsgbuf.buf);
+  msg.msg_iov = io_vector;
+  msg.msg_iovlen = 1;
+
+  cmsg = CMSG_FIRSTHDR(&msg);
+  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+  cmsg->cmsg_level = SOL_SOCKET;
+  cmsg->cmsg_type = SCM_RIGHTS;
+  *(int *)CMSG_DATA(cmsg) = fd;
+
+  if (sendmsg(s, &msg, 0) == -1) {
+    throw PDNSException("Unable to send fd message over control channel: "+stringerror());
+  }
+}
+
+void RecursorControlChannel::send(const std::string& msg, const std::string* remote, unsigned int timeout, int fd)
 {
   int ret = waitForRWData(d_fd, false, timeout, 0);
   if(ret == 0) {
@@ -167,6 +202,10 @@ void RecursorControlChannel::send(const std::string& msg, const std::string* rem
   }
   else if(::send(d_fd, msg.c_str(), msg.length(), 0) < 0)
     throw PDNSException("Unable to send message over control channel: "+stringerror());
+
+  if (fd != -1) {
+    sendfd(d_fd, fd, remote);
+  }
 }
 
 string RecursorControlChannel::recv(std::string* remote, unsigned int timeout)
index 2ffccdef87c854ecb53d3e11b6eb9e362247e48c..7337bd93f7c57b87c78df8a25c57770bcdab15b9 100644 (file)
@@ -51,7 +51,7 @@ public:
 
   uint64_t getStat(const std::string& name);
 
-  void send(const std::string& msg, const std::string* remote=nullptr, unsigned int timeout=5);
+  void send(const std::string& msg, const std::string* remote=nullptr, unsigned int timeout=5, int fd = -1);
   std::string recv(std::string* remote=0, unsigned int timeout=5);
 
   int d_fd;
@@ -68,7 +68,7 @@ public:
   }
   static void nop(void){}
   typedef void func_t(void);
-  std::string getAnswer(const std::string& question, func_t** func);
+  std::string getAnswer(int s, const std::string& question, func_t** func);
 };
 
 enum class StatComponent { API, Carbon, RecControl, SNMP };
index 0bcc47238eb868c6db0cd04edf132837a426626d..684eade7d5d171fc8674a7110f1ebc47a21c37e0 100644 (file)
@@ -293,16 +293,55 @@ static string doDumpNSSpeeds(T begin, T end)
   return "dumped "+std::to_string(total)+" records\n";
 }
 
+static int
+getfd(int s)
+{
+  int fd = -1;
+  struct msghdr    msg;
+  struct cmsghdr  *cmsg;
+  union {
+    struct cmsghdr hdr;
+    unsigned char    buf[CMSG_SPACE(sizeof(int))];
+  } cmsgbuf;
+  struct iovec io_vector[1];
+  char ch;
+
+  io_vector[0].iov_base = &ch;
+  io_vector[0].iov_len = 1;
+
+  memset(&msg, 0, sizeof(msg));
+  msg.msg_control = &cmsgbuf.buf;
+  msg.msg_controllen = sizeof(cmsgbuf.buf);
+  msg.msg_iov = io_vector;
+  msg.msg_iovlen = 1;
+
+  if (recvmsg(s, &msg, 0) == -1)
+    throw PDNSException("recvmsg");
+  if ((msg.msg_flags & MSG_TRUNC) || (msg.msg_flags & MSG_CTRUNC))
+    throw PDNSException("control message truncated");
+  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+       cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+    if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
+        cmsg->cmsg_level == SOL_SOCKET &&
+        cmsg->cmsg_type == SCM_RIGHTS) {
+      fd = *(int *)CMSG_DATA(cmsg);
+    }
+  }
+  return fd;
+}
+
 template<typename T>
-static string doDumpCache(T begin, T end)
+static string doDumpCache(int s, T begin, T end)
 {
+
+  int fd = getfd(s);
+  
   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: "+stringerror()+"\n";
   uint64_t total = 0;
@@ -1679,7 +1718,7 @@ static string clearDontThrottleNetmasks(T begin, T end) {
   return ret + "\n";
 }
 
-string RecursorControlParser::getAnswer(const string& question, RecursorControlParser::func_t** command)
+string RecursorControlParser::getAnswer(int s, const string& question, RecursorControlParser::func_t** command)
 {
   *command=nop;
   vector<string> words;
@@ -1775,7 +1814,7 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP
   }
 
   if(cmd=="dump-cache")
-    return doDumpCache(begin, end);
+    return doDumpCache(s, begin, end);
 
   if(cmd=="dump-ednsstatus" || cmd=="dump-edns")
     return doDumpEDNSStatus(begin, end);
index cf5bbecf82d59abe1e6503f541473ce1ec2dac6a..08b553ecf4b556685d66a869d4ac96652f3f989e 100644 (file)
@@ -99,12 +99,16 @@ try
 
   const vector<string>&commands=arg().getCommands();
   string command;
+  int fd = -1;
   for(unsigned int i=0; i< commands.size(); ++i) {
     if(i>0)
       command+=" ";
+    if (commands[i] == "dump-cache") {
+      fd = STDOUT_FILENO; // XXX
+    }
     command+=commands[i];
   }
-  rccS.send(command, nullptr, arg().asNum("timeout"));
+  rccS.send(command, nullptr, arg().asNum("timeout"), fd);
   string receive=rccS.recv(0, arg().asNum("timeout"));
   if(receive.compare(0, 7, "Unknown") == 0) {
     cerr<<receive<<endl;