]> granicus.if.org Git - pdns/commitdiff
reinstate windows 'service' support - untested
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 30 Apr 2006 11:34:16 +0000 (11:34 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 30 Apr 2006 11:34:16 +0000 (11:34 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@809 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/ntservice.hh
pdns/pdns_recursor.cc
pdns/recursorservice.cc
pdns/singleton.hh
pdns/win32_mtasker.cc

index 64fb9f8975afe83dc87b578ec7483c5c503b661e..1b21eefa9ebbb5cdf68b350fcc23f45a1c1ecf9e 100644 (file)
@@ -24,9 +24,7 @@
 
 #ifndef NTSERVICE_HH
 #define NTSERVICE_HH
-
-#define WINDOWS_LEAN_AND_MEAN
-#include <windows.h>
+#include "utility.hh"
 
 #include <string>
 #include "singleton.hh"
index c1d1e09d3d627f08bb81a750dfa8e2e381709df7..52ab05229b9a9212bc9bbb059f865a7ba6dd03a0 100644 (file)
 */
 
 #ifndef WIN32
-#include <netdb.h>
-#include <unistd.h>
+# include <netdb.h>
+# include <unistd.h>
+#else 
+ #include "ntservice.hh"
+ #include "recursorservice.hh"
 #endif // WIN32
 
 #include "utility.hh" 
@@ -1269,17 +1272,209 @@ void parseAuthAndForwards()
   }
 }
 
