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 if (!(myName = myIPAddr->
Name(0, &temp))) myName =
"";
584 ProtInfo.myName = myName;
585 ProtInfo.myAddr = myIPAddr->
SockAddr();
587 ProtInfo.myProg = myProg;
593 sprintf(buff,
"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName);
594 myInstance = strdup(buff);
596 myInstance += strlen(xrdInst);
605 LogInfo.
iName = myInsName;
606 LogInfo.
cfgFn = ConfigFN;
617 {
Log.
Emsg(
"Config",
"Unable to determine host name; ",
618 (temp ? temp :
"reason unknown"),
619 "; execution terminated.");
629 strcpy(buff,
"Starting on ");
641 {
Log.
Emsg(
"Config",myName,
"does not appear to be registered in the DNS.");
642 Log.
Emsg(
"Config",
"Verify that the '/etc/hosts' file is correct and "
643 "this machine is registered in DNS.");
644 Log.
Emsg(
"Config",
"Execution continues but connection failures may occur.");
646 }
else if (!(
myDomain = index(myName,
'.')))
647 Log.
Say(
"Config warning: this hostname, ", myName,
648 ", is registered without a domain qualification.");
652 Firstcp = Lastcp =
new XrdConfigProt(strdup(dfltProt), libProt, 0);
656 Log.
Say(
"++++++ ", myInstance,
" initialization started.");
660 devNull = XrdSysFD_Open(
"/dev/null", O_RDONLY);
662 {
Log.
Emsg(
"Config", errno,
"open '/dev/null' which is required!");
669 {
Log.
Say(
"Config using configuration file ", ConfigFN);
670 ProtInfo.ConfigFN = ConfigFN;
673 if (clPort >= 0) PortTCP = clPort;
674 if (ProtInfo.DebugON)
681 NoGo |= SetupAPath();
686 {
if (!tlsCert) ProtInfo.tlsCtx= 0;
687 else {
Log.
Say(
"++++++ ", myInstance,
" TLS initialization started.");
689 {
Log.
Say(
"------ ",myInstance,
" TLS initialization ended.");
694 Log.
Say(
"------ ",myInstance,
" TLS initialization failed.");
704 {
Log.
Say(
"Config TLS port specification ignored; TLS not configured!");
708 ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
724 {
Log.
Emsg(
"Config",
"Unable to determine interface addresses!");
730 if ((myInsName || HomePath)
735 if (!PidFile(pidFN, optbg)) NoGo = 1;
739 if (!NoGo) Manifest(pidFN);
743 if (!NoGo) NoGo = Setup(dfltProt, libProt);
752 if (tmoInfo && !NoGo)
754 if (!theGS)
Log.
Say(
"Config warning: TCP monitoring not enabled; "
755 "tcpmonlib plugin not loaded!");
756 else {tmoInfo->theEnv.PutPtr(
"TcpMon.gStream*", theGS);
757 TcpMonPin = tmoInfo->KingPin.Load(
"TcpMonPin");
767 int status = NoGo ? 1 : 0;
768 if(
write( pipeFD[1], &status,
sizeof( status ) )) {};
775 temp = (NoGo ?
" initialization failed." :
" initialization completed.");
776 sprintf(buff,
"%s:%d", myInstance, PortTCP);
777 Log.
Say(
"------ ", buff, temp);
779 {strcat(buff,
" running ");
797 if (
eDest) dynamic = 1;
811 TS_Xeq(
"adminpath", xapath);
813 TS_Xeq(
"homepath", xhpath);
817 TS_Xeq(
"protocol", xprot);
820 TS_Xeq(
"tcpmonlib", xtcpmon);
824 TS_Xeq(
"tlsciphers", xtlsci);
829 eDest->
Say(
"Config warning: ignoring unknown xrd directive '",var,
"'.");
841 int XrdConfig::ASocket(
const char *path,
const char *fname, mode_t mode)
843 struct sockaddr_un unixvar;
844 int plen = strlen(path), flen = strlen(fname);
848 if ((plen + flen + 3) > (
int)
sizeof(unixvar.sun_path))
849 {
Log.
Emsg(
"Config",
"admin path", path,
"too long");
884 int XrdConfig::ConfigProc()
887 int cfgFD, retc, NoGo = 0;
893 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
894 {
Log.
Emsg(
"Config", errno,
"open config file", ConfigFN);
901 while((var =
Config.GetMyFirstWord()))
902 if (!strncmp(var,
"xrd.", 4)
903 || !strcmp (var,
"all.adminpath")
904 || !strcmp (var,
"all.pidpath")
905 || !strcmp (var,
"all.sitename" ))
906 if (ConfigXeq(var+4,
Config)) {
Config.Echo(); NoGo = 1;}
910 if ((retc =
Config.LastError()))
911 NoGo =
Log.
Emsg(
"Config", retc,
"read config file", ConfigFN);
923 XrdInet *XrdConfig::getNet(
int port,
bool isTLS)
925 int the_Opts, the_Blen;
929 for (
int i = 0; i < (int)NetTCP.size(); i++)
930 if (port == NetTCP[i]->Port())
return NetTCP[i];
935 NetTCP.push_back(newNet);
940 {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
942 the_Opts = Net_Opts; the_Blen = Net_Blen;
944 if (the_Opts || the_Blen) newNet->
setDefaults(the_Opts, the_Blen);
952 if (newNet->
BindSD(port,
"tcp") == 0)
return newNet;
961 int XrdConfig::getUG(
char *parm, uid_t &newUid, gid_t &newGid)
968 {
Log.
Emsg(
"Config",
"-R user not specified.");
return 0;}
971 {
if (!(newUid = atol(parm)))
972 {
Log.
Emsg(
"Config",
"-R", parm,
"is invalid");
return 0;}
973 pp = getpwuid(newUid);
975 else pp = getpwnam(parm);
980 {
Log.
Emsg(
"Config", errno,
"retrieve -R user password entry");
983 if (!(newUid = pp->pw_uid))
984 {
Log.
Emsg(
"Config",
"-R", parm,
"is still unacceptably a superuser!");
995 void XrdConfig::Manifest(
const char *pidfn)
998 char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1003 if (!getcwd(pwdBuff,
sizeof(pwdBuff)))
1004 {
Log.
Emsg(
"Config",
"Unable to get current working directory!");
1010 if (HomePath) free(HomePath);
1011 HomePath = strdup(pwdBuff);
1015 strcpy(envBuff, ProtInfo.AdmPath);
1016 envLen = strlen(envBuff);
1017 if (envBuff[envLen-1] !=
'/') {envBuff[envLen] =
'/'; envLen++;}
1018 strcpy(envBuff+envLen,
".xrd/");
1019 xP = envBuff+envLen+5;
1023 if ((sP = getenv(
"XRDCONFIGFN")))
1024 {sprintf(xP,
"=/conf/%s.cf", myProg);
1030 sprintf(xP,
"=/core/%s", myProg);
1035 if ((sP = getenv(
"XRDLOGDIR")))
1036 {sprintf(xP,
"=/logs/%s", myProg);
1043 sprintf(xP,
"=/proc/%s", myProg);
1044 sprintf(manBuff,
"/proc/%d", getpid());
1050 envLen = snprintf(envBuff,
sizeof(envBuff),
"pid=%d&host=%s&inst=%s&ver=%s"
1051 "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1052 static_cast<int>(getpid()), ProtInfo.myName,
1053 ProtInfo.myInst, XrdVSTRING, HomePath,
1054 (getenv(
"XRDCONFIGFN") ? getenv(
"XRDCONFIGFN") :
""),
1059 if (pidfn && (Slash = rindex(pidfn,
'/')))
1060 {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1061 else {strcpy(manBuff, ProtInfo.AdmPath); pidP = manBuff+strlen(ProtInfo.AdmPath);}
1065 snprintf(pidP,
sizeof(manBuff)-(pidP-manBuff),
"/%s.%s.env",
1066 ProtInfo.myProg, ProtInfo.myInst);
1071 if ((envFD =
open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1072 {
Log.
Emsg(
"Config", errno,
"create envfile", manBuff);
1078 if (
write(envFD, envBuff, envLen) < 0)
1079 Log.
Emsg(
"Config", errno,
"write to envfile", manBuff);
1087 bool XrdConfig::PidFile(
const char *clpFN,
bool optbg)
1090 char *ppath, buff[32], pidFN[1200];
1091 const char *xop = 0;
1105 {xop =
"create"; snprintf(pidFN,
sizeof(pidFN),
"%s", ppath); errno = rc;}
1106 else {snprintf(pidFN,
sizeof(pidFN),
"%s/%s.pid", ppath, myProg);
1108 if ((xfd =
open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1110 else {
if (
write(xfd,buff,snprintf(buff,
sizeof(buff),
"%d",
1111 static_cast<int>(getpid()))) < 0) xop =
"write";
1119 if (xop)
Log.
Emsg(
"Config", errno, xop, pidFN);
1127 void XrdConfig::setCFG(
bool start)
1132 if (!ConfigFN || !(*ConfigFN))
1156 if (*ConfigFN !=
'/')
1157 {
char cwdBuff[1024];
1158 if (getcwd(cwdBuff,
sizeof(cwdBuff)-strlen(ConfigFN)-2))
1159 {
int n = strlen(cwdBuff);
1160 if (cwdBuff[n-1] !=
'/') cwdBuff[n++] =
'/';
1161 strcpy(cwdBuff+n, ConfigFN);
1163 ConfigFN = strdup(cwdBuff);
1176 const char *cvec[] = {
"*** ", myProg,
" config from '", ConfigFN,
"':", 0 };
1184 int XrdConfig::setFDL()
1191 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1192 return Log.
Emsg(
"Config", errno,
"get FD limit");
1196 if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1197 rlim.rlim_cur = maxFD;
1198 else rlim.rlim_cur = rlim.rlim_max;
1199 #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1200 if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1202 #if defined(__linux__)
1204 unsigned int epoll_max_fd = (INT_MAX /
sizeof(
struct epoll_event));
1205 if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1207 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1208 return Log.
Emsg(
"Config", errno,
"set FD limit");
1212 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1213 return Log.
Emsg(
"Config", errno,
"get FD limit");
1217 ProtInfo.ConnMax = rlim.rlim_cur;
1218 sprintf(buff,
"%d", ProtInfo.ConnMax);
1219 Log.
Say(
"Config maximum number of connections restricted to ", buff);
1223 #if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1225 {
if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1226 Log.
Emsg(
"Config", errno,
"get core limit");
1227 else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1228 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1229 Log.
Emsg(
"Config", errno,
"set core limit");
1236 #if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1240 if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1241 return Log.
Emsg(
"Config", errno,
"get thread limit");
1245 int nthr =
static_cast<int>(rlim.rlim_cur);
1246 if (nthr < 8192 || ProtInfo.DebugON)
1247 {sprintf(buff,
"%d",
static_cast<int>(rlim.rlim_cur));
1248 Log.
Say(
"Config maximum number of threads restricted to ", buff);
1259 int XrdConfig::Setup(
char *dfltp,
char *libProt)
1262 int xport, protNum = 0;
1266 if (setFDL())
return 1;
1270 #if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1271 {
int sokFD, setON = 1;
1272 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1274 &setON,
sizeof(setON));
1275 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
1311 for (
int i = 0; i < cp->
numP; i++)
1314 "configured with a TLS-only port "
1315 "but TLS is not configured!");
1319 xport = (cp->dotls ? PortTLS : PortTCP);
1320 ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1323 if (cp->port < 0)
return 1;
1324 for (
int i = 1; i < cp->
numP; i++)
1325 if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1333 ProtInfo.myName, Firstcp->port,
1334 ProtInfo.myInst, ProtInfo.myProg, mySitName);
1340 xport = (strcmp(
"xroot", Firstcp->proname) ? 0 : Firstcp->port);
1349 while((cp = Firstcp))
1350 {
for (
int i = 0; i < cp->
numP; i++)
1351 {
if (cp->portVec[i] < 0)
continue;
1352 if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1353 else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1354 if (!theNet)
return 1;
1355 if (!(cp->portVec[i])) arbNet = theNet;
1358 ProtInfo.
Port = theNet->Port();
1359 ProtInfo.NetTCP = theNet;
1360 ProtInfo.WSize = theNet->WSize();
1367 cp->
parms, &ProtInfo,
1369 if (!protNum)
return 1;
1372 if (!strcmp(
"http", cp->
proname) && xport)
1373 {
for (
int i = 0; i < cp->
numP; i++)
1374 {
if (cp->portVec[i] == xport) {xport = 0;
break;}}
1377 Firstcp = cp->
Next;
delete cp;
1389 if (repDest[0] != 0 && repOpts)
1390 ProtInfo.Stats->Report(repDest, repInt, repOpts);
1401 int XrdConfig::SetupAPath()
1410 else ProtInfo.AdmPath = AdminPath;
1419 {
Log.
Emsg(
"Config", rc,
"create admin path", AdminPath);
1425 return ASocket(AdminPath,
"admin", (mode_t)AdminMode);
1432 bool XrdConfig::SetupTLS()
1437 if (!caDir && !caFile && !tlsNoVer)
1439 Log.
Say(
"Config failure: the tlsca directive was not specified!");
1440 else Log.
Say(
"Config failure: the tlsca directive did not specify "
1441 "a certdir or certfile!");
1463 static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1467 if (!xrdTLS.isOK())
return false;
1479 void XrdConfig::Usage(
int rc)
1485 std::cerr <<
"\nUsage: " <<myProg <<
" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1486 "[-k {n|sz|sig}] [-l [=]<fn>] [-n name] [-p <port>] [-P <prot>] [-L <libprot>]\n"
1487 "[-R] [-s pidfile] [-S site] [-v] [-z] [<prot_options>]" <<std::endl;
1488 _exit(rc > 0 ? rc : 0);
1511 mode_t mode = S_IRWXU;
1516 if (!pval || !pval[0])
1517 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1522 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1526 if (AdminPath) free(AdminPath);
1527 AdminPath = strdup(pval);
1531 if ((val =
Config.GetWord()) && val[0])
1532 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1533 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1537 AdminMode = ProtInfo.AdmMode = mode;
1561 if (!(val =
Config.GetWord()))
1562 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1564 if (!strcmp(val,
"host")) ishost = 1;
1565 else if (!strcmp(val,
"netgroup")) ishost = 0;
1566 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1570 if (!(val =
Config.GetWord()))
1571 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1576 if (ishost) Police->AddHost(val);
1577 else Police->AddNetGroup(val);
1602 {
eDest->
Say(
"Config warning: command line homepath cannot be overridden.");
1609 if (HomePath) {free(HomePath); HomePath = 0;}
1614 return (HomePath ? 0 : 1);
1635 static const long long minBSZ = 1024*1024*2+1;
1636 static const long long maxBSZ = 1024*1024*1024;
1641 if (!(val =
Config.GetWord()))
1642 {
eDest->
Emsg(
"Config",
"buffer memory limit not specified");
return 1;}
1644 if (!strcmp(
"maxbsz", val))
1645 {
if (!(val =
Config.GetWord()))
1646 {
eDest->
Emsg(
"Config",
"max buffer size not specified");
return 1;}
1650 if (!(val =
Config.GetWord()))
return 0;
1654 (
long long)1024*1024))
return 1;
1656 if ((val =
Config.GetWord()))
1682 long long minV = 1024, maxV = 1024LL*1024LL;
1686 if ((val =
Config.GetWord()))
1687 {
if (!strcmp(val,
"strict"))
1690 }
else isStrict =
false;
1694 {
eDest->
Emsg(
"Config",
"file descriptor limit not specified");
return 1;}
1699 maxFD =
static_cast<unsigned int>(fdVal);
1733 int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1734 int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1;
1736 struct netopts {
const char *opname;
int hasarg;
int opval;
1737 int *oploc;
const char *etxt;}
1740 {
"assumev4", 0, 1, &V_assumev4,
"option"},
1741 {
"keepalive", 0, 1, &V_keep,
"option"},
1742 {
"nokeepalive",0, 0, &V_keep,
"option"},
1743 {
"kaparms", 4, 0, &V_keep,
"option"},
1744 {
"buffsz", 1, 0, &V_blen,
"network buffsz"},
1745 {
"cache", 2, 0, &V_ct,
"cache time"},
1746 {
"dnr", 0, 0, &V_nodnr,
"option"},
1747 {
"nodnr", 0, 1, &V_nodnr,
"option"},
1748 {
"dyndns", 0, 1, &V_dyndns,
"option"},
1749 {
"nodyndns", 0, 0, &V_dyndns,
"option"},
1750 {
"routes", 3, 1, 0,
"routes"},
1751 {
"rpipa", 0, 1, &v_rpip,
"rpipa"},
1752 {
"norpipa", 0, 0, &v_rpip,
"norpipa"},
1753 {
"tls", 0, 1, &V_istls,
"option"}
1755 int numopts =
sizeof(ntopts)/
sizeof(
struct netopts);
1757 if (!(val =
Config.GetWord()))
1758 {
eDest->
Emsg(
"Config",
"net option not specified");
return 1;}
1761 {
for (i = 0; i < numopts; i++)
1762 if (!strcmp(val, ntopts[i].opname))
1763 {
if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1764 else {
if (!(val =
Config.GetWord()))
1766 ntopts[i].opname,
"argument missing");
1769 if (ntopts[i].hasarg == 4)
1770 {
if (xnkap(
eDest, val))
return 1;
1773 if (ntopts[i].hasarg == 3)
1774 {
if (!strcmp(val,
"split"))
1776 else if (!strcmp(val,
"common"))
1778 else if (!strcmp(val,
"local"))
1780 else {
eDest->
Emsg(
"Config",
"Invalid routes argument -",val);
1783 if (!(val =
Config.GetWord())|| !(*val))
break;
1784 if (strcmp(val,
"use"))
continue;
1785 if (!(val =
Config.GetWord())|| !(*val))
1786 {
eDest->
Emsg(
"Config",
"network routes i/f names "
1794 if (ntopts[i].hasarg == 2)
1797 *ntopts[i].oploc = n;
1801 *ntopts[i].oploc = (int)llp;
1807 eDest->
Say(
"Config warning: ignoring invalid net option '",val,
"'.");
1808 else if (!val)
break;
1813 {
if (V_blen >= 0) TLS_Blen = V_blen;
1817 if (V_blen >= 0) Net_Blen = V_blen;
1824 {
if (V_dyndns && V_ct < 0) V_ct = 0;
1857 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1864 if (!(karg = val))
return 0;
1865 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1901 if (!val || !val[0])
1902 {
eDest->
Emsg(
"Config",
"pidpath not specified");
return 1;}
1906 if (PidPath) free(PidPath);
1907 PidPath = strdup(val);
1928 {
int rc, istls = 0, pnum = 0;
1929 char *val, cport[32];
1931 do {
if (!(val =
Config.GetWord()))
1932 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
1933 if (strcmp(
"tls", val) || istls)
break;
1937 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
1939 if ((val =
Config.GetWord()) && !strcmp(
"if", val))
1941 ProtInfo.myInst, myProg)) <= 0)
1942 {
if (!rc)
Config.noEcho();
return (rc < 0);}
1945 if (istls) PortTLS = pnum;
1946 else PortTCP = PortUDP = pnum;
1973 char *val, *parms, *lib, proname[64], buff[2048];
1977 do {
if (!(val =
Config.GetWord()))
1978 {
eDest->
Emsg(
"Config",
"protocol name not specified");
return 1;}
1979 if (dotls || strcmp(
"tls", val))
break;
1983 if (strlen(val) >
sizeof(proname)-1)
1984 {
eDest->
Emsg(
"Config",
"protocol name is too long");
return 1;}
1985 strcpy(proname, val);
1987 if ((val = index(proname,
':')))
1992 if (!(val =
Config.GetWord()))
1993 {
eDest->
Emsg(
"Config",
"protocol library not specified");
return 1;}
1994 if (!strcmp(
"*", val)) lib = 0;
1995 else if (*val ==
'+')
1996 {
if (strcmp(val,
"+port"))
1997 {
eDest->
Emsg(
"Config",
"invalid library specification -",val);
2000 if ((cpp = Firstcp))
2001 do {
if (!strcmp(proname, cpp->
proname))
2002 {
if (cpp->
AddPort(portnum, dotls))
return 0;
2003 eDest->
Emsg(
"Config",
"port add limit exceeded!");
2006 }
while((cpp = cpp->
Next));
2007 eDest->
Emsg(
"Config",
"protocol",proname,
"not previously defined!");
2010 else lib = strdup(val);
2015 if (!lib && Firstcp && strcmp(proname, Firstcp->proname))
2017 snprintf(eBuff,
sizeof(eBuff),
"the %s protocol is '%s' not '%s'; "
2018 "assuming you meant '%s'",
2019 (Firstcp->libpath ?
"assigned" :
"builtin"),
2020 Firstcp->proname, proname, Firstcp->proname);
2021 eDest->
Say(
"Config warning: ", eBuff,
" but please correct "
2022 "the following directive!");
2023 snprintf(proname,
sizeof(proname),
"%s", Firstcp->proname);
2027 if (!
Config.GetRest(buff,
sizeof(buff)))
2028 {
eDest->
Emsg(
"Config",
"Too many parms for protocol", proname);
2031 parms = (*buff ? strdup(buff) : 0);
2033 if ((cpp = Firstcp))
2034 do {
if (!strcmp(proname, cpp->
proname))
2035 {cpp->
Reset(lib, parms, portnum, dotls);
2038 }
while((cpp = cpp->
Next));
2040 cpp =
new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2041 if (!lib) {cpp->
Next = Firstcp; Firstcp = cpp;
2042 if (!Lastcp) Lastcp = cpp;
2044 else {
if (Lastcp) Lastcp->
Next = cpp;
2074 static struct repopts {
const char *opname;
int opval;} rpopts[] =
2089 int i, neg, numopts =
sizeof(rpopts)/
sizeof(
struct repopts);
2092 if (!(val =
Config.GetWord()))
2093 {
eDest->
Emsg(
"Config",
"report parameters not specified");
return 1;}
2097 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2098 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2104 if ((cp = (
char *)index(val,
',')))
2106 {
eDest->
Emsg(
"Config",
"malformed report destination -",val);
return 1;}
2107 else { repDest[1] = cp+1; *cp =
'\0';}
2110 for (i = 0; i < 2; i++)
2111 {
if (!(val = repDest[i]))
break;
2112 if (*val !=
'/' && (!(cp = index(val, (
int)
':')) || !atoi(cp+1)))
2113 {
eDest->
Emsg(
"Config",
"report dest port missing or invalid in",val);
2116 repDest[i] = strdup(val);
2121 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2122 {
eDest->
Emsg(
"Config",
"Warning, report dests are identical.");
2123 free(repDest[1]); repDest[1] = 0;
2129 if (!strcmp(
"every", val))
2130 {
if (!(val =
Config.GetWord()))
2131 {
eDest->
Emsg(
"Config",
"report every value not specified");
return 1;}
2139 {
if (!strcmp(val,
"off")) repOpts = 0;
2140 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2141 for (i = 0; i < numopts; i++)
2142 {
if (!strcmp(val, rpopts[i].opname))
2143 {
if (neg) repOpts &= ~rpopts[i].opval;
2144 else repOpts |= rpopts[i].opval;
2149 eDest->
Say(
"Config warning: ignoring invalid report option '",val,
"'.");
2194 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2195 struct schedopts {
const char *opname;
int minv;
int *oploc;
2196 const char *opmsg;} scopts[] =
2198 {
"stksz", 0, 0,
"sched stksz"},
2199 {
"mint", 1, &V_mint,
"sched mint"},
2200 {
"maxt", 1, &V_maxt,
"sched maxt"},
2201 {
"avlt", 1, &V_avlt,
"sched avlt"},
2202 {
"core", 1, 0,
"sched core"},
2203 {
"idle", 0, &V_idle,
"sched idle"}
2205 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2207 if (!(val =
Config.GetWord()))
2208 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2211 {
for (i = 0; i < numopts; i++)
2212 if (!strcmp(val, scopts[i].opname))
2213 {
if (!(val =
Config.GetWord()))
2214 {
eDest->
Emsg(
"Config",
"sched", scopts[i].opname,
2215 "value not specified");
2218 if (*scopts[i].opname ==
'i')
2220 &ppp, scopts[i].minv))
return 1;
2222 else if (*scopts[i].opname ==
'c')
2223 {
if (!strcmp(
"asis", val)) coreV = -1;
2224 else if (!strcmp(
"max", val)) coreV = 1;
2225 else if (!strcmp(
"off", val)) coreV = 0;
2226 else {
eDest->
Emsg(
"Config",
"invalid sched core value -",val);
2230 else if (*scopts[i].opname ==
's')
2232 &lpp, scopts[i].minv))
return 1;
2237 &ppp,scopts[i].minv))
return 1;
2238 *scopts[i].oploc = ppp;
2242 eDest->
Say(
"Config warning: ignoring invalid sched option '",val,
"'.");
2249 {
if (V_mint > 0 && V_mint > V_maxt)
2250 {
eDest->
Emsg(
"Config",
"sched mint must be less than maxt");
2253 if (V_avlt > 0 && V_avlt > V_maxt)
2254 {
eDest->
Emsg(
"Config",
"sched avlt must be less than maxt");
2284 if (!(val =
Config.GetWord()))
2285 {
eDest->
Emsg(
"Config",
"sitename value not specified");
return 1;}
2287 if (mySitName)
eDest->
Emsg(
"Config",
"sitename already specified, using '",
2310 char *val, parms[2048];
2315 if ((val =
Config.GetWord()))
2316 {
if (!strcmp(val,
"++"))
2325 {
eDest->
Emsg(
"Config",
"tcpmonlib not specified");
return 1;}
2330 {
eDest->
Emsg(
"Config",
"tcpmonlib path is not absolute");
return 1;}
2338 if (!
Config.GetRest(parms,
sizeof(parms)))
2339 {
eDest->
Emsg(
"Config",
"tcpmonlib parameters too long");
return 1;}
2347 tmoInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
2376 if (!(val =
Config.GetWord()))
2377 {
eDest->
Emsg(
"Config",
"tls cert path not specified");
return 1;}
2380 {
eDest->
Emsg(
"Config",
"tls cert path not absolute");
return 1;}
2382 if (tlsCert) free(tlsCert);
2383 tlsCert = strdup(val);
2384 if (tlsKey) free(tlsKey);
2387 if (!(val =
Config.GetWord()))
return 0;
2390 {tlsKey = strdup(val);
2391 if (!(val =
Config.GetWord()))
return 0;
2394 do {
if (!strcmp(val,
"detail")) SSLmsgs =
true;
2395 else if (!strcmp(val,
"nodetail")) SSLmsgs =
false;
2396 else if (!strcmp(val,
"hsto" ))
2397 {
if (!(val =
Config.GetWord()))
2398 {
eDest->
Emsg(
"Config",
"tls hsto value not specified");
2405 else {
eDest->
Emsg(
"Config",
"invalid tls option -",val);
return 1;}
2406 }
while ((val =
Config.GetWord()));
2443 char *val, **cadest, kword[16];
2447 if (!(val =
Config.GetWord()))
2448 {
eDest->
Emsg(
"Config",
"tlsca parameter not specified");
return 1;}
2451 if (!strcmp(val,
"noverify"))
2453 if (caDir) {free(caDir); caDir = 0;}
2454 if (caFile) {free(caFile); caFile = 0;}
2460 do {
if (!strcmp(val,
"proxies") || !strcmp(
"noproxies", val))
2466 if (strlen(val) >= (
int)
sizeof(kword))
2467 {
eDest->
Emsg(
"Config",
"Invalid tlsca parameter -", val);
2472 if (!(val =
Config.GetWord()))
2473 {
eDest->
Emsg(
"Config",
"tlsca", kword,
"value not specified");
2476 if ((isdir = !strcmp(kword,
"certdir"))
2477 || !strcmp(kword,
"certfile"))
2479 {
eDest->
Emsg(
"Config",
"tlsca",kword,
"path is not absolute.");
2482 cadest = (isdir ? &caDir : &caFile);
2483 if (*cadest) free(*cadest);
2484 *cadest = strdup(val);
2486 else if (!strcmp(kword,
"crlcheck"))
2490 else if ( strcmp(val,
"external"))
2491 {
eDest->
Emsg(
"Config",
"Invalid tlsca crlcheck "
2496 else if (!strcmp(kword,
"log"))
2497 {
if (!strcmp(val,
"off"))
2499 else if (!strcmp(val,
"failure"))
2501 else {
eDest->
Emsg(
"Config",
"Invalid tlsca log argument -",val);
2505 else if (!strcmp(kword,
"refresh"))
2508 if (rt < 60) rt = 60;
2509 else if (rt % 60) rt += 60;
2513 else if (!strcmp(kword,
"verdepth"))
2518 else {
eDest->
Emsg(
"Config",
"invalid tlsca option -",kword);
return 1;}
2520 }
while((val =
Config.GetWord()));
2540 char *val, *ciphers;
2542 if (!(val =
Config.GetWord()))
2543 {
eDest->
Emsg(
"Config",
"tlsciphers parameter not specified");
return 1;}
2545 ciphers = strdup(val);
2547 if ((val =
Config.GetWord()))
2548 {
eDest->
Emsg(
"Config",
"Invalid tlsciphers argument -",val);
2582 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2583 struct tmoopts {
const char *opname;
int istime;
int minv;
2584 int *oploc;
const char *etxt;}
2587 {
"read", 1, 1, &V_read,
"timeout read"},
2588 {
"hail", 1, 1, &V_hail,
"timeout hail"},
2589 {
"idle", 1, 0, &V_idle,
"timeout idle"},
2590 {
"kill", 1, 0, &V_kill,
"timeout kill"}
2592 int numopts =
sizeof(tmopts)/
sizeof(
struct tmoopts);
2594 if (!(val =
Config.GetWord()))
2595 {
eDest->
Emsg(
"Config",
"timeout option not specified");
return 1;}
2598 {
for (i = 0; i < numopts; i++)
2599 if (!strcmp(val, tmopts[i].opname))
2600 {
if (!(val =
Config.GetWord()))
2601 {
eDest->
Emsg(
"Config",
"timeout", tmopts[i].opname,
2602 "value not specified");
2605 rc = (tmopts[i].istime ?
2611 *tmopts[i].oploc = ppp;
2615 eDest->
Say(
"Config warning: ignoring invalid timeout option '",val,
"'.");
2621 if (V_read > 0) ProtInfo.readWait = V_read*1000;
2622 if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
2623 if (V_idle >= 0) ProtInfo.idleWait = V_idle;
2645 static struct traceopts {
const char *opname;
int opval;} tropts[] =
2662 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
2664 if (!(val =
Config.GetWord()))
2665 {
eDest->
Emsg(
"Config",
"trace option not specified");
return 1;}
2667 {
if (!strcmp(val,
"off")) trval = 0;
2668 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2669 for (i = 0; i < numopts; i++)
2670 {
if (!strcmp(val, tropts[i].opname))
2672 if (tropts[i].opval) trval &= ~tropts[i].opval;
2674 else if (tropts[i].opval) trval |= tropts[i].opval;
2680 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)