]> granicus.if.org Git - pdns/commitdiff
Based on request of Simon Kirby, added ability to listen on multiple addresses.
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 19 Feb 2005 14:38:55 +0000 (14:38 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 19 Feb 2005 14:38:55 +0000 (14:38 +0000)
This commit also removes the last mentions of 'AhuDNS', the very old name of
PowerDNS. It also removes some old documentation. Furthermore, there are some
additional license version clarifications.

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@325 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/dnspacket.cc
pdns/dnspacket.hh
pdns/nameserver.cc
pdns/pdns_recursor.cc

index ba9754d1fa2d17f86a7605313e0230cea3f16576..f92d13bda5b6c7d4384f331fb9534d674f7b6c3f 100644 (file)
@@ -3,9 +3,8 @@
     Copyright (C) 2005  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
+    it under the terms of the GNU General Public License versionm 2 as 
+    published by the Free Software Foundation
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -80,6 +79,7 @@ DNSPacket::DNSPacket(const DNSPacket &orig)
   d_dt=orig.d_dt;
   d_socklen=orig.d_socklen;
   d_compress=orig.d_compress;
+  d_tcp=orig.d_tcp;
   qtype=orig.qtype;
   qclass=orig.qclass;
   qdomain=orig.qdomain;
@@ -1412,6 +1412,7 @@ DNSPacket *DNSPacket::replyPacket() const
   
   r->d_dt=d_dt;
   r->d.qdcount=1;
+  r->d_tcp = d_tcp;
   return r;
 }
 
index 571e3b8ce340d5ae99f9d51ef0b0ffc38dca70d6..8e2445b1832eb1974ba1a060d302e1ee07976919 100644 (file)
@@ -132,7 +132,6 @@ public:
       DNSResourceRecord d_place field */
   void addRecord(const DNSResourceRecord &); 
 
-
   /** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */
   static void fillSOAData(const string &content, SOAData &data);
 
@@ -245,14 +244,14 @@ public:
   QType qtype;  //!< type of the question 8
 
   string qdomain;  //!< qname of the question 4
-
-
+  bool d_tcp;
 private:
   bool d_wrapped; // 1
   bool d_compress; // 1
   u_int16_t d_qlen; // length of the question (including class & type) in this packet 2
-
+  
   int d_socket; // 4
+  
   int findlabel(string &label);
   int toqname(const char *name, string &qname, bool compress = true);
   int toqname(const string &name, string &qname, bool compress = true);
index 6d4153e0fd3650032466b3ac44f119ec0d8a836f..90725262d0a1fc276f29bc666b699244e95e8a0d 100644 (file)
 extern StatBag S;
 
 /** \mainpage 
-    ahudns is a very versatile nameserver that can answer questions from different backends. To implement your
+    PowerDNS is a very versatile nameserver that can answer questions from different backends. To implement your
     own backend, see the documentation for the DNSBackend class.
 
     \section copyright Copyright and License
-    AhuDNS is (C) 2002 PowerDNS BV. It is distributed according to the terms of the General Public License version 2.
+    PowerDNS is (C) 2005 PowerDNS.COM BV. It is distributed according to the terms of the General Public License version 2.
 
     \section overview High level overview
 
@@ -67,16 +67,12 @@ extern StatBag S;
     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
     asking this question. If so, the entire Distributor is shunted, and the answer is sent back *directly*, within a few microseconds.
 
-    In turn, the athread() offers each outgoing packet to the PacketCache for possible inclusion.
-
     \section misc Miscellaneous
     Configuration details are available via the ArgvMap instance arg. Statistics are created by making calls to the StatBag object called S. 
     These statistics are made available via the UeberBackend on the same socket that is used for dynamic module commands.
 
     \section Main Main 
     The main() of PowerDNS can be found in receiver.cc - start reading there for further insights into the operation of the nameserver
-
-
 */
 
 void UDPNameserver::bindIPv4()