+int serviceMain(int argc, char**argv)
+{
+  L.setName("pdns_recursor");
+
+  L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2006 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
+#ifdef __GNUC__
+  L<<", gcc "__VERSION__;
+#endif // add other compilers here
+#ifdef _MSC_VER
+  L<<", MSVC "<<_MSC_VER;
+#endif
+  L<<") starting up"<<endl;
+  
+  L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
+    "This is free software, and you are welcome to redistribute it "
+    "according to the terms of the GPL version 2."<<endl;
+  
+  L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl;
+  
+  if(!::arg()["allow-from"].empty()) {
+    g_allowFrom=new NetmaskGroup;
+    vector<string> ips;
+    stringtok(ips, ::arg()["allow-from"], ", ");
+    L<<Logger::Warning<<"Only allowing queries from: ";
+    for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
+      g_allowFrom->addMask(*i);
+      if(i!=ips.begin())
+       L<<Logger::Warning<<", ";
+      L<<Logger::Warning<<*i;
+    }
+    L<<Logger::Warning<<endl;
+  }
+  else if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
+    L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
+  
+  g_quiet=::arg().mustDo("quiet");
+  if(::arg().mustDo("trace")) {
+    SyncRes::setLog(true);
+    ::arg().set("quiet")="no";
+    g_quiet=false;
+  }
+  
+  
+  if(!::arg()["query-local-address6"].empty()) {
+    SyncRes::s_doIPv6=true;
+    L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl;
+  }
+  
+  SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
+  SyncRes::s_serverID=::arg()["server-id"];
+  if(SyncRes::s_serverID.empty()) {
+    char tmp[128];
+    gethostname(tmp, sizeof(tmp)-1);
+    SyncRes::s_serverID=tmp;
+  }
+  
+  
+  parseAuthAndForwards();
+  
+  g_stats.remotes.resize(::arg().asNum("remotes-ringbuffer-entries"));
+  if(!g_stats.remotes.empty())
+    memset(&g_stats.remotes[0], 0, g_stats.remotes.size() * sizeof(RecursorStats::remotes_t::value_type));
+  g_logCommonErrors=::arg().mustDo("log-common-errors");
+  
+  makeUDPServerSockets();
+  makeTCPServerSockets();
+  
+#ifndef WIN32
+  if(::arg().mustDo("fork")) {
+    fork();
+    L<<Logger::Warning<<"This is forked pid "<<getpid()<<endl;
+  }
+#endif
+  
+  MT=new MTasker<PacketID,string>(100000);
+  makeControlChannelSocket();        
+  PacketID pident;
+  primeHints();    
+  L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
+#ifndef WIN32
+  if(::arg().mustDo("daemon")) {
+    L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
+    L.toConsole(Logger::Critical);
+    L.setLoglevel((Logger::Urgency)(4));
+    
+    daemonize();
+  }
+  signal(SIGUSR1,usr1Handler);
+  signal(SIGUSR2,usr2Handler);
+  signal(SIGPIPE,SIG_IGN);
+  writePid();
+#endif
+  g_fdm=getMultiplexer();
+  
+  for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i) 
+    g_fdm->addReadFD(i->first, i->second);
+  
+  int newgid=0;
+  if(!::arg()["setgid"].empty())
+    newgid=Utility::makeGidNumeric(::arg()["setgid"]);
+  int newuid=0;
+  if(!::arg()["setuid"].empty())
+    newuid=Utility::makeUidNumeric(::arg()["setuid"]);
+  
+#ifndef WIN32
+  if (!::arg()["chroot"].empty()) {
+    if (chroot(::arg()["chroot"].c_str())<0) {
+      L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
+      exit(1);
+    }
+  }
+  
+  Utility::dropPrivs(newuid, newgid);
+  g_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
+#endif 
+  
+  counter=0;
+  unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
+  g_tcpTimeout=::arg().asNum("client-tcp-timeout");
+  
+  g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
+  
+  
+  bool listenOnTCP(true);
+  
+  for(;;) {
+    while(MT->schedule()); // housekeeping, let threads do their thing
+      
+    if(!(counter%500)) {
+      MT->makeThread(houseKeeping,0);
+    }
+
+    if(!(counter%11)) {
+      typedef vector<pair<int, boost::any> > expired_t;
+      expired_t expired=g_fdm->getTimeouts(g_now);
+       
+      for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
+       TCPConnection conn=any_cast<TCPConnection>(i->second);
+       if(conn.state != TCPConnection::DONE) {
+         if(g_logCommonErrors)
+           L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl;
+         g_fdm->removeReadFD(i->first);
+         conn.closeAndCleanup();
+       }
+      }
+    }
+      
+    counter++;
+
+    if(statsWanted) {
+      doStats();
+    }
+
+    Utility::gettimeofday(&g_now, 0);
+    g_fdm->run(&g_now);
+
+    if(listenOnTCP) {
+      if(TCPConnection::s_currentConnections > maxTcpClients) {  // shutdown
+       for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
+         g_fdm->removeReadFD(*i);
+       listenOnTCP=false;
+      }
+    }
+    else {
+      if(TCPConnection::s_currentConnections <= maxTcpClients) {  // reenable
+       for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
+         g_fdm->addReadFD(*i, handleNewTCPQuestion);
+       listenOnTCP=true;
+      }
+    }
+  }
+}
+#ifdef WIN32
+void doWindowsServiceArguments(RecursorService& recursor)
+{
+  if(::arg().mustDo( "register-service" )) {
+    if ( !recursor.registerService( "The PowerDNS Recursor.", true )) {
+      cerr << "Could not register service." << endl;
+      exit( 99 );
+    }
+    
+    exit( 0 );
+  }
+
+  if ( ::arg().mustDo( "unregister-service" )) {
+    recursor.unregisterService();
+    exit( 0 );
+  }
+}
+#endif
+
 int main(int argc, char **argv) 
 {
   reportBasicTypes();
 
   int ret = EXIT_SUCCESS;
 #ifdef WIN32
-    WSADATA wsaData;
-    if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData )) {
-      cerr<<"Unable to initialize winsock\n";
-      exit(1);
-    }
+  RecursorService service;
+  WSADATA wsaData;
+  if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData )) {
+    cerr<<"Unable to initialize winsock\n";
+    exit(1);
+  }
 #endif // WIN32
 
   try {
@@ -1298,6 +1493,12 @@ int main(int argc, char **argv)
     ::arg().set("setuid","If set, change user id to this uid for more security")="";
 #ifdef WIN32
     ::arg().set("quiet","Suppress logging of questions and answers")="off";
+    ::arg().setSwitch( "register-service", "Register the service" )= "no";
+    ::arg().setSwitch( "unregister-service", "Unregister the service" )= "no";
+    ::arg().setSwitch( "ntservice", "Run as service" )= "no";
+    ::arg().setSwitch( "use-ntlog", "Use the NT logging facilities" )= "yes"; 
+    ::arg().setSwitch( "use-logfile", "Use a log file" )= "no"; 
+    ::arg().setSwitch( "logfile", "Filename of the log file" )= "recursor.log"; 
 #else
     ::arg().set("quiet","Suppress logging of questions and answers")="";
 #endif
@@ -1306,7 +1507,6 @@ int main(int argc, char **argv)
     ::arg().set("delegation-only","Which domains we only accept delegations from")="";
     ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
     ::arg().set("query-local-address6","Source IPv6 address for sending queries")="";
-    //    ::arg().set("query-local-port","Source port address for sending queries, defaults to random")="";
     ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
     ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
     ::arg().set("hint-file", "If set, load root hints from this file")="";
@@ -1351,175 +1551,13 @@ int main(int argc, char **argv)
       exit(0);
     }
 
