45 #include <sys/param.h>
46 #include <sys/resource.h>
47 #include <sys/types.h>
53 #include "XrdVersion.hh"
93 #if defined(__linux__) || defined(__GNU__)
94 #include <netinet/tcp.h>
96 #if defined(__linux__)
97 #include <sys/epoll.h>
100 #include <AvailabilityMacros.h>
141 void TlsError(
const char *tid,
const char *msg,
bool sslmsg)
149 const char *XrdConfig::TraceID =
"Config";
155 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
186 {
for (
int i = 0; i < numP; i++)
187 if (pnum == portVec[i])
188 {tlsVec[i] = isTLS;
return true;}
190 portVec[numP] = pnum; tlsVec[numP] = isTLS;
195 void Reset(
char *ln,
char *pp,
int np=-1,
bool to=
false)
196 {
if (libpath) free(libpath);
198 if (parms) free(parms);
200 memset(portVec, 0,
sizeof(portVec));
202 memset(tlsVec, 0,
sizeof(tlsVec));
209 : Next(0), proname(pn), libpath(ln), parms(pp), numP(1)
210 {memset(portVec, 0,
sizeof(portVec)); port = np;
211 memset(tlsVec, 0,
sizeof(tlsVec)); dotls =
to;
216 if (libpath) free(libpath);
217 if (parms) free(parms);
232 : KingPin(drctv,
theEnv, errR, &myVer)
256 AdminPath= strdup(
"/tmp");
258 PidPath = strdup(
"/tmp");
283 Firstcp = Lastcp = 0;
285 ProtInfo.eDest = &
Log;
288 ProtInfo.Sched = &
Sched;
289 ProtInfo.ConfigFN= 0;
291 ProtInfo.AdmPath = AdminPath;
292 ProtInfo.AdmMode = AdminMode;
293 ProtInfo.theEnv = &
theEnv;
294 ProtInfo.xrdFlags= 0;
297 memset(ProtInfo.rsvd3, 0,
sizeof(ProtInfo.rsvd3));
299 ProtInfo.ConnMax = -1;
300 ProtInfo.readWait = 3*1000;
301 ProtInfo.idleWait = 0;
302 ProtInfo.hailWait =30*1000;
303 ProtInfo.DebugON = 0;
306 ProtInfo.tlsPort = 0;
326 const char *xrdInst=
"XRDINSTANCE=";
328 int retc, NoGo = 0, clPort = -1;
330 char c, buff[512], *dfltProt, *libProt = 0;
334 extern int optind, opterr;
336 int pipeFD[2] = {-1, -1};
337 const char *pidFN = 0;
338 static const int myMaxc = 80;
339 char **urArgv, *myArgv[myMaxc], argBuff[myMaxc*3+8];
340 char *argbP = argBuff, *argbE = argbP+
sizeof(argBuff)-4;
342 int myArgc = 1, urArgc = argc, i;
343 bool noV6, ipV4 =
false, ipV6 =
false, rootChk =
true, optbg =
false;
348 for (
int k = 1; k < argc; k++)
349 {CmdLine +=
' '; CmdLine += argv[k];}
353 retc = strlen(argv[0]);
354 while(retc--)
if (argv[0][retc] ==
'/')
break;
355 myProg = &argv[0][retc+1];
362 {
char *p = dfltProt = strdup(myProg);
363 while(*p && (*p ==
'.' || *p ==
'-')) p++;
365 {
char *dot = index(p,
'.'), *dash = index(p,
'-');
366 if (dot && (dot < dash || !dash)) p = dot;
367 else if (dash) p = dash;
370 if (!strcmp(
"xrootd", dfltProt)) dfltProt[5] = 0;
371 else if (!strcmp(
"cmsd", dfltProt)) dfltProt[3] = 0;
381 {
if (*(argv[i]) ==
'-' && *(argv[i]+1) ==
'+')
382 {
int n = strlen(argv[i]+2), j = i+1, k = 1;
383 if (urArgc == argc) urArgc = i;
384 if (n) memcpy(buff, argv[i]+2, (n > 256 ? 256 : n));
385 strcpy(&(buff[n]),
".argv**");
386 while(j < argc && (*(argv[j]) !=
'-' || *(argv[j]+1) !=
'+')) j++;
387 urArgv =
new char*[j-i+1];
390 while(i < j) urArgv[k++] = argv[i++];
393 strcpy(&(buff[n]),
".argc");
403 if (argc > 1 &&
'-' == *argv[1])
404 while ((c = getopt(urArgc,argv,
":a:A:bc:dhHI:k:l:L:n:p:P:R:s:S:vw:W:z"))
405 && ((
unsigned char)c != 0xff))
408 case 'a':
if (AdminPath) free(AdminPath);
409 AdminPath = strdup(optarg);
410 AdminMode = ProtInfo.AdmMode = S_IRWXU;
413 case 'A':
if (AdminPath) free(AdminPath);
414 AdminPath = strdup(optarg);
415 AdminMode = ProtInfo.AdmMode = S_IRWXU | S_IRWXG;
418 case 'b': optbg =
true;
420 case 'c':
if (ConfigFN) free(ConfigFN);
421 ConfigFN = strdup(optarg);
424 ProtInfo.DebugON = 1;
431 case 'I':
if (!strcmp(
"v4", optarg)) {ipV4 =
true; ipV6 =
false;}
432 else if (!strcmp(
"v6", optarg)) {ipV4 =
false; ipV6 =
true;}
433 else {
Log.
Emsg(
"Config",
"Invalid -I argument -",optarg);
438 {
Log.
Emsg(
"Config",
"Invalid -k argument -",optarg);
442 case 'l': LogInfo.
logArg = optarg;
444 case 'L':
if (!*optarg)
445 {
Log.
Emsg(
"Config",
"Protocol library path not specified.");
448 if (libProt) free(libProt);
449 libProt = strdup(optarg);
451 case 'n': myInsName = (!strcmp(optarg,
"anon")||!strcmp(optarg,
"default")
456 case 'P':
if (dfltProt) free(dfltProt);
457 dfltProt = strdup(optarg);
459 case 'R':
if (!(getUG(optarg, myUid, myGid)))
Usage(1);
462 case 's': pidFN = optarg;
464 case 'S': mySitName = optarg;
466 case ':': buff[0] =
'-'; buff[1] =
optopt; buff[2] = 0;
467 Log.
Emsg(
"Config", buff,
"parameter not specified.");
470 case 'v': std::cerr <<XrdVSTRING <<std::endl;
473 case 'w':
if (HomePath) free(HomePath);
474 HomePath = strdup(optarg);
478 case 'W':
if (HomePath) free(HomePath);
479 HomePath = strdup(optarg);
480 HomeMode = S_IRWXU | S_IRGRP | S_IXGRP;
483 case 'z': LogInfo.
hiRes =
true;
487 {
Log.
Emsg(
"Config",
"Long options are not supported.");
490 if (myArgc >= myMaxc || argbP >= argbE)
491 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
494 myArgv[myArgc++] = argbP;
495 *argbP++ =
'-'; *argbP++ =
optopt; *argbP++ = 0;
503 {
Log.
Emsg(
"Config",
"Command line adminpath is not absolute.");
509 if (HomePath && *HomePath !=
'/')
510 {
Log.
Emsg(
"Config",
"Command line home path is not absolute.");
517 if (ConfigFN) setCFG(
true);
523 else if (ipV6){
if (noV6)
Log.
Say(
"Config warning: ipV6 appears to be broken;"
524 " forced ipV6 mode not advised!");
527 else if (noV6)
Log.
Say(
"Config warning: ipV6 is misconfigured or "
528 "unavailable; reverting to ipV4.");
536 if (myGid && setegid(myGid))
537 {
Log.
Emsg(
"Config", errno,
"set effective gid"); exit(17);}
538 if (myUid && seteuid(myUid))
539 {
Log.
Emsg(
"Config", errno,
"set effective uid"); exit(17);}
543 if (rootChk && geteuid() == 0)
544 {
Log.
Emsg(
"Config",
"Security reasons prohibit running as "
545 "superuser; program is terminating.");
551 if (urArgc-
optind+2 >= myMaxc)
552 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
560 ProtInfo.argc = myArgc;
561 ProtInfo.argv = myArgv;
570 if (pipe( pipeFD ) == -1)
571 {
Log.
Emsg(
"Config", errno,
"create a pipe"); exit(17);}
580 auto envName = getenv(
"XRDHOST");
581 const char *ipAddrName;
585 }
else if ((ipAddrName = myIPAddr->
Name(0, &temp))) {
593 ProtInfo.myName = myName.c_str();
594 ProtInfo.myAddr = myIPAddr->
SockAddr();
596 ProtInfo.myProg = myProg;
602 sprintf(buff,
"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName.c_str());
603 myInstance = strdup(buff);
605 myInstance += strlen(xrdInst);
614 LogInfo.
iName = myInsName;
615 LogInfo.
cfgFn = ConfigFN;
626 {
Log.
Emsg(
"Config",
"Unable to determine host name; ",
627 (temp ? temp :
"reason unknown"),
628 "; execution terminated.");
638 strcpy(buff,
"Starting on ");
650 {
Log.
Emsg(
"Config",myName.c_str(),
"does not appear to be registered in the DNS.");
651 Log.
Emsg(
"Config",
"Verify that the '/etc/hosts' file is correct and "
652 "this machine is registered in DNS.");
653 Log.
Emsg(
"Config",
"Execution continues but connection failures may occur.");
655 }
else if (!(
myDomain = index(myName.c_str(),
'.')))
656 Log.
Say(
"Config warning: this hostname, ", myName.c_str(),
657 ", is registered without a domain qualification.");
661 Firstcp = Lastcp =
new XrdConfigProt(strdup(dfltProt), libProt, 0);
665 Log.
Say(
"++++++ ", myInstance,
" initialization started.");
669 devNull = XrdSysFD_Open(
"/dev/null", O_RDONLY);
671 {
Log.
Emsg(
"Config", errno,
"open '/dev/null' which is required!");
678 {
Log.
Say(
"Config using configuration file ", ConfigFN);
679 ProtInfo.ConfigFN = ConfigFN;
682 if (clPort >= 0) PortTCP = clPort;
683 if (ProtInfo.DebugON)
690 NoGo |= SetupAPath();
695 {
if (!tlsCert) ProtInfo.tlsCtx= 0;
696 else {
Log.
Say(
"++++++ ", myInstance,
" TLS initialization started.");
698 {
Log.
Say(
"------ ",myInstance,
" TLS initialization ended.");
703 Log.
Say(
"------ ",myInstance,
" TLS initialization failed.");
713 {
Log.
Say(
"Config TLS port specification ignored; TLS not configured!");
717 ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
733 {
Log.
Emsg(
"Config",
"Unable to determine interface addresses!");
739 if ((myInsName || HomePath)
744 if (!PidFile(pidFN, optbg)) NoGo = 1;
748 if (!NoGo) Manifest(pidFN);
752 if (!NoGo) NoGo = Setup(dfltProt, libProt);
761 if (tmoInfo && !NoGo)
763 if (!theGS)
Log.
Say(
"Config warning: TCP monitoring not enabled; "
764 "tcpmonlib plugin not loaded!");
765 else {tmoInfo->theEnv.PutPtr(
"TcpMon.gStream*", theGS);
766 TcpMonPin = tmoInfo->KingPin.Load(
"TcpMonPin");
776 int status = NoGo ? 1 : 0;
777 if(
write( pipeFD[1], &status,
sizeof( status ) )) {};
784 temp = (NoGo ?
" initialization failed." :
" initialization completed.");
785 sprintf(buff,
"%s:%d", myInstance, PortTCP);
786 Log.
Say(
"------ ", buff, temp);
788 {strcat(buff,
" running ");
806 if (
eDest) dynamic = 1;
820 TS_Xeq(
"adminpath", xapath);
822 TS_Xeq(
"homepath", xhpath);
826 TS_Xeq(
"protocol", xprot);
829 TS_Xeq(
"tcpmonlib", xtcpmon);
833 TS_Xeq(
"tlsciphers", xtlsci);
838 eDest->
Say(
"Config warning: ignoring unknown xrd directive '",var,
"'.");
850 int XrdConfig::ASocket(
const char *path,
const char *fname, mode_t mode)
852 struct sockaddr_un unixvar;
853 int plen = strlen(path), flen = strlen(fname);
857 if ((plen + flen + 3) > (
int)
sizeof(unixvar.sun_path))
858 {
Log.
Emsg(
"Config",
"admin path", path,
"too long");
893 int XrdConfig::ConfigProc()
896 int cfgFD, retc, NoGo = 0;
902 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
903 {
Log.
Emsg(
"Config", errno,
"open config file", ConfigFN);
910 while((var =
Config.GetMyFirstWord()))
911 if (!strncmp(var,
"xrd.", 4)
912 || !strcmp (var,
"all.adminpath")
913 || !strcmp (var,
"all.pidpath")
914 || !strcmp (var,
"all.sitename" ))
915 if (ConfigXeq(var+4,
Config)) {
Config.Echo(); NoGo = 1;}
919 if ((retc =
Config.LastError()))
920 NoGo =
Log.
Emsg(
"Config", retc,
"read config file", ConfigFN);
932 XrdInet *XrdConfig::getNet(
int port,
bool isTLS)
934 int the_Opts, the_Blen;
938 for (
int i = 0; i < (int)NetTCP.size(); i++)
939 if (port == NetTCP[i]->Port())
return NetTCP[i];
944 NetTCP.push_back(newNet);
949 {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
951 the_Opts = Net_Opts; the_Blen = Net_Blen;
953 if (the_Opts || the_Blen) newNet->
setDefaults(the_Opts, the_Blen);
961 if (newNet->
BindSD(port,
"tcp") == 0)
return newNet;
970 int XrdConfig::getUG(
char *parm, uid_t &newUid, gid_t &newGid)
977 {
Log.
Emsg(
"Config",
"-R user not specified.");
return 0;}
980 {
if (!(newUid = atol(parm)))
981 {
Log.
Emsg(
"Config",
"-R", parm,
"is invalid");
return 0;}
982 pp = getpwuid(newUid);
984 else pp = getpwnam(parm);
989 {
Log.
Emsg(
"Config", errno,
"retrieve -R user password entry");
992 if (!(newUid = pp->pw_uid))
993 {
Log.
Emsg(
"Config",
"-R", parm,
"is still unacceptably a superuser!");
1004 void XrdConfig::Manifest(
const char *pidfn)
1007 char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1012 if (!getcwd(pwdBuff,
sizeof(pwdBuff)))
1013 {
Log.
Emsg(
"Config",
"Unable to get current working directory!");
1019 if (HomePath) free(HomePath);
1020 HomePath = strdup(pwdBuff);
1024 strcpy(envBuff, ProtInfo.AdmPath);
1025 envLen = strlen(envBuff);
1026 if (envBuff[envLen-1] !=
'/') {envBuff[envLen] =
'/'; envLen++;}
1027 strcpy(envBuff+envLen,
".xrd/");
1028 xP = envBuff+envLen+5;
1032 if ((sP = getenv(
"XRDCONFIGFN")))
1033 {sprintf(xP,
"=/conf/%s.cf", myProg);
1039 sprintf(xP,
"=/core/%s", myProg);
1044 if ((sP = getenv(
"XRDLOGDIR")))
1045 {sprintf(xP,
"=/logs/%s", myProg);
1052 sprintf(xP,
"=/proc/%s", myProg);
1053 sprintf(manBuff,
"/proc/%d", getpid());
1059 envLen = snprintf(envBuff,
sizeof(envBuff),
"pid=%d&host=%s&inst=%s&ver=%s"
1060 "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1061 static_cast<int>(getpid()), ProtInfo.myName,
1062 ProtInfo.myInst, XrdVSTRING, HomePath,
1063 (getenv(
"XRDCONFIGFN") ? getenv(
"XRDCONFIGFN") :
""),
1068 if (pidfn && (Slash = rindex(pidfn,
'/')))
1069 {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1070 else {strcpy(manBuff, ProtInfo.AdmPath); pidP = manBuff+strlen(ProtInfo.AdmPath);}
1074 snprintf(pidP,
sizeof(manBuff)-(pidP-manBuff),
"/%s.%s.env",
1075 ProtInfo.myProg, ProtInfo.myInst);
1080 if ((envFD =
open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1081 {
Log.
Emsg(
"Config", errno,
"create envfile", manBuff);
1087 if (
write(envFD, envBuff, envLen) < 0)
1088 Log.
Emsg(
"Config", errno,
"write to envfile", manBuff);
1096 bool XrdConfig::PidFile(
const char *clpFN,
bool optbg)
1099 char *ppath, buff[32], pidFN[1200];
1100 const char *xop = 0;
1114 {xop =
"create"; snprintf(pidFN,
sizeof(pidFN),
"%s", ppath); errno = rc;}
1115 else {snprintf(pidFN,
sizeof(pidFN),
"%s/%s.pid", ppath, myProg);
1117 if ((xfd =
open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1119 else {
if (
write(xfd,buff,snprintf(buff,
sizeof(buff),
"%d",
1120 static_cast<int>(getpid()))) < 0) xop =
"write";
1128 if (xop)
Log.
Emsg(
"Config", errno, xop, pidFN);
1136 void XrdConfig::setCFG(
bool start)
1141 if (!ConfigFN || !(*ConfigFN))
1165 if (*ConfigFN !=
'/')
1166 {
char cwdBuff[1024];
1167 if (getcwd(cwdBuff,
sizeof(cwdBuff)-strlen(ConfigFN)-2))
1168 {
int n = strlen(cwdBuff);
1169 if (cwdBuff[n-1] !=
'/') cwdBuff[n++] =
'/';
1170 strcpy(cwdBuff+n, ConfigFN);
1172 ConfigFN = strdup(cwdBuff);
1185 const char *cvec[] = {
"*** ", myProg,
" config from '", ConfigFN,
"':", 0 };
1193 int XrdConfig::setFDL()
1200 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1201 return Log.
Emsg(
"Config", errno,
"get FD limit");
1205 if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1206 rlim.rlim_cur = maxFD;
1207 else rlim.rlim_cur = rlim.rlim_max;
1208 #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1209 if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1211 #if defined(__linux__)
1213 unsigned int epoll_max_fd = (INT_MAX /
sizeof(
struct epoll_event));
1214 if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1216 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1217 return Log.
Emsg(
"Config", errno,
"set FD limit");
1221 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1222 return Log.
Emsg(
"Config", errno,
"get FD limit");
1226 ProtInfo.ConnMax = rlim.rlim_cur;
1227 sprintf(buff,
"%d", ProtInfo.ConnMax);
1228 Log.
Say(
"Config maximum number of connections restricted to ", buff);
1232 #if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1234 {
if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1235 Log.
Emsg(
"Config", errno,
"get core limit");
1236 else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1237 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1238 Log.
Emsg(
"Config", errno,
"set core limit");
1245 #if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1249 if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1250 return Log.
Emsg(
"Config", errno,
"get thread limit");
1254 int nthr =
static_cast<int>(rlim.rlim_cur);
1255 if (nthr < 8192 || ProtInfo.DebugON)
1256 {sprintf(buff,
"%d",
static_cast<int>(rlim.rlim_cur));
1257 Log.
Say(
"Config maximum number of threads restricted to ", buff);
1268 int XrdConfig::Setup(
char *dfltp,
char *libProt)
1271 int xport, protNum = 0;
1275 if (setFDL())
return 1;
1279 #if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1280 {
int sokFD, setON = 1;
1281 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1283 &setON,
sizeof(setON));
1284 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
1320 for (
int i = 0; i < cp->
numP; i++)
1323 "configured with a TLS-only port "
1324 "but TLS is not configured!");
1328 xport = (cp->dotls ? PortTLS : PortTCP);
1329 ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1332 if (cp->port < 0)
return 1;
1333 for (
int i = 1; i < cp->
numP; i++)
1334 if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1342 ProtInfo.myName, Firstcp->port,
1343 ProtInfo.myInst, ProtInfo.myProg, mySitName);
1349 xport = (strcmp(
"xroot", Firstcp->proname) ? 0 : Firstcp->port);
1358 while((cp = Firstcp))
1359 {
for (
int i = 0; i < cp->
numP; i++)
1360 {
if (cp->portVec[i] < 0)
continue;
1361 if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1362 else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1363 if (!theNet)
return 1;
1364 if (!(cp->portVec[i])) arbNet = theNet;
1367 ProtInfo.
Port = theNet->Port();
1368 ProtInfo.NetTCP = theNet;
1369 ProtInfo.WSize = theNet->WSize();
1376 cp->
parms, &ProtInfo,
1378 if (!protNum)
return 1;
1381 if (!strcmp(
"http", cp->
proname) && xport)
1382 {
for (
int i = 0; i < cp->
numP; i++)
1383 {
if (cp->portVec[i] == xport) {xport = 0;
break;}}
1386 Firstcp = cp->
Next;
delete cp;
1398 if (repDest[0] != 0 && repOpts)
1399 ProtInfo.Stats->Report(repDest, repInt, repOpts);
1410 int XrdConfig::SetupAPath()
1419 else ProtInfo.AdmPath = AdminPath;
1428 {
Log.
Emsg(
"Config", rc,
"create admin path", AdminPath);
1434 return ASocket(AdminPath,
"admin", (mode_t)AdminMode);
1441 bool XrdConfig::SetupTLS()
1446 if (!caDir && !caFile && !tlsNoVer)
1448 Log.
Say(
"Config failure: the tlsca directive was not specified!");
1449 else Log.
Say(
"Config failure: the tlsca directive did not specify "
1450 "a certdir or certfile!");
1472 static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1476 if (!xrdTLS.isOK())
return false;
1488 void XrdConfig::Usage(
int rc)
1494 std::cerr <<
"\nUsage: " <<myProg <<
" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1495 "[-k {n|sz|sig}] [-l [=]<fn>] [-n name] [-p <port>] [-P <prot>] [-L <libprot>]\n"
1496 "[-R] [-s pidfile] [-S site] [-v] [-z] [<prot_options>]" <<std::endl;
1497 _exit(rc > 0 ? rc : 0);
1520 mode_t mode = S_IRWXU;
1525 if (!pval || !pval[0])
1526 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1531 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1535 if (AdminPath) free(AdminPath);
1536 AdminPath = strdup(pval);
1540 if ((val =
Config.GetWord()) && val[0])
1541 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1542 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1546 AdminMode = ProtInfo.AdmMode = mode;
1570 if (!(val =
Config.GetWord()))
1571 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1573 if (!strcmp(val,
"host")) ishost = 1;
1574 else if (!strcmp(val,
"netgroup")) ishost = 0;
1575 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1579 if (!(val =
Config.GetWord()))
1580 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1585 if (ishost) Police->AddHost(val);
1586 else Police->AddNetGroup(val);
1611 {
eDest->
Say(
"Config warning: command line homepath cannot be overridden.");
1618 if (HomePath) {free(HomePath); HomePath = 0;}
1623 return (HomePath ? 0 : 1);
1644 static const long long minBSZ = 1024*1024*2+1;
1645 static const long long maxBSZ = 1024*1024*1024;
1650 if (!(val =
Config.GetWord()))
1651 {
eDest->
Emsg(
"Config",
"buffer memory limit not specified");
return 1;}
1653 if (!strcmp(
"maxbsz", val))
1654 {
if (!(val =
Config.GetWord()))
1655 {
eDest->
Emsg(
"Config",
"max buffer size not specified");
return 1;}
1659 if (!(val =
Config.GetWord()))
return 0;
1663 (
long long)1024*1024))
return 1;
1665 if ((val =
Config.GetWord()))
1691 long long minV = 1024, maxV = 1024LL*1024LL;
1695 if ((val =
Config.GetWord()))
1696 {
if (!strcmp(val,
"strict"))
1699 }
else isStrict =
false;
1703 {
eDest->
Emsg(
"Config",
"file descriptor limit not specified");
return 1;}
1708 maxFD =
static_cast<unsigned int>(fdVal);
1742 int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1743 int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1;
1745 struct netopts {
const char *opname;
int hasarg;
int opval;
1746 int *oploc;
const char *etxt;}
1749 {
"assumev4", 0, 1, &V_assumev4,
"option"},
1750 {
"keepalive", 0, 1, &V_keep,
"option"},
1751 {
"nokeepalive",0, 0, &V_keep,
"option"},
1752 {
"kaparms", 4, 0, &V_keep,
"option"},
1753 {
"buffsz", 1, 0, &V_blen,
"network buffsz"},
1754 {
"cache", 2, 0, &V_ct,
"cache time"},
1755 {
"dnr", 0, 0, &V_nodnr,
"option"},
1756 {
"nodnr", 0, 1, &V_nodnr,
"option"},
1757 {
"dyndns", 0, 1, &V_dyndns,
"option"},
1758 {
"nodyndns", 0, 0, &V_dyndns,
"option"},
1759 {
"routes", 3, 1, 0,
"routes"},
1760 {
"rpipa", 0, 1, &v_rpip,
"rpipa"},
1761 {
"norpipa", 0, 0, &v_rpip,
"norpipa"},
1762 {
"tls", 0, 1, &V_istls,
"option"}
1764 int numopts =
sizeof(ntopts)/
sizeof(
struct netopts);
1766 if (!(val =
Config.GetWord()))
1767 {
eDest->
Emsg(
"Config",
"net option not specified");
return 1;}
1770 {
for (i = 0; i < numopts; i++)
1771 if (!strcmp(val, ntopts[i].opname))
1772 {
if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1773 else {
if (!(val =
Config.GetWord()))
1775 ntopts[i].opname,
"argument missing");
1778 if (ntopts[i].hasarg == 4)
1779 {
if (xnkap(
eDest, val))
return 1;
1782 if (ntopts[i].hasarg == 3)
1783 {
if (!strcmp(val,
"split"))
1785 else if (!strcmp(val,
"common"))
1787 else if (!strcmp(val,
"local"))
1789 else {
eDest->
Emsg(
"Config",
"Invalid routes argument -",val);
1792 if (!(val =
Config.GetWord())|| !(*val))
break;
1793 if (strcmp(val,
"use"))
continue;
1794 if (!(val =
Config.GetWord())|| !(*val))
1795 {
eDest->
Emsg(
"Config",
"network routes i/f names "
1803 if (ntopts[i].hasarg == 2)
1806 *ntopts[i].oploc = n;
1810 *ntopts[i].oploc = (int)llp;
1816 eDest->
Say(
"Config warning: ignoring invalid net option '",val,
"'.");
1817 else if (!val)
break;
1822 {
if (V_blen >= 0) TLS_Blen = V_blen;
1826 if (V_blen >= 0) Net_Blen = V_blen;
1833 {
if (V_dyndns && V_ct < 0) V_ct = 0;
1866 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1873 if (!(karg = val))
return 0;
1874 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1910 if (!val || !val[0])
1911 {
eDest->
Emsg(
"Config",
"pidpath not specified");
return 1;}
1915 if (PidPath) free(PidPath);
1916 PidPath = strdup(val);
1937 {
int rc, istls = 0, pnum = 0;
1938 char *val, cport[32];
1940 do {
if (!(val =
Config.GetWord()))
1941 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
1942 if (strcmp(
"tls", val) || istls)
break;
1946 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
1948 if ((val =
Config.GetWord()) && !strcmp(
"if", val))
1950 ProtInfo.myInst, myProg)) <= 0)
1951 {
if (!rc)
Config.noEcho();
return (rc < 0);}
1954 if (istls) PortTLS = pnum;
1955 else PortTCP = PortUDP = pnum;
1982 char *val, *parms, *lib, proname[64], buff[2048];
1986 do {
if (!(val =
Config.GetWord()))
1987 {
eDest->
Emsg(
"Config",
"protocol name not specified");
return 1;}
1988 if (dotls || strcmp(
"tls", val))
break;
1992 if (strlen(val) >
sizeof(proname)-1)
1993 {
eDest->
Emsg(
"Config",
"protocol name is too long");
return 1;}
1994 strcpy(proname, val);
1996 if ((val = index(proname,
':')))
2001 if (!(val =
Config.GetWord()))
2002 {
eDest->
Emsg(
"Config",
"protocol library not specified");
return 1;}
2003 if (!strcmp(
"*", val)) lib = 0;
2004 else if (*val ==
'+')
2005 {
if (strcmp(val,
"+port"))
2006 {
eDest->
Emsg(
"Config",
"invalid library specification -",val);
2009 if ((cpp = Firstcp))
2010 do {
if (!strcmp(proname, cpp->
proname))
2011 {
if (cpp->
AddPort(portnum, dotls))
return 0;
2012 eDest->
Emsg(
"Config",
"port add limit exceeded!");
2015 }
while((cpp = cpp->
Next));
2016 eDest->
Emsg(
"Config",
"protocol",proname,
"not previously defined!");
2019 else lib = strdup(val);
2024 if (!lib && Firstcp && strcmp(proname, Firstcp->proname))
2026 snprintf(eBuff,
sizeof(eBuff),
"the %s protocol is '%s' not '%s'; "
2027 "assuming you meant '%s'",
2028 (Firstcp->libpath ?
"assigned" :
"builtin"),
2029 Firstcp->proname, proname, Firstcp->proname);
2030 eDest->
Say(
"Config warning: ", eBuff,
" but please correct "
2031 "the following directive!");
2032 snprintf(proname,
sizeof(proname),
"%s", Firstcp->proname);
2036 if (!
Config.GetRest(buff,
sizeof(buff)))
2037 {
eDest->
Emsg(
"Config",
"Too many parms for protocol", proname);
2040 parms = (*buff ? strdup(buff) : 0);
2042 if ((cpp = Firstcp))
2043 do {
if (!strcmp(proname, cpp->
proname))
2044 {cpp->
Reset(lib, parms, portnum, dotls);
2047 }
while((cpp = cpp->
Next));
2049 cpp =
new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2050 if (!lib) {cpp->
Next = Firstcp; Firstcp = cpp;
2051 if (!Lastcp) Lastcp = cpp;
2053 else {
if (Lastcp) Lastcp->
Next = cpp;
2083 static struct repopts {
const char *opname;
int opval;} rpopts[] =
2098 int i, neg, numopts =
sizeof(rpopts)/
sizeof(
struct repopts);
2101 if (!(val =
Config.GetWord()))
2102 {
eDest->
Emsg(
"Config",
"report parameters not specified");
return 1;}
2106 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2107 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2113 if ((cp = (
char *)index(val,
',')))
2115 {
eDest->
Emsg(
"Config",
"malformed report destination -",val);
return 1;}
2116 else { repDest[1] = cp+1; *cp =
'\0';}
2119 for (i = 0; i < 2; i++)
2120 {
if (!(val = repDest[i]))
break;
2121 if (*val !=
'/' && (!(cp = index(val, (
int)
':')) || !atoi(cp+1)))
2122 {
eDest->
Emsg(
"Config",
"report dest port missing or invalid in",val);
2125 repDest[i] = strdup(val);
2130 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2131 {
eDest->
Emsg(
"Config",
"Warning, report dests are identical.");
2132 free(repDest[1]); repDest[1] = 0;
2138 if (!strcmp(
"every", val))
2139 {
if (!(val =
Config.GetWord()))
2140 {
eDest->
Emsg(
"Config",
"report every value not specified");
return 1;}
2148 {
if (!strcmp(val,
"off")) repOpts = 0;
2149 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2150 for (i = 0; i < numopts; i++)
2151 {
if (!strcmp(val, rpopts[i].opname))
2152 {
if (neg) repOpts &= ~rpopts[i].opval;
2153 else repOpts |= rpopts[i].opval;
2158 eDest->
Say(
"Config warning: ignoring invalid report option '",val,
"'.");
2203 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2204 struct schedopts {
const char *opname;
int minv;
int *oploc;
2205 const char *opmsg;} scopts[] =
2207 {
"stksz", 0, 0,
"sched stksz"},
2208 {
"mint", 1, &V_mint,
"sched mint"},
2209 {
"maxt", 1, &V_maxt,
"sched maxt"},
2210 {
"avlt", 1, &V_avlt,
"sched avlt"},
2211 {
"core", 1, 0,
"sched core"},
2212 {
"idle", 0, &V_idle,
"sched idle"}
2214 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2216 if (!(val =
Config.GetWord()))
2217 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2220 {
for (i = 0; i < numopts; i++)
2221 if (!strcmp(val, scopts[i].opname))
2222 {
if (!(val =
Config.GetWord()))
2223 {
eDest->
Emsg(
"Config",
"sched", scopts[i].opname,
2224 "value not specified");
2227 if (*scopts[i].opname ==
'i')
2229 &ppp, scopts[i].minv))
return 1;
2231 else if (*scopts[i].opname ==
'c')
2232 {
if (!strcmp(
"asis", val)) coreV = -1;
2233 else if (!strcmp(
"max", val)) coreV = 1;
2234 else if (!strcmp(
"off", val)) coreV = 0;
2235 else {
eDest->
Emsg(
"Config",
"invalid sched core value -",val);
2239 else if (*scopts[i].opname ==
's')
2241 &lpp, scopts[i].minv))
return 1;
2246 &ppp,scopts[i].minv))
return 1;
2247 *scopts[i].oploc = ppp;
2251 eDest->
Say(
"Config warning: ignoring invalid sched option '",val,
"'.");
2258 {
if (V_mint > 0 && V_mint > V_maxt)
2259 {
eDest->
Emsg(
"Config",
"sched mint must be less than maxt");
2262 if (V_avlt > 0 && V_avlt > V_maxt)
2263 {
eDest->
Emsg(
"Config",
"sched avlt must be less than maxt");
2293 if (!(val =
Config.GetWord()))
2294 {
eDest->
Emsg(
"Config",
"sitename value not specified");
return 1;}
2296 if (mySitName)
eDest->
Emsg(
"Config",
"sitename already specified, using '",
2319 char *val, parms[2048];
2324 if ((val =
Config.GetWord()))
2325 {
if (!strcmp(val,
"++"))
2334 {
eDest->
Emsg(
"Config",
"tcpmonlib not specified");
return 1;}
2339 {
eDest->
Emsg(
"Config",
"tcpmonlib path is not absolute");
return 1;}
2347 if (!
Config.GetRest(parms,
sizeof(parms)))
2348 {
eDest->
Emsg(
"Config",
"tcpmonlib parameters too long");
return 1;}
2356 tmoInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
2385 if (!(val =
Config.GetWord()))
2386 {
eDest->
Emsg(
"Config",
"tls cert path not specified");
return 1;}
2389 {
eDest->
Emsg(
"Config",
"tls cert path not absolute");
return 1;}
2391 if (tlsCert) free(tlsCert);
2392 tlsCert = strdup(val);
2393 if (tlsKey) free(tlsKey);
2396 if (!(val =
Config.GetWord()))
return 0;
2399 {tlsKey = strdup(val);
2400 if (!(val =
Config.GetWord()))
return 0;
2403 do {
if (!strcmp(val,
"detail")) SSLmsgs =
true;
2404 else if (!strcmp(val,
"nodetail")) SSLmsgs =
false;
2405 else if (!strcmp(val,
"hsto" ))
2406 {
if (!(val =
Config.GetWord()))
2407 {
eDest->
Emsg(
"Config",
"tls hsto value not specified");
2414 else {
eDest->
Emsg(
"Config",
"invalid tls option -",val);
return 1;}
2415 }
while ((val =
Config.GetWord()));
2452 char *val, **cadest, kword[16];
2456 if (!(val =
Config.GetWord()))
2457 {
eDest->
Emsg(
"Config",
"tlsca parameter not specified");
return 1;}
2460 if (!strcmp(val,
"noverify"))
2462 if (caDir) {free(caDir); caDir = 0;}
2463 if (caFile) {free(caFile); caFile = 0;}
2469 do {
if (!strcmp(val,
"proxies") || !strcmp(
"noproxies", val))
2475 if (strlen(val) >= (
int)
sizeof(kword))
2476 {
eDest->
Emsg(
"Config",
"Invalid tlsca parameter -", val);
2481 if (!(val =
Config.GetWord()))
2482 {
eDest->
Emsg(
"Config",
"tlsca", kword,
"value not specified");
2485 if ((isdir = !strcmp(kword,
"certdir"))
2486 || !strcmp(kword,
"certfile"))
2488 {
eDest->
Emsg(
"Config",
"tlsca",kword,
"path is not absolute.");
2491 cadest = (isdir ? &caDir : &caFile);
2492 if (*cadest) free(*cadest);
2493 *cadest = strdup(val);
2495 else if (!strcmp(kword,
"crlcheck"))
2499 else if ( strcmp(val,
"external"))
2500 {
eDest->
Emsg(
"Config",
"Invalid tlsca crlcheck "
2505 else if (!strcmp(kword,
"log"))
2506 {
if (!strcmp(val,
"off"))
2508 else if (!strcmp(val,
"failure"))
2510 else {
eDest->
Emsg(
"Config",
"Invalid tlsca log argument -",val);
2514 else if (!strcmp(kword,
"refresh"))
2517 if (rt < 60) rt = 60;
2518 else if (rt % 60) rt += 60;
2522 else if (!strcmp(kword,
"verdepth"))
2527 else {
eDest->
Emsg(
"Config",
"invalid tlsca option -",kword);
return 1;}
2529 }
while((val =
Config.GetWord()));
2549 char *val, *ciphers;
2551 if (!(val =
Config.GetWord()))
2552 {
eDest->
Emsg(
"Config",
"tlsciphers parameter not specified");
return 1;}
2554 ciphers = strdup(val);
2556 if ((val =
Config.GetWord()))
2557 {
eDest->
Emsg(
"Config",
"Invalid tlsciphers argument -",val);
2591 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2592 struct tmoopts {
const char *opname;
int istime;
int minv;
2593 int *oploc;
const char *etxt;}
2596 {
"read", 1, 1, &V_read,
"timeout read"},
2597 {
"hail", 1, 1, &V_hail,
"timeout hail"},
2598 {
"idle", 1, 0, &V_idle,
"timeout idle"},
2599 {
"kill", 1, 0, &V_kill,
"timeout kill"}
2601 int numopts =
sizeof(tmopts)/
sizeof(
struct tmoopts);
2603 if (!(val =
Config.GetWord()))
2604 {
eDest->
Emsg(
"Config",
"timeout option not specified");
return 1;}
2607 {
for (i = 0; i < numopts; i++)
2608 if (!strcmp(val, tmopts[i].opname))
2609 {
if (!(val =
Config.GetWord()))
2610 {
eDest->
Emsg(
"Config",
"timeout", tmopts[i].opname,
2611 "value not specified");
2614 rc = (tmopts[i].istime ?
2620 *tmopts[i].oploc = ppp;
2624 eDest->
Say(
"Config warning: ignoring invalid timeout option '",val,
"'.");
2630 if (V_read > 0) ProtInfo.readWait = V_read*1000;
2631 if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
2632 if (V_idle >= 0) ProtInfo.idleWait = V_idle;
2654 static struct traceopts {
const char *opname;
int opval;} tropts[] =
2671 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
2673 if (!(val =
Config.GetWord()))
2674 {
eDest->
Emsg(
"Config",
"trace option not specified");
return 1;}
2676 {
if (!strcmp(val,
"off")) trval = 0;
2677 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2678 for (i = 0; i < numopts; i++)
2679 {
if (!strcmp(val, tropts[i].opname))
2681 if (tropts[i].opval) trval &= ~tropts[i].opval;
2683 else if (tropts[i].opval) trval |= tropts[i].opval;
2689 eDest->
Say(
"Config warning: ignoring invalid trace option '",val,
"'.");
void Usage(const char *msg)
static XrdSysError eDest(0,"crypto_")
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_HSTO(cOpts, hstv)
#define TLS_SET_REFINT(cOpts, refi)
void Set(int maxmem=-1, int minw=-1)
void Reset(char *ln, char *pp, int np=-1, bool to=false)
XrdConfigProt(char *pn, char *ln, char *pp, int np=-1, bool to=false)
bool AddPort(int pnum, bool isTLS)
int ConfigXeq(char *var, XrdOucStream &Config, XrdSysError *eDest=0)
int Configure(int argc, char **argv)
int BindSD(int port, const char *contype="tcp")
static void SetAssumeV4(bool newVal)
static int Setup(int maxfds, int idlewt)
static void setKWT(int wkSec, int kwSec)
const sockaddr * SockAddr()
const char * Name(const char *eName=0, const char **eText=0)
static void SetCache(int keeptime)
static void SetDynDNS(bool onoff)
static void SetRPIPA(bool rval)
static int GetIF(XrdOucTList **ifList, const char **eText=0)
static void Routing(netType nettype)
static void SetMsgs(XrdSysError *erp)
static bool SetIFNames(char *ifnames)
static int ProtoID(const char *pName)
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
void setDomain(const char *dname)
void setDefaults(int options, int buffsz=0)
void PutInt(const char *varname, long value)
static int Export(const char *Var, const char *Val)
void * GetPtr(const char *varname)
void PutPtr(const char *varname, void *value)
void Put(const char *varname, const char *value)
static bool configLog(XrdSysError &eDest, configLogInfo &logInfo)
static const char * Set(const char *name, int maxlen=15)
static XrdOucString * Capture()
const char * c_str() const
static char * parseHome(XrdSysError &eDest, XrdOucStream &Config, int &mode)
static const mode_t pathMode
static char * genPath(const char *path, const char *inst, const char *psfx=0)
static int ReLink(const char *path, const char *target, mode_t mode=0)
static const char * InstName(int TranOpt=0)
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
static int makePath(char *path, mode_t mode, bool reset=false)
static bool PidFile(XrdSysError &eDest, const char *path)
static void makeHome(XrdSysError &eDest, const char *inst)
static void Undercover(XrdSysError &eDest, int noLog, int *pipeFD=0)
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2p(XrdSysError &, const char *ptype, const char *val, bool anyOK=true)
static int Setup(int numfd)
static const int PortoMax
static int Port(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi)
static int Load(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi, bool istls)
int Stats(char *buff, int blen, int do_sync=0)
void setParms(int minw, int maxw, int avlt, int maxi, int once=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
void AddMsg(const char *msg)
int ParseKeep(const char *arg)
static void setDebug(XrdSysError *erp)
static void setStackSize(size_t stsz, bool force=false)
static int FmtUname(char *buff, int blen)
XrdOucPinKing< XrdTcpMonPin > KingPin
XrdTcpMonInfo(const char *drctv, const char *cfn, XrdSysError &errR)
static const int crlRS
Bits to shift vdept.
static void SetDefaultCiphers(const char *ciphers)
static const uint64_t servr
This is a server context.
static const uint64_t nopxy
Do not allow proxy certs.
static const uint64_t logVF
Log verify failures.
static const uint64_t crlFC
Full crl chain checking.
static const uint64_t crlON
Enables crl checking.
static const uint64_t crlRF
Mask to isolate crl refresh in min.
static void SetMsgCB(msgCB_t cbP)
static const int dbgSIO
Turn debugging in for socket I/O.
static const int dbgSOK
Turn debugging in for socket operations.
static const int dbgALL
Turn debugging for everything.
static const int dbgCTX
Turn debugging in for context operations.
static void SetDebug(int opts, XrdSysLogger *logP=0)
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
static INT to(const char *buffer)