index 499f8c75a7dc76abe7475a5ea766a696fcc53b68..59edd6fb4dee7cc10c63711c87e89f0c753c9a27 100644 (file)
@@ -3,9 +3,8 @@
     Copyright (C) 2005  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
+    it under the terms of the GNU General Public License version 2 
+    as published by the Free Software Foundation
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -72,8 +71,8 @@ ArgvMap &arg()
   return theArg;
 }
 static int d_clientsock;
-static int d_serversock;
-static int d_tcpserversock;
+static vector<int> d_udpserversocks;
+static vector<int> d_tcpserversocks;
 
 struct PacketID
 {
@@ -123,8 +122,6 @@ int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::
 }
 
 
-
-
 static void writePid(void)
 {
   string fname=arg()["socket-dir"]+"/"+s_programname+".pid";
@@ -194,8 +191,9 @@ void startDoResolve(void *p)
     }
 
     const char *buffer=R->getData();
-    if(!R->getSocket())
-      sendto(d_serversock,buffer,R->len,0,(struct sockaddr *)(R->remote),R->d_socklen);
+
+    if(!R->d_tcp)
+      sendto(R->getSocket(),buffer,R->len,0,(struct sockaddr *)(R->remote),R->d_socklen);
     else {
       char buf[2];
       buf[0]=R->len/256;
@@ -249,72 +247,82 @@ void makeClientSocket()
   Utility::setNonBlocking(d_clientsock);
 }
 
-void makeTCPServerSocket()
+void makeTCPServerSockets()
 {
-  d_tcpserversock=socket(AF_INET, SOCK_STREAM,0);
-  if(d_tcpserversock<0) 
-    throw AhuException("Making a server socket for resolver: "+stringerror());
-  
-  struct sockaddr_in sin;
-  memset((char *)&sin,0, sizeof(sin));
-  
-  sin.sin_family = AF_INET;
+  vector<string>locals;
+  stringtok(locals,arg()["local-address"]," ,");
 
+  if(locals.empty())
+    throw AhuException("No local address specified");
+  
   if(arg()["local-address"]=="0.0.0.0") {
-    sin.sin_addr.s_addr = INADDR_ANY;
-  }
-  else {
-    if(!IpToU32(arg()["local-address"], &sin.sin_addr.s_addr))
-      throw AhuException("Unable to resolve local address"); 
+    L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
   }
 
-  sin.sin_port = htons(arg().asNum("local-port")); 
-
-  int tmp=1;
-  if(setsockopt(d_tcpserversock,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
-    L<<Logger::Error<<"Setsockopt failed"<<endl;
-    exit(1);  
-  }
-    
-  if (bind(d_tcpserversock, (struct sockaddr *)&sin, sizeof(sin))<0) 
-    throw AhuException("TCP Resolver binding to server socket: "+stringerror());
+  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
+    int fd=socket(AF_INET, SOCK_STREAM,0);
+    if(fd<0) 
+      throw AhuException("Making a server socket for resolver: "+stringerror());
   
-
-  Utility::setNonBlocking(d_tcpserversock);
-
-  listen(d_tcpserversock, 128);
+    struct sockaddr_in sin;
+    memset((char *)&sin,0, sizeof(sin));
+    
+    sin.sin_family = AF_INET;
+    if(!IpToU32(*i, &sin.sin_addr.s_addr))
+      throw AhuException("Unable to resolve local address '"+ *i +"'"); 
+
+    int tmp=1;
+    if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
+      L<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
+      exit(1);  
+    }
+    
+    sin.sin_port = htons(arg().asNum("local-port")); 
+    
+    if (bind(fd, (struct sockaddr *)&sin, sizeof(sin))<0) 
+      throw AhuException("Binding TCP server socket for "+*i+": "+stringerror());
+    
+    Utility::setNonBlocking(fd);
+    listen(fd, 128);
+    d_tcpserversocks.push_back(fd);
+    L<<Logger::Error<<"Listening for TCP queries on "<<inet_ntoa(sin.sin_addr)<<":"<<arg().asNum("local-port")<<endl;
+  }
 }
 