-    L.setName("pdns_recursor");
-
-    L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2006 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
-#ifdef __GNUC__
-    L<<", gcc "__VERSION__;
-#endif // add other compilers here
-#ifdef _MSC_VER
-       L<<", MSVC "<<_MSC_VER;
-#endif
-    L<<") starting up"<<endl;
-
-    L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
-      "This is free software, and you are welcome to redistribute it "
-      "according to the terms of the GPL version 2."<<endl;
-
-    L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl;
-
-    if(!::arg()["allow-from"].empty()) {
-      g_allowFrom=new NetmaskGroup;
-      vector<string> ips;
-      stringtok(ips, ::arg()["allow-from"], ", ");
-      L<<Logger::Warning<<"Only allowing queries from: ";
-      for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
-       g_allowFrom->addMask(*i);
-       if(i!=ips.begin())
-         L<<Logger::Warning<<", ";
-       L<<Logger::Warning<<*i;
-      }
-      L<<Logger::Warning<<endl;
-    }
-    else if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
-      L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
-    
-    g_quiet=::arg().mustDo("quiet");
-    if(::arg().mustDo("trace")) {
-      SyncRes::setLog(true);
-      ::arg().set("quiet")="no";
-      g_quiet=false;
-    }
-
-
-    if(!::arg()["query-local-address6"].empty()) {
-      SyncRes::s_doIPv6=true;
-      L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl;
-    }
-    
-    SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
-    SyncRes::s_serverID=::arg()["server-id"];
-    if(SyncRes::s_serverID.empty()) {
-      char tmp[128];
-      gethostname(tmp, sizeof(tmp)-1);
-      SyncRes::s_serverID=tmp;
-    }
-    
-
-    parseAuthAndForwards();
-
-    g_stats.remotes.resize(::arg().asNum("remotes-ringbuffer-entries"));
-       if(!g_stats.remotes.empty())
-         memset(&g_stats.remotes[0], 0, g_stats.remotes.size() * sizeof(RecursorStats::remotes_t::value_type));
-    g_logCommonErrors=::arg().mustDo("log-common-errors");
-
-    makeUDPServerSockets();
-    makeTCPServerSockets();
-
-#ifndef WIN32
-    if(::arg().mustDo("fork")) {
-      fork();
-      L<<Logger::Warning<<"This is forked pid "<<getpid()<<endl;
-    }
-#endif
-
-    MT=new MTasker<PacketID,string>(100000);
-    makeControlChannelSocket();        
-    PacketID pident;
-    primeHints();    
-    L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
 #ifndef WIN32
-    if(::arg().mustDo("daemon")) {
-      L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
-      L.toConsole(Logger::Critical);
-      L.setLoglevel((Logger::Urgency)(4));
-
-      daemonize();
-    }
-    signal(SIGUSR1,usr1Handler);
-    signal(SIGUSR2,usr2Handler);
-    signal(SIGPIPE,SIG_IGN);
-    writePid();
+    doWindowsServiceArguments(service);
+    serviceMain(argc, argv);
+#else
+    RecursorService::instance()->start( argc, argv, ::arg().mustDo( "ntservice" )); 
 #endif
