]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dynmessenger.cc
Merge pull request #3834 from rgacogne/dnsdist-config-tests
[thirdparty/pdns.git] / pdns / dynmessenger.cc
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 - 2008 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
8
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "dynmessenger.hh"
26 #include <cstdio>
27 #include "utility.hh"
28 #include <cstdlib>
29 #include <cstring>
30 #include <cerrno>
31 #include <iostream>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 DynMessenger::DynMessenger(const string &fname,
36 int timeout_sec,
37 int timeout_usec)
38 {
39 d_s=socket(AF_UNIX,SOCK_STREAM,0);
40 setCloseOnExec(d_s);
41
42 if(d_s<0) {
43 throw PDNSException(string("socket")+strerror(errno));
44 }
45
46 try {
47 if(makeUNsockaddr(fname, &d_remote))
48 throw PDNSException("Unable to connect to remote '"+fname+"': Path is not a valid UNIX socket path.");
49
50 struct timeval timeout;
51 timeout.tv_sec = timeout_sec;
52 timeout.tv_usec = timeout_usec;
53
54 if (setsockopt (d_s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
55 throw PDNSException("Unable to set SO_RCVTIMEO option on socket: " + stringerror());
56
57 if (setsockopt (d_s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
58 throw PDNSException("Unable to set SO_SNDTIMEO option on socket: " + stringerror());
59
60 int ret = Utility::timed_connect(d_s,(sockaddr*)&d_remote,sizeof(d_remote), timeout_sec, timeout_usec);
61
62 if (ret == 0)
63 throw TimeoutException("Unable to connect to remote '"+fname+"': "+stringerror());
64 else if (ret < 0)
65 throw PDNSException("Unable to connect to remote '"+fname+"': "+stringerror());
66
67 } catch(...) {
68 close(d_s);
69 d_s=-1;
70 throw;
71 }
72 }
73
74 DynMessenger::DynMessenger(const ComboAddress& remote,
75 const string &secret,
76 int timeout_sec,
77 int timeout_usec)
78 {
79 d_s=socket(AF_INET, SOCK_STREAM,0);
80 setCloseOnExec(d_s);
81
82 if(d_s<0) {
83 throw PDNSException(string("socket")+strerror(errno));
84 }
85
86 try {
87 struct timeval timeout;
88 timeout.tv_sec = timeout_sec;
89 timeout.tv_usec = timeout_usec;
90
91 if (setsockopt (d_s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
92 throw PDNSException("Unable to set SO_RCVTIMEO option on socket: " + stringerror());
93
94 if (setsockopt (d_s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
95 throw PDNSException("Unable to set SO_SNDTIMEO option on socket: " + stringerror());
96
97 int ret = Utility::timed_connect(d_s, (sockaddr*)&remote, remote.getSocklen(), timeout_sec, timeout_usec);
98
99 if (ret == 0)
100 throw TimeoutException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno)));
101 else if (ret < 0)
102 throw PDNSException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno)));
103
104 string login=secret+"\n";
105 writen2(d_s, login);
106 } catch(...) {
107 close(d_s);
108 d_s=-1;
109 throw;
110 }
111 }
112
113 DynMessenger::~DynMessenger()
114 {
115 if (d_s > 0)
116 close(d_s);
117 }
118
119 int DynMessenger::send(const string &msg) const
120 {
121 try {
122 writen2(d_s, msg+"\n");
123 return 0;
124 } catch(std::runtime_error& e) {
125 if (errno == EAGAIN)
126 throw TimeoutException("Error from remote in send(): " + string(e.what()));
127 else
128 throw PDNSException("Error from remote in send(): " + string(e.what()));
129 }
130 }
131
132 string DynMessenger::receive() const
133 {
134 char buffer[1500];
135
136 int retlen;
137 string answer;
138 for(;;) {
139 retlen=recv(d_s,buffer,sizeof(buffer),0);
140 if(retlen<0) {
141 if (errno == EAGAIN)
142 throw TimeoutException("Error from remote in receive(): " + string(strerror(errno)));
143 else
144 throw PDNSException("Error from remote in receive(): " + string(strerror(errno)));
145 }
146
147 answer.append(buffer,retlen);
148 if (retlen == 0)
149 break;
150 }
151
152 return answer;
153 }
154