]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsproxy.cc
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "dnsproxy.hh"
21 #include "ahuexception.hh"
22 #include <sys/types.h>
27 #include "packetcache.hh"
30 extern PacketCache PC
;
32 DNSProxy::DNSProxy(const string
&remote
)
36 parseService(remote
,st
);
38 pthread_mutex_init(&d_lock
,0);
39 d_resanswers
=S
.getPointer("recursing-answers");
40 d_resquestions
=S
.getPointer("recursing-questions");
41 d_udpanswers
=S
.getPointer("udp-answers");
42 if((d_sock
=socket(AF_INET
, SOCK_DGRAM
,0))<0)
43 throw AhuException(string("socket: ")+strerror(errno
));
45 struct sockaddr_in sin
;
46 memset((char *)&sin
, 0, sizeof(sin
));
48 sin
.sin_family
= AF_INET
;
49 sin
.sin_addr
.s_addr
= INADDR_ANY
;
52 sin
.sin_port
= htons(10000+( Utility::random()%50000));
54 if(bind(d_sock
, (struct sockaddr
*)&sin
, sizeof(sin
)) >= 0)
58 Utility::closesocket(d_sock
);
60 throw AhuException(string("binding dnsproxy socket: ")+strerror(errno
));
63 struct sockaddr_in toaddr
;
65 Utility::inet_aton(st
.host
.c_str(),&inp
);
66 toaddr
.sin_addr
.s_addr
=inp
.s_addr
;
68 toaddr
.sin_port
=htons(st
.port
);
69 toaddr
.sin_family
=AF_INET
;
71 if(connect(d_sock
, (sockaddr
*)&toaddr
, sizeof(toaddr
))<0)
72 throw AhuException("Unable to UDP connect to remote nameserver "+st
.host
+" ("+itoa(st
.port
)+"): "+stringerror());
74 d_xor
=Utility::random()&0xffff;
75 L
<<Logger::Error
<<"DNS Proxy launched, local port "<<ntohs(sin
.sin_port
)<<", remote "<<st
.host
<<":"<<st
.port
<<endl
;
81 pthread_create(&tid
,0,&launchhelper
,this);
85 void DNSProxy::onlyFrom(const string
&ips
)
88 stringtok(parts
,ips
,", \t");
89 for(vector
<string
>::const_iterator i
=parts
.begin();
95 /** returns false if p->remote is not allowed to recurse via us */
96 bool DNSProxy::sendPacket(DNSPacket
*p
)
98 if(!d_ng
.empty() && !d_ng
.match((struct sockaddr_in
*)&p
->remote
))
108 memcpy((void *)&ce
.remote
,(void *)&p
->remote
, p
->d_socklen
);
109 ce
.addrlen
= p
->d_socklen
;
110 ce
.outsock
= p
->getSocket();
111 ce
.created
= time( NULL
);
115 p
->spoofID(id
^d_xor
);
117 char *buffer
=const_cast<char *>(p
->getRaw());
119 if(send(d_sock
,buffer
,len
,0)<0) { // zoom
120 L
<<Logger::Error
<<"Unable to send a packet to our recursing backend: "<<stringerror()<<endl
;
126 /** This finds us an unused or stale ID. Does not actually clean the contents */
127 int DNSProxy::getID_locked()
131 i
=d_conntrack
.find(n
);
132 if(i
==d_conntrack
.end()) {
135 else if(i
->second
.created
<time(0)-60) {
136 if(i
->second
.created
)
137 L
<<Logger::Warning
<<"Recursive query for remote "<<
138 sockAddrToString((struct sockaddr_in
*)&i
->second
.remote
, i
->second
.addrlen
)<<" with internal id "<<n
<<
139 " was not answered by backend within timeout, reusing id"<<endl
;
146 void DNSProxy::mainloop(void)
153 len
=recv(d_sock
, buffer
, sizeof(buffer
),0); // answer from our backend
156 L
<<Logger::Error
<<"Error receiving packet from recursor backend: "<<stringerror()<<endl
;
158 L
<<Logger::Error
<<"Error receiving packet from recursor backend, EOF"<<endl
;
160 L
<<Logger::Error
<<"Short packet from recursor backend, "<<len
<<" bytes"<<endl
;
166 DNSPacket::dnsheader
*d
=reinterpret_cast<DNSPacket::dnsheader
*>(buffer
);
169 map_t::iterator i
=d_conntrack
.find(d
->id
^d_xor
);
170 if(i
==d_conntrack
.end()) {
171 L
<<Logger::Error
<<"Discarding untracked packet from recursor backend with id "<<(d
->id
^d_xor
)<<
172 ". Contrack table size="<<d_conntrack
.size()<<endl
;
175 else if(i
->second
.created
==0) {
176 L
<<Logger::Error
<<"Received packet from recursor backend with id "<<(d
->id
^d_xor
)<<" which is a duplicate"<<endl
;
180 sendto(i
->second
.outsock
,buffer
,len
,0,(struct sockaddr
*)&i
->second
.remote
,i
->second
.addrlen
);
191 catch(AhuException
&ae
) {
192 L
<<Logger::Error
<<"Fatal error in DNS proxy: "<<ae
.reason
<<endl
;
194 catch(exception
&e
) {
195 L
<<Logger::Error
<<"Communicator thread died because of STL error: "<<e
.what()<<endl
;
199 L
<< Logger::Error
<< "Caught unknown exception." << endl
;
201 L
<<Logger::Error
<<"Exiting because DNS proxy failed"<<endl
;