]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/rec_channel.cc
4 #include "rec_channel.hh"
6 #include <sys/socket.h>
12 #include <sys/types.h>
16 #include "pdnsexception.hh"
18 #include "namespaces.hh"
20 RecursorControlChannel::RecursorControlChannel()
27 RecursorControlChannel::~RecursorControlChannel()
32 unlink(d_local
.sun_path
);
35 int RecursorControlChannel::listen(const string
& fname
)
37 d_fd
=socket(AF_UNIX
,SOCK_DGRAM
,0);
41 throw PDNSException("Creating UNIX domain socket: "+stringerror());
44 if(setsockopt(d_fd
, SOL_SOCKET
, SO_REUSEADDR
,(char*)&tmp
,sizeof tmp
)<0)
45 throw PDNSException("Setsockopt failed: "+stringerror());
47 int err
=unlink(fname
.c_str());
48 if(err
< 0 && errno
!=ENOENT
)
49 throw PDNSException("Can't remove (previous) controlsocket '"+fname
+"': "+stringerror() + " (try --socket-dir)");
51 if(makeUNsockaddr(fname
, &d_local
))
52 throw PDNSException("Unable to bind to controlsocket, path '"+fname
+"' is not a valid UNIX socket path.");
54 if(bind(d_fd
, (sockaddr
*)&d_local
,sizeof(d_local
))<0)
55 throw PDNSException("Unable to bind to controlsocket '"+fname
+"': "+stringerror());
60 void RecursorControlChannel::connect(const string
& path
, const string
& fname
)
62 struct sockaddr_un remote
;
64 d_fd
=socket(AF_UNIX
,SOCK_DGRAM
,0);
68 throw PDNSException("Creating UNIX domain socket: "+string(strerror(errno
)));
72 if(setsockopt(d_fd
, SOL_SOCKET
, SO_REUSEADDR
,(char*)&tmp
,sizeof tmp
)<0)
73 throw PDNSException("Setsockopt failed: "+stringerror());
75 string localname
=path
+"/lsockXXXXXX";
77 if (makeUNsockaddr(localname
, &d_local
))
78 throw PDNSException("Unable to bind to local temporary file, path '"+localname
+"' is not a valid UNIX socket path.");
80 if(mkstemp(d_local
.sun_path
) < 0)
81 throw PDNSException("Unable to generate local temporary file in directory '"+path
+"': "+stringerror());
83 int err
=unlink(d_local
.sun_path
);
84 if(err
< 0 && errno
!=ENOENT
)
85 throw PDNSException("Unable to remove local controlsocket: "+stringerror());
87 if(bind(d_fd
, (sockaddr
*)&d_local
,sizeof(d_local
))<0)
88 throw PDNSException("Unable to bind to local temporary file: "+stringerror());
90 if(chmod(d_local
.sun_path
,0666)<0) // make sure that pdns can reply!
91 throw PDNSException("Unable to chmod local temporary socket: "+stringerror());
93 string remotename
=path
+"/"+fname
;
94 if (makeUNsockaddr(remotename
, &remote
))
95 throw PDNSException("Unable to connect to controlsocket, path '"+remotename
+"' is not a valid UNIX socket path.");
97 if(::connect(d_fd
, (sockaddr
*)&remote
, sizeof(remote
)) < 0) {
99 unlink(d_local
.sun_path
);
100 throw PDNSException("Unable to connect to remote '"+string(remote
.sun_path
)+"': "+stringerror());
106 d_local
.sun_path
[0]=0;
111 void RecursorControlChannel::send(const std::string
& msg
, const std::string
* remote
)
114 struct sockaddr_un remoteaddr
;
115 memset(&remoteaddr
, 0, sizeof(remoteaddr
));
117 remoteaddr
.sun_family
=AF_UNIX
;
118 strncpy(remoteaddr
.sun_path
, remote
->c_str(), sizeof(remoteaddr
.sun_path
));
119 remoteaddr
.sun_path
[sizeof(remoteaddr
.sun_path
)-1] = '\0';
121 if(::sendto(d_fd
, msg
.c_str(), msg
.length(), 0, (struct sockaddr
*) &remoteaddr
, sizeof(remoteaddr
) ) < 0)
122 throw PDNSException("Unable to send message over control channel '"+string(remoteaddr
.sun_path
)+"': "+string(strerror(errno
)));
124 else if(::send(d_fd
, msg
.c_str(), msg
.length(), 0) < 0)
125 throw PDNSException("Unable to send message over control channel: "+string(strerror(errno
)));
128 string
RecursorControlChannel::recv(std::string
* remote
, unsigned int timeout
)
132 struct sockaddr_un remoteaddr
;
133 socklen_t addrlen
=sizeof(remoteaddr
);
135 int ret
=waitForData(d_fd
, timeout
, 0);
137 throw PDNSException("Timeout waiting for answer from control channel");
139 if( ret
< 0 || (len
=::recvfrom(d_fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&remoteaddr
, &addrlen
)) < 0)
140 throw PDNSException("Unable to receive message over control channel: "+string(strerror(errno
)));
143 *remote
=remoteaddr
.sun_path
;
145 return string(buffer
, buffer
+len
);