-void makeServerSocket()
+
+void makeUDPServerSockets()
 {
-  d_serversock=socket(AF_INET, SOCK_DGRAM,0);
-  if(d_serversock<0) 
-    throw AhuException("Making a server socket for resolver: "+stringerror());
-  
-  struct sockaddr_in sin;
-  memset((char *)&sin,0, sizeof(sin));
-  
-  sin.sin_family = AF_INET;
+  vector<string>locals;
+  stringtok(locals,arg()["local-address"]," ,");
 
+  if(locals.empty())
+    throw AhuException("No local address specified");
+  
   if(arg()["local-address"]=="0.0.0.0") {
     L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
-    sin.sin_addr.s_addr = INADDR_ANY;
   }
-  else {
-    
-    if(!IpToU32(arg()["local-address"], &sin.sin_addr.s_addr))
-      throw AhuException("Unable to resolve local address"); 
 
-  }
-
-  sin.sin_port = htons(arg().asNum("local-port")); 
+  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
+    int fd=socket(AF_INET, SOCK_DGRAM,0);
+    if(fd<0) 
+      throw AhuException("Making a server socket for resolver: "+stringerror());
+  
+    struct sockaddr_in sin;
+    memset((char *)&sin,0, sizeof(sin));
     
-  if (bind(d_serversock, (struct sockaddr *)&sin, sizeof(sin))<0) 
-    throw AhuException("Resolver binding to server socket: "+stringerror());
-
-  Utility::setNonBlocking(d_serversock);
-
-  L<<Logger::Error<<"Incoming query source port: "<<arg().asNum("local-port")<<endl;
+    sin.sin_family = AF_INET;
+    if(!IpToU32(*i, &sin.sin_addr.s_addr))
+      throw AhuException("Unable to resolve local address '"+ *i +"'"); 
+    
+    sin.sin_port = htons(arg().asNum("local-port")); 
+    
+    if (bind(fd, (struct sockaddr *)&sin, sizeof(sin))<0) 
+      throw AhuException("Resolver binding to server socket for "+*i+": "+stringerror());
+    
+    Utility::setNonBlocking(fd);
+    d_udpserversocks.push_back(fd);
+    L<<Logger::Error<<"Listening for UDP queries on "<<inet_ntoa(sin.sin_addr)<<":"<<arg().asNum("local-port")<<endl;
+  }
 }
 
 
@@ -346,14 +354,12 @@ void usr1Handler(int)
 void doStats(void)
 {
   if(qcounter) {
-    
     L<<Logger::Error<<"stats: "<<qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, "
      <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits";
     L<<Logger::Error<<", outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
     L<<Logger::Error<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
      <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
     L<<Logger::Error<<"queries running: "<<MT->numProcesses()<<endl;
-    
   }
   statsWanted=false;
 }
@@ -442,8 +448,8 @@ int main(int argc, char **argv)
       SyncRes::setLog(true);
     
     makeClientSocket();
-    makeServerSocket();
-    makeTCPServerSocket();
+    makeUDPServerSockets();
+    makeTCPServerSockets();
         
     MT=new MTasker<PacketID,string>(100000);
 
@@ -484,15 +490,21 @@ int main(int argc, char **argv)
       fd_set readfds;
       FD_ZERO( &readfds );
       FD_SET( d_clientsock, &readfds );
-      FD_SET( d_serversock, &readfds );
-      FD_SET( d_tcpserversock, &readfds );
-      int fdmax=max(d_tcpserversock,max(d_clientsock,d_serversock));
+      int fdmax=d_clientsock;
+
       for(vector<TCPConnection>::const_iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) {
        FD_SET(i->fd, &readfds);
        fdmax=max(fdmax,i->fd);
       }
