]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/nameserver.cc
1ef97afe52baa769208f22b0959710c6f3794571
2 Copyright (C) 2002 PowerDNS.COM BV
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // $Id: nameserver.cc,v 1.3 2002/12/10 13:36:26 ahu Exp $
26 #include <sys/types.h>
29 #include "dnsbackend.hh"
30 #include "dnspacket.hh"
31 #include "nameserver.hh"
32 #include "distributor.hh"
34 #include "arguments.hh"
40 ahudns is a very versatile nameserver that can answer questions from different backends. To implement your
41 own backend, see the documentation for the DNSBackend class.
43 \section copyright Copyright and License
44 AhuDNS is (C) 2002 PowerDNS BV.
46 AhuDNS is NOT open source (yet), so treat this code as a trade secret. If it has been supplied to you for evaluation,
47 this does not mean that you can deploy the code!
49 \section overview High level overview
51 AhuDNS is highly threaded, which means that several tasks each have their own process thread. Two of the pivotal
52 threads are the qthread() and the athread().
54 - The qthread() receives questions over the network (via the Nameserver class, which returns DNSPacket objects), and gives them to the Distributor.
55 - The athread() waits on the Distributor to return answers, ready to send back over the network, again via UDPNameserver.
57 The Distributor contains a configurable number of PacketHandler instances, each in its own thread, for connection pooling
59 The PacketHandler implements the RFC1034 algorithm and converts question packets into DNSBackend queries.
61 A DNSBackend is an entity that returns DNSResourceRecord objects in return to explicit questions for domains with a specified QType
63 AhuDNS uses the UeberBackend as its DNSBackend. The UeberBackend by default has no DNSBackends within itself, those are loaded
64 using the dynloader tool. This way DNSBackend implementations can be kept completely separate.
66 If one or more DNSBackends are loaded, the UeberBackend fields the queries to all of them until one answers.
68 \section TCP TCP Operations
70 The TCP operation runs within a single thread called tcpreceiver(), that also queries the PacketHandler.
72 \section Cache Caching
74 On its own, this setup is not suitable for high performance operations. A single DNS query can turn into many DNSBackend questions,
75 each taking many miliseconds to complete. This is why the qthread() first checks the PacketCache to see if an answer is known to a packet
76 asking this question. If so, the entire Distributor is shunted, and the answer is sent back *directly*, within a few microseconds.
78 In turn, the athread() offers each outgoing packet to the PacketCache for possible inclusion.
80 \section misc Miscellaneous
81 Configuration details are available via the ArgvMap instance arg. Statistics are created by making calls to the StatBag object called S.
82 These statistics are made available via the UeberBackend on the same socket that is used for dynamic module commands.
85 The main() of AhuDNS can be found in receiver.cc - start reading there for further insights into the operation of the nameserver
90 void UDPNameserver::bindIPv4()
93 stringtok(locals
,arg()["local-address"]," ,");
96 throw AhuException("No local address specified");
99 for(vector
<string
>::const_iterator i
=locals
.begin();i
!=locals
.end();++i
) {
100 string
localname(*i
);
101 struct sockaddr_in locala
;
103 s
=socket(AF_INET
,SOCK_DGRAM
,0);
105 throw AhuException("Unable to acquire a UDP socket: "+string(strerror(errno
)));
107 memset(&locala
,0,sizeof(locala
));
108 locala
.sin_family
=AF_INET
;
110 if(localname
=="0.0.0.0") {
111 L
<<Logger::Warning
<<"It is advised to bind to explicit addresses with the --local-address option"<<endl
;
113 locala
.sin_addr
.s_addr
= INADDR_ANY
;
118 h
=gethostbyname(localname
.c_str());
120 throw AhuException("Unable to resolve local address");
122 locala
.sin_addr
.s_addr
=*(int*)h
->h_addr
;
125 locala
.sin_port
=htons(arg().asNum("local-port"));
127 if(bind(s
, (sockaddr
*)&locala
,sizeof(locala
))<0) {
128 L
<<Logger::Error
<<"binding to UDP socket: "<<strerror(errno
)<<endl
;
129 throw AhuException("Unable to bind to UDP socket");
131 d_highfd
=max(s
,d_highfd
);
132 d_sockets
.push_back(s
);
133 L
<<Logger::Error
<<"UDP server bound to "<<localname
<<":"<<arg()["local-port"]<<endl
;
138 void UDPNameserver::bindIPv6()
140 #if !WIN32 && HAVE_IPV6
141 vector
<string
>locals
;
142 stringtok(locals
,arg()["local-ipv6"]," ,");
149 for(vector
<string
>::const_iterator i
=locals
.begin();i
!=locals
.end();++i
) {
150 string
localname(*i
);
152 s
=socket(AF_INET6
,SOCK_DGRAM
,0);
154 throw AhuException("Unable to acquire a UDPv6 socket: "+string(strerror(errno
)));
156 if(localname
=="::0") {
157 L
<<Logger::Warning
<<"It is advised to bind to explicit addresses with the --local-ipv6 option"<<endl
;
161 locala
.sin6_port
=ntohs(arg().asNum("local-port"));
162 if(!inet_pton(AF_INET6
, localname
.c_str(), (void *)&locala
.sin6_addr
)) {
165 memset(&hints
,0,sizeof(hints
));
166 hints
.ai_socktype
=SOCK_DGRAM
;
167 hints
.ai_family
=AF_INET6
;
169 if(getaddrinfo(localname
.c_str(),arg()["local-port"].c_str(),&hints
,&addrinfos
))
170 throw AhuException("Unable to resolve local IPv6 address '"+localname
+"'");
171 memcpy(&locala
,addrinfos
->ai_addr
,addrinfos
->ai_addrlen
);
174 if(bind(s
, (sockaddr
*)&locala
, sizeof(locala
))<0) {
175 L
<<Logger::Error
<<"binding to UDP ipv6 socket: "<<strerror(errno
)<<endl
;
176 throw AhuException("Unable to bind to UDP ipv6 socket");
178 d_highfd
=max(s
,d_highfd
);
179 d_sockets
.push_back(s
);
180 L
<<Logger::Error
<<"UDPv6 server bound to "<<localname
<<":"<<arg()["local-port"]<<endl
;
186 UDPNameserver::UDPNameserver()
190 if(!arg()["local-address"].empty())
192 if(!arg()["local-ipv6"].empty())
195 if(arg()["local-address"].empty() && arg()["local-ipv6"].empty())
196 L
<<Logger::Critical
<<"PDNS is deaf and mute! Not listening on any interfaces"<<endl
;
200 void UDPNameserver::send(DNSPacket
*p
)
202 const char *buffer
=p
->getData();
203 DLOG(L
<<Logger::Notice
<<"Sending a packet to "<<inet_ntoa( reinterpret_cast< sockaddr_in
* >(( p
->remote
))->sin_addr
)<<" ("<<p
->len
<<" octets)"<<endl
);
208 if(sendto(p
->getSocket(),buffer
,p
->len
,0,(struct sockaddr
*)(p
->remote
),p
->d_socklen
)<0)
209 L
<<Logger::Error
<<"Error sending reply with sendto (socket="<<p
->getSocket()<<"): "<<strerror(errno
)<<endl
;
214 if(sendto(p
->getSocket(),buffer
,p
->len
,0,(struct sockaddr
*)(p
->remote
),p
->d_socklen
)<0)
215 L
<<Logger::Error
<<"Error sending reply with sendto (socket="<<p
->getSocket()<<"): "<<strerror(errno
)<<endl
;