From 74fb9452a0e5baeaf0023a7ebcbb64661abfb326 Mon Sep 17 00:00:00 2001 From: Fons Rademakers <Fons.Rademakers@cern.ch> Date: Mon, 28 Oct 2002 14:22:51 +0000 Subject: [PATCH] Applied rootd patch by Ulrik Egede and Tim Adye from BaBar. New features: 1) New option, -P FILE, to specify an alternate SRP password file. As an example rootd -P $HOME/.srootdpass2 will start rootd using the files $HOME/.srootdpass2.conf and $HOME/.srootdpass2 for SRP authentication. 2) Modified option, -p port1-port2, will search for the first available port in the range. You can also specify -p 0-N for search relative to the service port specified in /etc/services (this was sort of accidental, but not a bad feature :-). If a single port is specified as before, then no search is made. 3) Unless started by inetd (rootd -i), it prints something like ROOTD_PORT=5151 ROOTD_PID=14433 before spawning the daemon so the user knows what was used (eval `rootd` will set these as variables in Bourne-shells). 4) rootd now shows an error message (as well as the syslog message it always sent) if there is any problem binding the port or forking the daemon. git-svn-id: http://root.cern.ch/svn/root/trunk@5507 27541ba8-7e3a-0410-8455-c3a389f83636 --- rootd/inc/rootdp.h | 6 +-- rootd/src/daemon.cxx | 36 +++++++++++----- rootd/src/net.cxx | 62 +++++++++++++++++----------- rootd/src/rootd.cxx | 98 ++++++++++++++++++++++++++++++-------------- 4 files changed, 133 insertions(+), 69 deletions(-) diff --git a/rootd/inc/rootdp.h b/rootd/inc/rootdp.h index 36e6ffd1a9a..4c28ad3ce40 100644 --- a/rootd/inc/rootdp.h +++ b/rootd/inc/rootdp.h @@ -1,4 +1,4 @@ -/* @(#)root/rootd:$Name: $:$Id: rootdp.h,v 1.4 2001/02/22 09:43:25 rdm Exp $ */ +/* @(#)root/rootd:$Name: $:$Id: rootdp.h,v 1.5 2001/02/26 02:49:07 rdm Exp $ */ /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * @@ -42,7 +42,7 @@ extern double gBytesSent; extern double gBytesRecv; -void DaemonStart(int ignsigcld); +void DaemonStart(int ignsigcld, int fdkeep); void ErrorInit(const char *ident); void ErrorInfo(const char *va_(fmt), ...); @@ -53,7 +53,7 @@ int GetErrno(); void ResetErrno(); void Perror(char *buf); -void NetInit(const char *service, int port, int tcpwindowsize); +int NetInit(const char *service, int port1, int port2, int tcpwindowsize); int NetOpen(int inetdflag); void NetClose(); char *NetRemoteHost(); diff --git a/rootd/src/daemon.cxx b/rootd/src/daemon.cxx index 6eca01fa7ab..b3dd4181cde 100644 --- a/rootd/src/daemon.cxx +++ b/rootd/src/daemon.cxx @@ -1,4 +1,4 @@ -// @(#)root/rootd:$Name: $:$Id: daemon.cxx,v 1.3 2001/04/06 14:17:42 rdm Exp $ +// @(#)root/rootd:$Name: $:$Id: daemon.cxx,v 1.4 2002/01/22 10:53:29 rdm Exp $ // Author: Fons Rademakers 11/08/97 /************************************************************************* @@ -72,7 +72,7 @@ static void SigChild(int) #endif //______________________________________________________________________________ -void DaemonStart(int ignsigcld) +void DaemonStart(int ignsigcld, int fdkeep) { // Detach a daemon process from login session context. @@ -84,8 +84,10 @@ void DaemonStart(int ignsigcld) int fd; - if (getppid() == 1) + if (getppid() == 1) { + printf ("ROOTD_PID=%ld\n", (long) getpid()); goto out; + } // Ignore the terminal stop signals (BSD). @@ -104,10 +106,15 @@ void DaemonStart(int ignsigcld) // group leader. int childpid; - if ((childpid = fork()) < 0) + if ((childpid = fork()) < 0) { + fprintf(stderr, "DaemonStart: can't fork first child\n"); ErrorSys(kErrFatal, "DaemonStart: can't fork first child"); - else if (childpid > 0) + } else if (childpid > 0) { +#ifdef SIGTSTP + printf("ROOTD_PID=%d\n", childpid); +#endif exit(0); // parent + } // First child process... @@ -117,11 +124,13 @@ void DaemonStart(int ignsigcld) #ifdef SIGTSTP #ifdef USE_SETSID - if (setsid() == -1) + if (setsid() == -1) { #else - if (setpgrp(0, getpid()) == -1) + if (setpgrp(0, getpid()) == -1) { #endif + fprintf(stderr, "DaemonStart: can't change process group\n"); ErrorSys(kErrFatal, "DaemonStart: can't change process group"); + } if ((fd = open("/dev/tty", O_RDWR)) >= 0) { #if !defined(__hpux) && !defined(__sun) @@ -132,15 +141,20 @@ void DaemonStart(int ignsigcld) #else - if (setpgrp() == -1) + if (setpgrp() == -1) { + fprintf(stderr, "DaemonStart: can't change process group\n"); ErrorSys(kErrFatal, "DaemonStart: can't change process group"); + } signal(SIGHUP, SIG_IGN); // immune from pgrp leader death - if ((childpid = fork()) < 0) + if ((childpid = fork()) < 0) { + fprintf(stderr, "DaemonStart: can't fork second child\n"); ErrorSys(kErrFatal, "DaemonStart: can't fork second child"); - else if (childpid > 0) + } else if (childpid > 0) { + printf("ROOTD_PID=%d\n", childpid); exit(0); // first child + } // Second child process... @@ -151,7 +165,7 @@ out: // Close any open file descriptors for (fd = 0; fd < NOFILE; fd++) - close(fd); + if (fd != fdkeep) close(fd); ResetErrno(); // probably got set to EBADF from a close diff --git a/rootd/src/net.cxx b/rootd/src/net.cxx index 50220421026..1a0ee8ca3f2 100644 --- a/rootd/src/net.cxx +++ b/rootd/src/net.cxx @@ -1,4 +1,4 @@ -// @(#)root/rootd:$Name: $:$Id: net.cxx,v 1.14 2002/01/22 10:53:29 rdm Exp $ +// @(#)root/rootd:$Name: $:$Id: net.cxx,v 1.15 2002/02/06 18:27:40 rdm Exp $ // Author: Fons Rademakers 12/08/97 /************************************************************************* @@ -274,7 +274,7 @@ int NetRecv(char *msg, int len, EMessageTypes &kind) } //______________________________________________________________________________ -void NetInit(const char *service, int port, int tcpwindowsize) +int NetInit(const char *service, int port1, int port2, int tcpwindowsize) { // Initialize the network connection for the server, when it has *not* // been invoked by inetd. @@ -283,46 +283,56 @@ void NetInit(const char *service, int port, int tcpwindowsize) // We have to create a socket ourselves and bind our well-known // address to it. - memset(&tcp_srv_addr, 0, sizeof(tcp_srv_addr)); - tcp_srv_addr.sin_family = AF_INET; - tcp_srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - - if (service) { - - if (port > 0) - tcp_srv_addr.sin_port = htons(port); - else { + if (port1 <= 0) { + if (service) { struct servent *sp; - if ((sp = getservbyname(service, "tcp")) == 0) + if ((sp = getservbyname(service, "tcp")) == 0) { + fprintf(stderr, "NetInit: unknown service: %s/tcp\n", service); ErrorFatal(kErrFatal, "NetInit: unknown service: %s/tcp", service); - tcp_srv_addr.sin_port = sp->s_port; - } - - } else { - - if (port <= 0) + } + port1 = ntohs(sp->s_port); + port2 += port1; // in this case, port2 is relative to service port + } else { + fprintf(stderr, "NetInit: must specify either service or port\n"); ErrorFatal(kErrFatal, "NetInit: must specify either service or port"); - tcp_srv_addr.sin_port = htons(port); - + } } // Create the socket and bind our local address so that any client can // send to us. - if ((tcp_srv_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + if ((tcp_srv_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "NetInit: can't create socket\n"); ErrorSys(kErrFatal, "NetInit: can't create socket"); + } int val = 1; if (setsockopt(tcp_srv_sock, SOL_SOCKET, SO_REUSEADDR, (char*) &val, - sizeof(val)) == -1) + sizeof(val)) == -1) { + fprintf(stderr, "NetInit: can't set SO_REUSEADDR socket option\n"); ErrorSys(kErrFatal, "NetInit: can't set SO_REUSEADDR socket option"); + } // Set several general performance network options NetSetOptions(tcp_srv_sock, tcpwindowsize); - if (bind(tcp_srv_sock, (struct sockaddr *) &tcp_srv_addr, - sizeof(tcp_srv_addr)) < 0) - ErrorSys(kErrFatal, "NetInit: can't bind local address"); + memset(&tcp_srv_addr, 0, sizeof(tcp_srv_addr)); + tcp_srv_addr.sin_family = AF_INET; + tcp_srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + int port; + for (port= port1; port <= port2; port++) { + tcp_srv_addr.sin_port = htons(port); + if (bind(tcp_srv_sock, (struct sockaddr *) &tcp_srv_addr, + sizeof(tcp_srv_addr)) == 0) break; + } + + if (port > port2) { + fprintf(stderr, "NetInit: can't bind local address to ports %d-%d\n", port1, port2); + ErrorSys(kErrFatal, "NetInit: can't bind local address to ports %d-%d", port1, port2); + } + + printf("ROOTD_PORT=%d\n", port); // And set the listen parameter, telling the system that we're // ready to accept incoming connection requests. @@ -332,6 +342,8 @@ void NetInit(const char *service, int port, int tcpwindowsize) if (gDebug > 0) ErrorInfo("NetInit: socket %d listening on port %d", tcp_srv_sock, ntohs(tcp_srv_addr.sin_port)); + + return tcp_srv_sock; } //______________________________________________________________________________ diff --git a/rootd/src/rootd.cxx b/rootd/src/rootd.cxx index 45cf5109b20..9f3607b049b 100644 --- a/rootd/src/rootd.cxx +++ b/rootd/src/rootd.cxx @@ -1,4 +1,4 @@ -// @(#)root/rootd:$Name: $:$Id: rootd.cxx,v 1.43 2002/06/25 23:53:26 rdm Exp $ +// @(#)root/rootd:$Name: $:$Id: rootd.cxx,v 1.44 2002/06/27 23:58:02 rdm Exp $ // Author: Fons Rademakers 11/08/97 /************************************************************************* @@ -9,7 +9,8 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -/* Parts of this file are copied from the MIT krb5 distribution and +/* + * Parts of this file are copied from the MIT krb5 distribution and * are subject to the following license: * * Copyright 1990,1991 by the Massachusetts Institute of Technology. @@ -33,7 +34,6 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * */ ////////////////////////////////////////////////////////////////////////// @@ -63,14 +63,25 @@ // rootd -p 5151 // // // // Notice: no & is needed. Rootd will go in background by itself. // +// In this case, the port number and process id will be printed, e.g. // +// // +// ROOTD_PORT=5151 // +// ROOTD_PID=14433 // // // // Rootd arguments: // // -i says we were started by inetd // -// -p port# specifies a different port to listen on // +// -p port# specifies a different port to listen on. // +// Use port1-port2 to find first available port in // +// range. Use 0-N for range relative to service // +// port. // // -b tcpwindowsize specifies the tcp window size in bytes (e.g. see // // http://www.psc.edu/networking/perf_tune.html) // // Default is 65535. Only change default for pipes // // with a high bandwidth*delay product. // +// -P file use this password file, instead of .srootdpass // +// -S keytabfile use this keytab file, instead of the default // +// (option only supported when compiled with // +// Kerberos5 support) // // -d level level of debug info written to syslog // // 0 = no debug (default) // // 1 = minimum // @@ -289,34 +300,37 @@ extern krb5_deltat krb5_clockskew; //--- Globals ------------------------------------------------------------------ +const int kMAXPATHLEN = 1024; const char kRootdService[] = "rootd"; const char kRootdTab[] = "/usr/tmp/rootdtab"; const char kRootdPass[] = ".rootdpass"; const char kSRootdPass[] = ".srootdpass"; -const int kMAXPATHLEN = 1024; enum { kBinary, kAscii }; -int gInetdFlag = 0; -int gPort = 0; -int gDebug = 0; -int gSockFd = -1; -int gAuth = 0; -int gAnon = 0; -int gFd = -1; -int gWritable = 0; -int gProtocol = 6; // increase when protocol changes -int gUploaded = 0; -int gDownloaded = 0; -int gFtp = 0; -double gBytesRead = 0; -double gBytesWritten = 0; -char gUser[64] = { 0 }; -char gPasswd[64] = { 0 }; // only used for anonymous access -char gOption[32] = { 0 }; -char gFile[kMAXPATHLEN] = { 0 }; +int gInetdFlag = 0; +int gPort1 = 0; +int gPort2 = 0; +int gDebug = 0; +int gSockFd = -1; +int gAuth = 0; +int gAnon = 0; +int gAltSRP = 0; +int gFd = -1; +int gWritable = 0; +int gProtocol = 6; // increase when protocol changes +int gUploaded = 0; +int gDownloaded = 0; +int gFtp = 0; +double gBytesRead = 0; +double gBytesWritten = 0; +char gUser[64] = { 0 }; +char gPasswd[64] = { 0 }; // only used for anonymous access +char gOption[32] = { 0 }; +char gFile[kMAXPATHLEN] = { 0 }; +char gAltSRPPass[kMAXPATHLEN] = { 0 }; #ifdef R__KRB5 -krb5_keytab gKeytab = 0; // to allow specifying on the command line +krb5_keytab gKeytab = 0; // to allow specifying on the command line krb5_context gKcontext; #endif @@ -996,8 +1010,13 @@ void RootdSRPUser(const char *user) strcpy(gUser, user); - sprintf(srootdpass, "%s/%s", pw->pw_dir, kSRootdPass); - sprintf(srootdconf, "%s/%s.conf", pw->pw_dir, kSRootdPass); + if (!gAltSRP) { + sprintf(srootdpass, "%s/%s", pw->pw_dir, kSRootdPass); + sprintf(srootdconf, "%s/%s.conf", pw->pw_dir, kSRootdPass); + } else { + sprintf(srootdpass, "%s", gAltSRPPass); + sprintf(srootdconf, "%s.conf", gAltSRPPass); + } FILE *fp1 = fopen(srootdpass, "r"); if (!fp1) { @@ -2166,7 +2185,17 @@ int main(int argc, char **argv) fprintf(stderr, "-p requires a port number as argument\n"); ErrorFatal(kErrFatal, "-p requires a port number as argument"); } - gPort = atoi(*++argv); + char *p; + gPort1 = strtol(*++argv, &p, 10); + if (*p == '-') + gPort2 = strtol(++p, &p, 10); + else if (*p == '\0') + gPort2 = gPort1; + if (*p != '\0' || gPort2 < gPort1 || gPort2 < 0) { + if (!gInetdFlag) + fprintf(stderr, "invalid port number or range: %s\n", *argv); + ErrorFatal(kErrFatal, "invalid port number or range: %s", *argv); + } break; case 'd': @@ -2187,6 +2216,16 @@ int main(int argc, char **argv) tcpwindowsize = atoi(*++argv); break; + case 'P': + if (--argc <= 0) { + if (!gInetdFlag) + fprintf(stderr, "-P requires a file name for SRP password file\n"); + ErrorFatal(kErrFatal, "-P requires a file name for SRP password file"); + } + gAltSRP = 1; + sprintf(gAltSRPPass, "%s", *++argv); + break; + #ifdef R__KRB5 case 'S': if (--argc <= 0) { @@ -2213,9 +2252,8 @@ int main(int argc, char **argv) // Also initialize the network connection - create the socket // and bind our well-know address to it. - DaemonStart(1); - - NetInit(kRootdService, gPort, tcpwindowsize); + int fdkeep = NetInit(kRootdService, gPort1, gPort2, tcpwindowsize); + DaemonStart(1, fdkeep); } if (gDebug > 0) -- GitLab