]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dynmessenger.cc
Merge branch 'master' of github.com:PowerDNS/pdns
[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
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 #include "dynmessenger.hh"
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <cerrno>
24 #include <iostream>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 DynMessenger::DynMessenger(const string &localdir, const string &fname)
29 {
30 d_s=socket(AF_UNIX,SOCK_STREAM,0);
31 Utility::setCloseOnExec(d_s);
32
33 if(d_s<0) {
34 throw PDNSException(string("socket")+strerror(errno));
35 }
36
37 memset(&d_local,0,sizeof(d_local));
38
39 string localname=localdir;
40
41 localname+="/lsockXXXXXX";
42 d_local.sun_family=AF_UNIX;
43 strcpy(d_local.sun_path,localname.c_str());
44
45 if(mkstemp(d_local.sun_path)<0)
46 throw PDNSException("Unable to generate local temporary file: "+string(strerror(errno)));
47
48 unlink(d_local.sun_path);
49
50 if(bind(d_s, (sockaddr*)&d_local,sizeof(d_local))<0) {
51 unlink(d_local.sun_path);
52 throw PDNSException("Unable to bind to local temporary file: "+string(strerror(errno)));
53 }
54
55 if(chmod(d_local.sun_path,0666)<0) { // make sure that pdns can reply!
56 unlink(d_local.sun_path);
57 perror("fchmod");
58 exit(1);
59 }
60
61 memset(&d_remote,0,sizeof(d_remote));
62
63 d_remote.sun_family=AF_UNIX;
64 strcpy(d_remote.sun_path,fname.c_str());
65 if(connect(d_s,(sockaddr*)&d_remote,sizeof(d_remote))<0) {
66 unlink(d_local.sun_path);
67 throw PDNSException("Unable to connect to remote '"+fname+"': "+string(strerror(errno)));
68 }
69
70 }
71
72 DynMessenger::DynMessenger(const ComboAddress& remote, const string &secret)
73 {
74 *d_local.sun_path=0;
75 d_s=socket(AF_INET, SOCK_STREAM,0);
76 Utility::setCloseOnExec(d_s);
77
78 if(d_s<0) {
79 throw PDNSException(string("socket")+strerror(errno));
80 }
81
82 if(connect(d_s, (sockaddr*)&remote, remote.getSocklen())<0) {
83 close(d_s);
84 throw PDNSException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno)));
85 }
86
87 string login=secret+"\n";
88 writen2(d_s, login);
89 }
90
91 DynMessenger::~DynMessenger()
92 {
93 if(*d_local.sun_path && unlink(d_local.sun_path)<0)
94 cerr<<"Warning: unable to unlink local unix domain endpoint: "<<strerror(errno)<<endl;
95 close(d_s);
96 }
97
98 int DynMessenger::send(const string &msg) const
99 {
100 if(writen2(d_s, msg+"\n") < 0) { // sue me
101 perror("sendto");
102 return -1;
103 }
104 return 0;
105 }
106
107 string DynMessenger::receive() const
108 {
109 char buffer[1500];
110
111 int retlen;
112 string answer;
113 for(;;) {
114 retlen=recv(d_s,buffer,sizeof(buffer),0);
115 if(retlen<0)
116 throw PDNSException("Error from remote: "+string(strerror(errno)));
117
118 answer.append(buffer,retlen);
119 if(retlen!=sizeof(buffer))
120 break;
121 }
122
123 return answer;
124 }
125