]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/rec_channel.cc
new stuff for making a separate recursor package
[thirdparty/pdns.git] / pdns / rec_channel.cc
CommitLineData
f6f016d1
BH
1#include "rec_channel.hh"
2#include <sys/socket.h>
3#include <sys/un.h>
4#include <cerrno>
1d5b3ce6
BH
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <iostream>
9
f6f016d1
BH
10#include "ahuexception.hh"
11
12using namespace std;
13
14int RecursorControlChannel::listen(const string& fname)
15{
16 struct sockaddr_un local;
17 d_fd=socket(AF_UNIX,SOCK_DGRAM,0);
18
19 if(d_fd < 0)
20 throw AhuException("Creating UNIX domain socket: "+string(strerror(errno)));
21
22 int tmp=1;
23 if(setsockopt(d_fd, SOL_SOCKET, SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
24 throw AhuException(string("Setsockopt failed: ")+strerror(errno));
25
26 int err=unlink(fname.c_str());
27 if(err < 0 && errno!=ENOENT)
28 throw AhuException("Unable to remove (previous) controlsocket: "+string(strerror(errno)));
29
30 memset(&local,0,sizeof(local));
31 local.sun_family=AF_UNIX;
32 strcpy(local.sun_path, fname.c_str());
33
34 if(bind(d_fd, (sockaddr*)&local,sizeof(local))<0)
35 throw AhuException("Unable to bind to controlsocket: "+string(strerror(errno)));
36
1d5b3ce6
BH
37 return d_fd;
38}
39
40void RecursorControlChannel::connect(const string& fname)
41{
42 struct sockaddr_un local, remote;
43
44 d_fd=socket(AF_UNIX,SOCK_DGRAM,0);
45
46 if(d_fd < 0)
47 throw AhuException("Creating UNIX domain socket: "+string(strerror(errno)));
48
49 int tmp=1;
50 if(setsockopt(d_fd, SOL_SOCKET, SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
51 throw AhuException(string("Setsockopt failed: ")+strerror(errno));
52
53 string localname="./blah";
54
55 local.sun_family=AF_UNIX;
56 strcpy(local.sun_path,localname.c_str());
57
58 int err=unlink(localname.c_str());
59 if(err < 0 && errno!=ENOENT)
60 throw AhuException("Unable to remove local controlsocket: "+string(strerror(errno)));
61
62 if(bind(d_fd, (sockaddr*)&local,sizeof(local))<0) {
63 unlink(local.sun_path);
64 throw AhuException("Unable to bind to local temporary file: "+string(strerror(errno)));
65 }
66
67 if(chmod(local.sun_path,0666)<0) { // make sure that pdns can reply!
68 unlink(local.sun_path);
69 throw AhuException("Unable to chmnod local temporary socket: "+string(strerror(errno)));
70 }
71
72 memset(&remote,0,sizeof(remote));
73
74 remote.sun_family=AF_UNIX;
75 strcpy(remote.sun_path,fname.c_str());
76 if(::connect(d_fd, (sockaddr*)&remote, sizeof(remote)) < 0) {
77 unlink(local.sun_path);
78 throw AhuException("Unable to connect to remote '"+fname+"': "+string(strerror(errno)));
79 }
f6f016d1 80}
1d5b3ce6
BH
81
82void RecursorControlChannel::send(const std::string& msg, const std::string* remote)
83{
84 if(remote) {
85 struct sockaddr_un remoteaddr;
86 memset(&remoteaddr, 0, sizeof(remoteaddr));
87
88 remoteaddr.sun_family=AF_UNIX;
89 strcpy(remoteaddr.sun_path, remote->c_str());
90
91 if(::sendto(d_fd, msg.c_str(), msg.length(), 0, (struct sockaddr*) &remoteaddr, sizeof(remoteaddr) ) < 0)
92 throw AhuException("Unable to send message over control channel: "+string(strerror(errno)));
93 }
94 else if(::send(d_fd, msg.c_str(), msg.length(), 0) < 0)
95 throw AhuException("Unable to send message over control channel: "+string(strerror(errno)));
96}
97
98string RecursorControlChannel::recv(std::string* remote)
99{
100 char buffer[16384];
101 ssize_t len;
102 struct sockaddr_un remoteaddr;
103 socklen_t addrlen=sizeof(remoteaddr);
104
105 if((len=::recvfrom(d_fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&remoteaddr, &addrlen)) < 0)
106 throw AhuException("Unable to receive message over control channel: "+string(strerror(errno)));
107
108 if(remote)
109 *remote=remoteaddr.sun_path;
110
111 return string(buffer, buffer+len);
112}
113