Show
Ignore:
Timestamp:
04/30/06 13:34:16 (7 years ago)
Author:
ahu
Message:

reinstate windows 'service' support - untested

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/pdns/pdns/pdns_recursor.cc

    r803 r809  
    1818 
    1919#ifndef WIN32 
    20 #include <netdb.h> 
    21 #include <unistd.h> 
     20# include <netdb.h> 
     21# include <unistd.h> 
     22#else  
     23 #include "ntservice.hh" 
     24 #include "recursorservice.hh" 
    2225#endif // WIN32 
    2326 
     
    12701273} 
    12711274 
     1275int serviceMain(int argc, char**argv) 
     1276{ 
     1277  L.setName("pdns_recursor"); 
     1278 
     1279  L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2006 PowerDNS.COM BV ("<<__DATE__", "__TIME__; 
     1280#ifdef __GNUC__ 
     1281  L<<", gcc "__VERSION__; 
     1282#endif // add other compilers here 
     1283#ifdef _MSC_VER 
     1284  L<<", MSVC "<<_MSC_VER; 
     1285#endif 
     1286  L<<") starting up"<<endl; 
     1287   
     1288  L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. " 
     1289    "This is free software, and you are welcome to redistribute it " 
     1290    "according to the terms of the GPL version 2."<<endl; 
     1291   
     1292  L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl; 
     1293   
     1294  if(!::arg()["allow-from"].empty()) { 
     1295    g_allowFrom=new NetmaskGroup; 
     1296    vector<string> ips; 
     1297    stringtok(ips, ::arg()["allow-from"], ", "); 
     1298    L<<Logger::Warning<<"Only allowing queries from: "; 
     1299    for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) { 
     1300      g_allowFrom->addMask(*i); 
     1301      if(i!=ips.begin()) 
     1302        L<<Logger::Warning<<", "; 
     1303      L<<Logger::Warning<<*i; 
     1304    } 
     1305    L<<Logger::Warning<<endl; 
     1306  } 
     1307  else if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53) 
     1308    L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl; 
     1309   
     1310  g_quiet=::arg().mustDo("quiet"); 
     1311  if(::arg().mustDo("trace")) { 
     1312    SyncRes::setLog(true); 
     1313    ::arg().set("quiet")="no"; 
     1314    g_quiet=false; 
     1315  } 
     1316   
     1317   
     1318  if(!::arg()["query-local-address6"].empty()) { 
     1319    SyncRes::s_doIPv6=true; 
     1320    L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl; 
     1321  } 
     1322   
     1323  SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl"); 
     1324  SyncRes::s_serverID=::arg()["server-id"]; 
     1325  if(SyncRes::s_serverID.empty()) { 
     1326    char tmp[128]; 
     1327    gethostname(tmp, sizeof(tmp)-1); 
     1328    SyncRes::s_serverID=tmp; 
     1329  } 
     1330   
     1331   
     1332  parseAuthAndForwards(); 
     1333   
     1334  g_stats.remotes.resize(::arg().asNum("remotes-ringbuffer-entries")); 
     1335  if(!g_stats.remotes.empty()) 
     1336    memset(&g_stats.remotes[0], 0, g_stats.remotes.size() * sizeof(RecursorStats::remotes_t::value_type)); 
     1337  g_logCommonErrors=::arg().mustDo("log-common-errors"); 
     1338   
     1339  makeUDPServerSockets(); 
     1340  makeTCPServerSockets(); 
     1341   
     1342#ifndef WIN32 
     1343  if(::arg().mustDo("fork")) { 
     1344    fork(); 
     1345    L<<Logger::Warning<<"This is forked pid "<<getpid()<<endl; 
     1346  } 
     1347#endif 
     1348   
     1349  MT=new MTasker<PacketID,string>(100000); 
     1350  makeControlChannelSocket();         
     1351  PacketID pident; 
     1352  primeHints();     
     1353  L<<Logger::Warning<<"Done priming cache with root hints"<<endl; 
     1354#ifndef WIN32 
     1355  if(::arg().mustDo("daemon")) { 
     1356    L<<Logger::Warning<<"Calling daemonize, going to background"<<endl; 
     1357    L.toConsole(Logger::Critical); 
     1358    L.setLoglevel((Logger::Urgency)(4)); 
     1359     
     1360    daemonize(); 
     1361  } 
     1362  signal(SIGUSR1,usr1Handler); 
     1363  signal(SIGUSR2,usr2Handler); 
     1364  signal(SIGPIPE,SIG_IGN); 
     1365  writePid(); 
     1366#endif 
     1367  g_fdm=getMultiplexer(); 
     1368   
     1369  for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)  
     1370    g_fdm->addReadFD(i->first, i->second); 
     1371   
     1372  int newgid=0; 
     1373  if(!::arg()["setgid"].empty()) 
     1374    newgid=Utility::makeGidNumeric(::arg()["setgid"]); 
     1375  int newuid=0; 
     1376  if(!::arg()["setuid"].empty()) 
     1377    newuid=Utility::makeUidNumeric(::arg()["setuid"]); 
     1378   
     1379#ifndef WIN32 
     1380  if (!::arg()["chroot"].empty()) { 
     1381    if (chroot(::arg()["chroot"].c_str())<0) { 
     1382      L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl; 
     1383      exit(1); 
     1384    } 
     1385  } 
     1386   
     1387  Utility::dropPrivs(newuid, newgid); 
     1388  g_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel 
     1389#endif  
     1390   
     1391  counter=0; 
     1392  unsigned int maxTcpClients=::arg().asNum("max-tcp-clients"); 
     1393  g_tcpTimeout=::arg().asNum("client-tcp-timeout"); 
     1394   
     1395  g_maxTCPPerClient=::arg().asNum("max-tcp-per-client"); 
     1396   
     1397   
     1398  bool listenOnTCP(true); 
     1399   
     1400  for(;;) { 
     1401    while(MT->schedule()); // housekeeping, let threads do their thing 
     1402       
     1403    if(!(counter%500)) { 
     1404      MT->makeThread(houseKeeping,0); 
     1405    } 
     1406 
     1407    if(!(counter%11)) { 
     1408      typedef vector<pair<int, boost::any> > expired_t; 
     1409      expired_t expired=g_fdm->getTimeouts(g_now); 
     1410         
     1411      for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) { 
     1412        TCPConnection conn=any_cast<TCPConnection>(i->second); 
     1413        if(conn.state != TCPConnection::DONE) { 
     1414          if(g_logCommonErrors) 
     1415            L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl; 
     1416          g_fdm->removeReadFD(i->first); 
     1417          conn.closeAndCleanup(); 
     1418        } 
     1419      } 
     1420    } 
     1421       
     1422    counter++; 
     1423 
     1424    if(statsWanted) { 
     1425      doStats(); 
     1426    } 
     1427 
     1428    Utility::gettimeofday(&g_now, 0); 
     1429    g_fdm->run(&g_now); 
     1430 
     1431    if(listenOnTCP) { 
     1432      if(TCPConnection::s_currentConnections > maxTcpClients) {  // shutdown 
     1433        for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i) 
     1434          g_fdm->removeReadFD(*i); 
     1435        listenOnTCP=false; 
     1436      } 
     1437    } 
     1438    else { 
     1439      if(TCPConnection::s_currentConnections <= maxTcpClients) {  // reenable 
     1440        for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i) 
     1441          g_fdm->addReadFD(*i, handleNewTCPQuestion); 
     1442        listenOnTCP=true; 
     1443      } 
     1444    } 
     1445  } 
     1446} 
     1447#ifdef WIN32 
     1448void doWindowsServiceArguments(RecursorService& recursor) 
     1449{ 
     1450  if(::arg().mustDo( "register-service" )) { 
     1451    if ( !recursor.registerService( "The PowerDNS Recursor.", true )) { 
     1452      cerr << "Could not register service." << endl; 
     1453      exit( 99 ); 
     1454    } 
     1455     
     1456    exit( 0 ); 
     1457  } 
     1458 
     1459  if ( ::arg().mustDo( "unregister-service" )) { 
     1460    recursor.unregisterService(); 
     1461    exit( 0 ); 
     1462  } 
     1463} 
     1464#endif 
     1465 
    12721466int main(int argc, char **argv)  
    12731467{ 
     
    12761470  int ret = EXIT_SUCCESS; 
    12771471#ifdef WIN32 
    1278     WSADATA wsaData; 
    1279     if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData )) { 
    1280       cerr<<"Unable to initialize winsock\n"; 
    1281       exit(1); 
    1282     } 
     1472  RecursorService service; 
     1473  WSADATA wsaData; 
     1474  if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData )) { 
     1475    cerr<<"Unable to initialize winsock\n"; 
     1476    exit(1); 
     1477  } 
    12831478#endif // WIN32 
    12841479 
     
    12991494#ifdef WIN32 
    13001495    ::arg().set("quiet","Suppress logging of questions and answers")="off"; 
     1496    ::arg().setSwitch( "register-service", "Register the service" )= "no"; 
     1497    ::arg().setSwitch( "unregister-service", "Unregister the service" )= "no"; 
     1498    ::arg().setSwitch( "ntservice", "Run as service" )= "no"; 
     1499    ::arg().setSwitch( "use-ntlog", "Use the NT logging facilities" )= "yes";  
     1500    ::arg().setSwitch( "use-logfile", "Use a log file" )= "no";  
     1501    ::arg().setSwitch( "logfile", "Filename of the log file" )= "recursor.log";  
    13011502#else 
    13021503    ::arg().set("quiet","Suppress logging of questions and answers")=""; 
     
    13071508    ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0"; 
    13081509    ::arg().set("query-local-address6","Source IPv6 address for sending queries")=""; 
    1309     //    ::arg().set("query-local-port","Source port address for sending queries, defaults to random")=""; 
    13101510    ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2"; 
    13111511    ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128"; 
     
    13521552    } 
    13531553 
    1354     L.setName("pdns_recursor"); 
    1355  
    1356     L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2006 PowerDNS.COM BV ("<<__DATE__", "__TIME__; 
    1357 #ifdef __GNUC__ 
    1358     L<<", gcc "__VERSION__; 
    1359 #endif // add other compilers here 
    1360 #ifdef _MSC_VER 
    1361         L<<", MSVC "<<_MSC_VER; 
     1554#ifndef WIN32 
     1555    doWindowsServiceArguments(service); 
     1556    serviceMain(argc, argv); 
     1557#else 
     1558    RecursorService::instance()->start( argc, argv, ::arg().mustDo( "ntservice" ));  
    13621559#endif 
    1363     L<<") starting up"<<endl; 
    1364  
    1365     L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. " 
    1366       "This is free software, and you are welcome to redistribute it " 
    1367       "according to the terms of the GPL version 2."<<endl; 
    1368  
    1369     L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl; 
    1370  
    1371     if(!::arg()["allow-from"].empty()) { 
    1372       g_allowFrom=new NetmaskGroup; 
    1373       vector<string> ips; 
    1374       stringtok(ips, ::arg()["allow-from"], ", "); 
    1375       L<<Logger::Warning<<"Only allowing queries from: "; 
    1376       for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) { 
    1377         g_allowFrom->addMask(*i); 
    1378         if(i!=ips.begin()) 
    1379           L<<Logger::Warning<<", "; 
    1380         L<<Logger::Warning<<*i; 
    1381       } 
    1382       L<<Logger::Warning<<endl; 
    1383     } 
    1384     else if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53) 
    1385       L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl; 
    1386      
    1387     g_quiet=::arg().mustDo("quiet"); 
    1388     if(::arg().mustDo("trace")) { 
    1389       SyncRes::setLog(true); 
    1390       ::arg().set("quiet")="no"; 
    1391       g_quiet=false; 
    1392     } 
    1393  
    1394  
    1395     if(!::arg()["query-local-address6"].empty()) { 
    1396       SyncRes::s_doIPv6=true; 
    1397       L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl; 
    1398     } 
    1399      
    1400     SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl"); 
    1401     SyncRes::s_serverID=::arg()["server-id"]; 
    1402     if(SyncRes::s_serverID.empty()) { 
    1403       char tmp[128]; 
    1404       gethostname(tmp, sizeof(tmp)-1); 
    1405       SyncRes::s_serverID=tmp; 
    1406     } 
    1407      
    1408  
    1409     parseAuthAndForwards(); 
    1410  
    1411     g_stats.remotes.resize(::arg().asNum("remotes-ringbuffer-entries")); 
    1412         if(!g_stats.remotes.empty()) 
    1413           memset(&g_stats.remotes[0], 0, g_stats.remotes.size() * sizeof(RecursorStats::remotes_t::value_type)); 
    1414     g_logCommonErrors=::arg().mustDo("log-common-errors"); 
    1415  
    1416     makeUDPServerSockets(); 
    1417     makeTCPServerSockets(); 
    1418  
    1419 #ifndef WIN32 
    1420     if(::arg().mustDo("fork")) { 
    1421       fork(); 
    1422       L<<Logger::Warning<<"This is forked pid "<<getpid()<<endl; 
    1423     } 
    1424 #endif 
    1425  
    1426     MT=new MTasker<PacketID,string>(100000); 
    1427     makeControlChannelSocket();         
    1428     PacketID pident; 
    1429     primeHints();     
    1430     L<<Logger::Warning<<"Done priming cache with root hints"<<endl; 
    1431 #ifndef WIN32 
    1432     if(::arg().mustDo("daemon")) { 
    1433       L<<Logger::Warning<<"Calling daemonize, going to background"<<endl; 
    1434       L.toConsole(Logger::Critical); 
    1435       L.setLoglevel((Logger::Urgency)(4)); 
    1436  
    1437       daemonize(); 
    1438     } 
    1439     signal(SIGUSR1,usr1Handler); 
    1440     signal(SIGUSR2,usr2Handler); 
    1441     signal(SIGPIPE,SIG_IGN); 
    1442     writePid(); 
    1443 #endif 
    1444     g_fdm=getMultiplexer(); 
    1445  
    1446     for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)  
    1447       g_fdm->addReadFD(i->first, i->second); 
    1448  
    1449     int newgid=0; 
    1450     if(!::arg()["setgid"].empty()) 
    1451       newgid=Utility::makeGidNumeric(::arg()["setgid"]); 
    1452     int newuid=0; 
    1453     if(!::arg()["setuid"].empty()) 
    1454       newuid=Utility::makeUidNumeric(::arg()["setuid"]); 
    1455  
    1456 #ifndef WIN32 
    1457     if (!::arg()["chroot"].empty()) { 
    1458         if (chroot(::arg()["chroot"].c_str())<0) { 
    1459             L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl; 
    1460             exit(1); 
    1461         } 
    1462     } 
    1463  
    1464     Utility::dropPrivs(newuid, newgid); 
    1465     g_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel 
    1466 #endif  
    1467  
    1468     counter=0; 
    1469     unsigned int maxTcpClients=::arg().asNum("max-tcp-clients"); 
    1470     g_tcpTimeout=::arg().asNum("client-tcp-timeout"); 
    1471  
    1472     g_maxTCPPerClient=::arg().asNum("max-tcp-per-client"); 
    1473  
    1474  
    1475     bool listenOnTCP(true); 
    1476  
    1477     for(;;) { 
    1478       while(MT->schedule()); // housekeeping, let threads do their thing 
    1479        
    1480       if(!(counter%500)) { 
    1481         MT->makeThread(houseKeeping,0); 
    1482       } 
    1483  
    1484       if(!(counter%11)) { 
    1485         typedef vector<pair<int, boost::any> > expired_t; 
    1486         expired_t expired=g_fdm->getTimeouts(g_now); 
    1487          
    1488         for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) { 
    1489           TCPConnection conn=any_cast<TCPConnection>(i->second); 
    1490           if(conn.state != TCPConnection::DONE) { 
    1491             if(g_logCommonErrors) 
    1492               L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl; 
    1493             g_fdm->removeReadFD(i->first); 
    1494             conn.closeAndCleanup(); 
    1495           } 
    1496         } 
    1497       } 
    1498        
    1499       counter++; 
    1500  
    1501       if(statsWanted) { 
    1502         doStats(); 
    1503       } 
    1504  
    1505       Utility::gettimeofday(&g_now, 0); 
    1506       g_fdm->run(&g_now); 
    1507  
    1508       if(listenOnTCP) { 
    1509         if(TCPConnection::s_currentConnections > maxTcpClients) {  // shutdown 
    1510           for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i) 
    1511             g_fdm->removeReadFD(*i); 
    1512           listenOnTCP=false; 
    1513         } 
    1514       } 
    1515       else { 
    1516         if(TCPConnection::s_currentConnections <= maxTcpClients) {  // reenable 
    1517           for(g_tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i) 
    1518             g_fdm->addReadFD(*i, handleNewTCPQuestion); 
    1519           listenOnTCP=true; 
    1520         } 
    1521       } 
    1522     } 
     1560 
    15231561  } 
    15241562  catch(AhuException &ae) {