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()) {
}
}
-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) {
}
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)
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;
}
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 };
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;
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;
}
if(cmd=="dump-cache")
- return doDumpCache(begin, end);
+ return doDumpCache(s, begin, end);
if(cmd=="dump-ednsstatus" || cmd=="dump-edns")
return doDumpEDNSStatus(begin, end);
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;