+      for(vector<int>::const_iterator i=d_udpserversocks.begin(); i!=d_udpserversocks.end(); ++i) {
+       FD_SET( *i, &readfds );
+       fdmax=max(fdmax,*i);
+      }
+      for(vector<int>::const_iterator i=d_tcpserversocks.begin(); i!=d_tcpserversocks.end(); ++i) {
+       FD_SET( *i, &readfds );
+       fdmax=max(fdmax,*i);
+      }
 
-      /* this should listen on a TCP port as well for new connections,  */
       int selret = select(  fdmax + 1, &readfds, NULL, NULL, &tv );
       if(selret<=0) 
        if (selret == -1 && errno!=EINTR) 
@@ -523,38 +535,43 @@ int main(int argc, char **argv)
        }
       }
       
-      if(FD_ISSET(d_serversock,&readfds)) { // do we have a new question on udp?
-       d_len=recvfrom(d_serversock, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);    
-       if(d_len<0) 
-         continue;
-       P.setRemote((struct sockaddr *)&fromaddr, addrlen);
-       if(P.parse(data,d_len)<0) {
-         L<<Logger::Error<<"Unparseable packet from remote client "<<P.getRemote()<<endl;
-       }
-       else { 
-         if(P.d.qr)
-           L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
-         else {
-           ++qcounter;
-           P.setSocket(0);
-           MT->makeThread(startDoResolve,(void*)new DNSPacket(P));
 
+      for(vector<int>::const_iterator i=d_udpserversocks.begin(); i!=d_udpserversocks.end(); ++i) {
+       if(FD_ISSET(*i,&readfds)) { // do we have a new question on udp?
+         d_len=recvfrom(*i, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);    
+         if(d_len<0) 
+           continue;
+         P.setRemote((struct sockaddr *)&fromaddr, addrlen);
+         if(P.parse(data,d_len)<0) {
+           L<<Logger::Error<<"Unparseable packet from remote client "<<P.getRemote()<<endl;
+         }
+         else { 
+           if(P.d.qr)
+             L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
+           else {
+             ++qcounter;
+             P.setSocket(*i);
+             P.d_tcp=false;
+             MT->makeThread(startDoResolve,(void*)new DNSPacket(P));
+           }
          }
        }
       }
 
-      if(FD_ISSET(d_tcpserversock,&readfds)) { // do we have a new TCP connection
-       struct sockaddr_in addr;
-       socklen_t addrlen=sizeof(addr);
-       int newsock=accept(d_tcpserversock, (struct sockaddr*)&addr, &addrlen);
-
-       if(newsock>0) {
-         Utility::setNonBlocking(newsock);
-         TCPConnection tc;
-         tc.fd=newsock;
-         tc.state=TCPConnection::BYTE0;
-         tc.remote=addr;
-         tcpconnections.push_back(tc);
+      for(vector<int>::const_iterator i=d_tcpserversocks.begin(); i!=d_tcpserversocks.end(); ++i) { 
+       if(FD_ISSET(*i ,&readfds)) { // do we have a new TCP connection
+         struct sockaddr_in addr;
+         socklen_t addrlen=sizeof(addr);
+         int newsock=accept(*i, (struct sockaddr*)&addr, &addrlen);
+         
+         if(newsock>0) {
+           Utility::setNonBlocking(newsock);
+           TCPConnection tc;
+           tc.fd=newsock;
+           tc.state=TCPConnection::BYTE0;
+           tc.remote=addr;
+           tcpconnections.push_back(tc);
+         }
        }
       }
 
@@ -610,6 +627,7 @@ int main(int argc, char **argv)
              }
              else { 
                P.setSocket(i->fd);
+               P.d_tcp=true;
                P.setRemote((struct sockaddr *)&i->remote,sizeof(i->remote));
                if(P.d.qr)
                  L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;