-    g_fdm=getMultiplexer();
-
-    for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i) 
-      g_fdm->addReadFD(i->first, i->second);
-
-    int newgid=0;
-    if(!::arg()["setgid"].empty())
-      newgid=Utility::makeGidNumeric(::arg()["setgid"]);
-    int newuid=0;
-    if(!::arg()["setuid"].empty())
-      newuid=Utility::makeUidNumeric(::arg()["setuid"]);
-
-#ifndef WIN32
-    if (!::arg()["chroot"].empty()) {
-        if (chroot(::arg()["chroot"].c_str())<0) {
-            L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
-           exit(1);
-       }
-    }
-
-    Utility::dropPrivs(newuid, newgid);
-    g_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
-#endif 
-
-    counter=0;
-    unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
-    g_tcpTimeout=::arg().asNum("client-tcp-timeout");
-
-    g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
-
-
-    bool listenOnTCP(true);
-
-    for(;;) {
-      while(MT->schedule()); // housekeeping, let threads do their thing
-      
-      if(!(counter%500)) {
-       MT->makeThread(houseKeeping,0);
-      }
 
-      if(!(counter%11)) {
-       typedef vector<pair<int, boost::any> > expired_t;
-       expired_t expired=g_fdm->getTimeouts(g_now);
-       
-       for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
-         TCPConnection conn=any_cast<TCPConnection>(i->second);
-         if(conn.state != TCPConnection::DONE) {
-           if(g_logCommonErrors)
-             L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl;
-           g_fdm->removeReadFD(i->first);
-           conn.closeAndCleanup();
-         }
-       }
-      }
-      
-      counter++;
-
-      if(statsWanted) {
-       doStats();
-      }
-
-      Utility::gettimeofday(&g_now, 0);
-      g_fdm->run(&g_now);
-
-      if(listenOnTCP) {
-       if(TCPConnection::s_currentConnections > maxTcpClients) {  // shutdown
-         for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
-           g_fdm->removeReadFD(*i);
-         listenOnTCP=false;
-       }
-      }
-      else {
-       if(TCPConnection::s_currentConnections <= maxTcpClients) {  // reenable
-         for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
-           g_fdm->addReadFD(*i, handleNewTCPQuestion);
-         listenOnTCP=true;
-       }
-      }
-    }
   }
   catch(AhuException &ae) {
     L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
index a7303aab6aae3a70e5890af02a72f5e57bfce2b2..6f95e95f9106c4dda48faf57d23c74656c6a80a8 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2002  PowerDNS.COM BV
+    Copyright (C) 2002 - 2006  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 version 2
@@ -17,7 +17,6 @@
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#include "common_startup.hh"
 #include "recursorservice.hh"
 
 extern int serviceMain( int argc, char *argv[] );
index 5a2482ff1fe86e6d9bbef5141222ea5df5692124..20038b18ec9a126e02d0080160dc73b9b6857fff 100644 (file)
@@ -20,8 +20,6 @@
 #ifndef SINGLETON_HH
 #define SINGLETON_HH
 
-#pragma warning ( disable: 4786 ) 
-
 #define WINDOWS_LEAN_AND_MEAN
 #include <windows.h>
 
index 326fc16b2e3bfaa93c9daad64889f9ca66ef9d43..78c62872aa07cad8d3959b2a26ee31fdb8c45a59 100644 (file)
@@ -248,9 +248,9 @@ template<class Key, class Val>bool MTasker<Key,Val>::schedule()
     time_t now=time(0);
     for(typename waiters_t::const_iterator i=d_waiters.begin();i!=d_waiters.end();) {
       if(i->ttd && i->ttd<now) {
-d_waitstatus=TimeOut;
-SwitchToFiber(i->context);
-d_waiters.erase(i++);                  // removes the waitpoint
+       d_waitstatus=TimeOut;
+       SwitchToFiber(i->context);
+       d_waiters.erase(i++);                  // removes the waitpoint
       }
       else ++i;
     }