46#include <sys/resource.h>
53#include "XrdVersion.hh"
94#if defined(__linux__) || defined(__GNU__)
95#include <netinet/tcp.h>
101#include <AvailabilityMacros.h>
142void TlsError(
const char *tid,
const char *msg,
bool sslmsg)
150 const char *XrdConfig::TraceID =
"Config";
156#define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
187 {
for (
int i = 0; i <
numP; i++)
188 if (pnum == portVec[i])
189 {tlsVec[i] = isTLS;
return true;}
191 portVec[
numP] = pnum; tlsVec[
numP] = isTLS;
196void Reset(
char *ln,
char *pp,
int np=-1,
bool to=
false)
201 memset(portVec, 0,
sizeof(portVec));
203 memset(tlsVec, 0,
sizeof(tlsVec));
211 {memset(portVec, 0,
sizeof(portVec)); port = np;
212 memset(tlsVec, 0,
sizeof(tlsVec)); dotls = to;
257 AdminPath= strdup(
"/tmp");
259 PidPath = strdup(
"/tmp");
284 Firstcp = Lastcp = 0;
286 ProtInfo.eDest = &
Log;
289 ProtInfo.Sched = &
Sched;
290 ProtInfo.ConfigFN= 0;
292 ProtInfo.AdmPath = AdminPath;
293 ProtInfo.AdmMode = AdminMode;
294 ProtInfo.theEnv = &theEnv;
295 ProtInfo.xrdFlags= 0;
298 memset(ProtInfo.rsvd3, 0,
sizeof(ProtInfo.rsvd3));
300 ProtInfo.ConnMax = -1;
301 ProtInfo.readWait = 3*1000;
302 ProtInfo.idleWait = 0;
303 ProtInfo.hailWait =30*1000;
304 ProtInfo.DebugON = 0;
307 ProtInfo.tlsPort = 0;
327 const char *xrdInst=
"XRDINSTANCE=";
329 int retc, NoGo = 0, clPort = -1;
331 char c, buff[512], *dfltProt, *libProt = 0;
335 extern int optind, opterr;
337 int pipeFD[2] = {-1, -1};
338 const char *pidFN = 0;
339 static const int myMaxc = 80;
340 char **urArgv, *myArgv[myMaxc], argBuff[myMaxc*3+8];
341 char *argbP = argBuff, *argbE = argbP+
sizeof(argBuff)-4;
343 int myArgc = 1, urArgc = argc, i;
344 bool noV6, ipV4 =
false, ipV6 =
false, rootChk =
true, optbg =
false;
349 for (
int k = 1; k < argc; k++)
350 {CmdLine +=
' '; CmdLine += argv[k];}
354 retc = strlen(argv[0]);
355 while(retc--)
if (argv[0][retc] ==
'/')
break;
356 myProg = &argv[0][retc+1];
363 {
char *p = dfltProt = strdup(myProg);
364 while(*p && (*p ==
'.' || *p ==
'-')) p++;
366 {
char *dot = index(p,
'.'), *dash = index(p,
'-');
367 if (dot && (dot < dash || !dash)) p = dot;
368 else if (dash) p = dash;
371 if (!strcmp(
"xrootd", dfltProt)) dfltProt[5] = 0;
372 else if (!strcmp(
"cmsd", dfltProt)) dfltProt[3] = 0;
382 {
if (*(argv[i]) ==
'-' && *(argv[i]+1) ==
'+')
383 {
int n = strlen(argv[i]+2), j = i+1, k = 1;
384 if (urArgc == argc) urArgc = i;
385 if (n) memcpy(buff, argv[i]+2, (n > 256 ? 256 : n));
386 strcpy(&(buff[n]),
".argv**");
387 while(j < argc && (*(argv[j]) !=
'-' || *(argv[j]+1) !=
'+')) j++;
388 urArgv =
new char*[j-i+1];
391 while(i < j) urArgv[k++] = argv[i++];
393 theEnv.
PutPtr(buff, urArgv);
394 strcpy(&(buff[n]),
".argc");
395 theEnv.
PutInt(buff,
static_cast<long>(k));
398 theEnv.
PutPtr(
"argv[0]", argv[0]);
404 if (argc > 1 &&
'-' == *argv[1])
405 while ((c = getopt(urArgc,argv,
":a:A:bc:dhHI:k:l:L:n:N:p:P:R:s:S:vw:W:z"))
406 && ((
unsigned char)c != 0xff))
409 case 'a':
if (AdminPath) free(AdminPath);
410 AdminPath = strdup(optarg);
411 AdminMode = ProtInfo.AdmMode = S_IRWXU;
414 case 'A':
if (AdminPath) free(AdminPath);
415 AdminPath = strdup(optarg);
416 AdminMode = ProtInfo.AdmMode = S_IRWXU | S_IRWXG;
419 case 'b': optbg =
true;
421 case 'c':
if (ConfigFN) free(ConfigFN);
422 ConfigFN = strdup(optarg);
425 ProtInfo.DebugON = 1;
432 case 'I':
if (!strcmp(
"v4", optarg)) {ipV4 =
true; ipV6 =
false;}
433 else if (!strcmp(
"v6", optarg)) {ipV4 =
false; ipV6 =
true;}
434 else {
Log.
Emsg(
"Config",
"Invalid -I argument -",optarg);
439 {
Log.
Emsg(
"Config",
"Invalid -k argument -",optarg);
443 case 'l': LogInfo.
logArg = optarg;
445 case 'L':
if (!*optarg)
446 {
Log.
Emsg(
"Config",
"Protocol library path not specified.");
449 if (libProt) free(libProt);
450 libProt = strdup(optarg);
452 case 'n': myInsName = (!strcmp(optarg,
"anon")||!strcmp(optarg,
"default")
459 case 'P':
if (dfltProt) free(dfltProt);
460 dfltProt = strdup(optarg);
462 case 'R':
if (!(getUG(optarg, myUid, myGid)))
Usage(1);
465 case 's': pidFN = optarg;
467 case 'S': mySitName = optarg;
469 case ':': buff[0] =
'-'; buff[1] =
optopt; buff[2] = 0;
470 Log.
Emsg(
"Config", buff,
"parameter not specified.");
473 case 'v': std::cerr <<XrdVSTRING <<std::endl;
476 case 'w':
if (HomePath) free(HomePath);
477 HomePath = strdup(optarg);
481 case 'W':
if (HomePath) free(HomePath);
482 HomePath = strdup(optarg);
483 HomeMode = S_IRWXU | S_IRGRP | S_IXGRP;
486 case 'z': LogInfo.
hiRes =
true;
490 {
Log.
Emsg(
"Config",
"Long options are not supported.");
493 if (myArgc >= myMaxc || argbP >= argbE)
494 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
497 myArgv[myArgc++] = argbP;
498 *argbP++ =
'-'; *argbP++ =
optopt; *argbP++ = 0;
506 {
Log.
Emsg(
"Config",
"Command line adminpath is not absolute.");
512 if (HomePath && *HomePath !=
'/')
513 {
Log.
Emsg(
"Config",
"Command line home path is not absolute.");
520 if (ConfigFN) setCFG(
true);
526 else if (ipV6){
if (noV6)
Log.
Say(
"Config warning: ipV6 appears to be broken;"
527 " forced ipV6 mode not advised!");
530 else if (noV6)
Log.
Say(
"Config warning: ipV6 is misconfigured or "
531 "unavailable; reverting to ipV4.");
539 if (myGid && setegid(myGid))
540 {
Log.
Emsg(
"Config", errno,
"set effective gid"); exit(17);}
541 if (myUid && seteuid(myUid))
542 {
Log.
Emsg(
"Config", errno,
"set effective uid"); exit(17);}
546 if (rootChk && geteuid() == 0)
547 {
Log.
Emsg(
"Config",
"Security reasons prohibit running as "
548 "superuser; program is terminating.");
554 if (urArgc-
optind+2 >= myMaxc)
555 {
Log.
Emsg(
"Config",
"Too many command line arguments.");
563 ProtInfo.argc = myArgc;
564 ProtInfo.argv = myArgv;
573 if (pipe( pipeFD ) == -1)
574 {
Log.
Emsg(
"Config", errno,
"create a pipe"); exit(17);}
583 if (!(myName = myIPAddr->
Name(0, &temp))) myName =
"";
587 ProtInfo.myName = myName;
588 ProtInfo.myAddr = myIPAddr->
SockAddr();
590 ProtInfo.myProg = myProg;
596 sprintf(buff,
"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName);
597 myInstance = strdup(buff);
599 myInstance += strlen(xrdInst);
607 {LogInfo.
xrdEnv = &theEnv;
608 LogInfo.
iName = myInsName;
609 LogInfo.
cfgFn = ConfigFN;
620 {
Log.
Emsg(
"Config",
"Unable to determine host name; ",
621 (temp ? temp :
"reason unknown"),
622 "; execution terminated.");
632 strcpy(buff,
"Starting on ");
644 {
Log.
Emsg(
"Config",myName,
"does not appear to be registered in the DNS.");
645 Log.
Emsg(
"Config",
"Verify that the '/etc/hosts' file is correct and "
646 "this machine is registered in DNS.");
647 Log.
Emsg(
"Config",
"Execution continues but connection failures may occur.");
649 }
else if (!(myDomain = index(myName,
'.')))
650 Log.
Say(
"Config warning: this hostname, ", myName,
651 ", is registered without a domain qualification.");
655 Firstcp = Lastcp =
new XrdConfigProt(strdup(dfltProt), libProt, 0);
659 Log.
Say(
"++++++ ", myInstance,
" initialization started.");
663 devNull = XrdSysFD_Open(
"/dev/null", O_RDONLY);
665 {
Log.
Emsg(
"Config", errno,
"open '/dev/null' which is required!");
672 {
Log.
Say(
"Config using configuration file ", ConfigFN);
673 ProtInfo.ConfigFN = ConfigFN;
676 if (clPort >= 0) PortTCP = clPort;
677 if (ProtInfo.DebugON)
684 NoGo |= SetupAPath();
689 {
if (!tlsCert) ProtInfo.tlsCtx= 0;
690 else {
Log.
Say(
"++++++ ", myInstance,
" TLS initialization started.");
692 {
Log.
Say(
"------ ",myInstance,
" TLS initialization ended.");
697 Log.
Say(
"------ ",myInstance,
" TLS initialization failed.");
707 {
Log.
Say(
"Config TLS port specification ignored; TLS not configured!");
711 ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
727 {
Log.
Emsg(
"Config",
"Unable to determine interface addresses!");
733 if ((myInsName || HomePath)
738 if (!PidFile(pidFN, optbg)) NoGo = 1;
742 if (!NoGo) Manifest(pidFN);
746 if (!NoGo) NoGo = Setup(dfltProt, libProt);
755 if (tmoInfo && !NoGo)
756 {
void *theGS = theEnv.
GetPtr(
"TcpMon.gStream*");
757 if (!theGS)
Log.
Say(
"Config warning: TCP monitoring not enabled; "
758 "tcpmonlib plugin not loaded!");
770 int status = NoGo ? 1 : 0;
771 if(
write( pipeFD[1], &status,
sizeof( status ) )) {};
778 temp = (NoGo ?
" initialization failed." :
" initialization completed.");
779 sprintf(buff,
"%s:%d", myInstance, PortTCP);
780 Log.
Say(
"------ ", buff, temp);
782 {strcat(buff,
" running ");
800 if (
eDest) dynamic = 1;
814 TS_Xeq(
"adminpath", xapath);
816 TS_Xeq(
"homepath", xhpath);
820 TS_Xeq(
"protocol", xprot);
823 TS_Xeq(
"tcpmonlib", xtcpmon);
827 TS_Xeq(
"tlsciphers", xtlsci);
832 eDest->
Say(
"Config warning: ignoring unknown xrd directive '",var,
"'.");
844int XrdConfig::ASocket(
const char *path,
const char *fname, mode_t mode)
846 struct sockaddr_un unixvar;
847 int plen = strlen(path), flen = strlen(fname);
851 if ((plen + flen + 3) > (
int)
sizeof(unixvar.sun_path))
852 {
Log.
Emsg(
"Config",
"admin path", path,
"too long");
887int XrdConfig::ConfigProc()
890 int cfgFD, retc, NoGo = 0;
896 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
897 {
Log.
Emsg(
"Config", errno,
"open config file", ConfigFN);
904 while((var =
Config.GetMyFirstWord()))
905 if (!strncmp(var,
"xrd.", 4)
906 || !strcmp (var,
"all.adminpath")
907 || !strcmp (var,
"all.pidpath")
908 || !strcmp (var,
"all.sitename" ))
913 if ((retc =
Config.LastError()))
914 NoGo =
Log.
Emsg(
"Config", retc,
"read config file", ConfigFN);
926XrdInet *XrdConfig::getNet(
int port,
bool isTLS)
928 int the_Opts, the_Blen;
932 for (
int i = 0; i < (int)
NetTCP.size(); i++)
943 {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
945 the_Opts = Net_Opts; the_Blen = Net_Blen;
947 if (the_Opts || the_Blen) newNet->
setDefaults(the_Opts, the_Blen);
951 if (myDomain) newNet->
setDomain(myDomain);
955 if (newNet->
BindSD(port,
"tcp") == 0)
return newNet;
964int XrdConfig::getUG(
char *parm, uid_t &newUid, gid_t &newGid)
971 {
Log.
Emsg(
"Config",
"-R user not specified.");
return 0;}
974 {
if (!(newUid = atol(parm)))
975 {
Log.
Emsg(
"Config",
"-R", parm,
"is invalid");
return 0;}
976 pp = getpwuid(newUid);
978 else pp = getpwnam(parm);
983 {
Log.
Emsg(
"Config", errno,
"retrieve -R user password entry");
986 if (!(newUid = pp->pw_uid))
987 {
Log.
Emsg(
"Config",
"-R", parm,
"is still unacceptably a superuser!");
998void XrdConfig::Manifest(
const char *pidfn)
1001 char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1006 if (!getcwd(pwdBuff,
sizeof(pwdBuff)))
1007 {
Log.
Emsg(
"Config",
"Unable to get current working directory!");
1013 if (HomePath) free(HomePath);
1014 HomePath = strdup(pwdBuff);
1018 strcpy(envBuff, ProtInfo.AdmPath);
1019 envLen = strlen(envBuff);
1020 if (envBuff[envLen-1] !=
'/') {envBuff[envLen] =
'/'; envLen++;}
1021 strcpy(envBuff+envLen,
".xrd/");
1022 xP = envBuff+envLen+5;
1026 if ((sP = getenv(
"XRDCONFIGFN")))
1027 {sprintf(xP,
"=/conf/%s.cf", myProg);
1033 sprintf(xP,
"=/core/%s", myProg);
1038 if ((sP = getenv(
"XRDLOGDIR")))
1039 {sprintf(xP,
"=/logs/%s", myProg);
1046 sprintf(xP,
"=/proc/%s", myProg);
1047 sprintf(manBuff,
"/proc/%d", getpid());
1053 envLen = snprintf(envBuff,
sizeof(envBuff),
"pid=%d&host=%s&inst=%s&ver=%s"
1054 "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1055 static_cast<int>(getpid()), ProtInfo.myName,
1056 ProtInfo.myInst, XrdVSTRING, HomePath,
1057 (getenv(
"XRDCONFIGFN") ? getenv(
"XRDCONFIGFN") :
""),
1062 if (pidfn && (Slash = rindex(pidfn,
'/')))
1063 {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1064 else {strcpy(manBuff, ProtInfo.AdmPath); pidP = manBuff+strlen(ProtInfo.AdmPath);}
1068 snprintf(pidP,
sizeof(manBuff)-(pidP-manBuff),
"/%s.%s.env",
1069 ProtInfo.myProg, ProtInfo.myInst);
1074 if ((envFD =
open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1075 {
Log.
Emsg(
"Config", errno,
"create envfile", manBuff);
1081 if (
write(envFD, envBuff, envLen) < 0)
1082 Log.
Emsg(
"Config", errno,
"write to envfile", manBuff);
1090bool XrdConfig::PidFile(
const char *clpFN,
bool optbg)
1093 char *ppath, buff[32], pidFN[1200];
1094 const char *xop = 0;
1108 {xop =
"create"; snprintf(pidFN,
sizeof(pidFN),
"%s", ppath); errno = rc;}
1109 else {snprintf(pidFN,
sizeof(pidFN),
"%s/%s.pid", ppath, myProg);
1111 if ((xfd =
open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1113 else {
if (
write(xfd,buff,snprintf(buff,
sizeof(buff),
"%d",
1114 static_cast<int>(getpid()))) < 0) xop =
"write";
1122 if (xop)
Log.
Emsg(
"Config", errno, xop, pidFN);
1130void XrdConfig::setCFG(
bool start)
1135 if (!ConfigFN || !(*ConfigFN))
1159 if (*ConfigFN !=
'/')
1160 {
char cwdBuff[1024];
1161 if (getcwd(cwdBuff,
sizeof(cwdBuff)-strlen(ConfigFN)-2))
1162 {
int n = strlen(cwdBuff);
1163 if (cwdBuff[n-1] !=
'/') cwdBuff[n++] =
'/';
1164 strcpy(cwdBuff+n, ConfigFN);
1166 ConfigFN = strdup(cwdBuff);
1179 const char *cvec[] = {
"*** ", myProg,
" config from '", ConfigFN,
"':", 0 };
1187int XrdConfig::setFDL()
1194 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1195 return Log.
Emsg(
"Config", errno,
"get FD limit");
1199 if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1200 rlim.rlim_cur = maxFD;
1201 else rlim.rlim_cur = rlim.rlim_max;
1202#if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1203 if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1205#if defined(__linux__)
1207 unsigned int epoll_max_fd = (INT_MAX /
sizeof(
struct epoll_event));
1208 if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1210 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1211 return Log.
Emsg(
"Config", errno,
"set FD limit");
1215 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1216 return Log.
Emsg(
"Config", errno,
"get FD limit");
1220 ProtInfo.ConnMax = rlim.rlim_cur;
1221 sprintf(buff,
"%d", ProtInfo.ConnMax);
1222 Log.
Say(
"Config maximum number of connections restricted to ", buff);
1226#
if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1228 {
if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1229 Log.
Emsg(
"Config", errno,
"get core limit");
1230 else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1231 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1232 Log.
Emsg(
"Config", errno,
"set core limit");
1239#if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1243 if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1244 return Log.
Emsg(
"Config", errno,
"get thread limit");
1248 int nthr =
static_cast<int>(rlim.rlim_cur);
1249 if (nthr < 8192 || ProtInfo.DebugON)
1250 {sprintf(buff,
"%d", static_cast<int>(rlim.rlim_cur));
1251 Log.Say(
"Config maximum number of threads restricted to ", buff);
1262int XrdConfig::Setup(
char *dfltp,
char *libProt)
1265 int xport, protNum = 0;
1269 if (setFDL())
return 1;
1273#if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1274{
int sokFD, setON = 1;
1275 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1277 &setON,
sizeof(setON));
1278 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
1314 for (
int i = 0; i < cp->
numP; i++)
1317 "configured with a TLS-only port "
1318 "but TLS is not configured!");
1322 xport = (cp->dotls ? PortTLS : PortTCP);
1323 ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1326 if (cp->port < 0)
return 1;
1327 for (
int i = 1; i < cp->
numP; i++)
1328 if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1336 ProtInfo.myName, Firstcp->port,
1337 ProtInfo.myInst, ProtInfo.myProg, mySitName);
1343 xport = (strcmp(
"xroot", Firstcp->
proname) ? 0 : Firstcp->port);
1352 while((cp = Firstcp))
1353 {
for (
int i = 0; i < cp->
numP; i++)
1354 {
if (cp->portVec[i] < 0)
continue;
1355 if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1356 else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1357 if (!theNet)
return 1;
1358 if (!(cp->portVec[i])) arbNet = theNet;
1361 ProtInfo.
Port = theNet->Port();
1362 ProtInfo.NetTCP = theNet;
1363 ProtInfo.WSize = theNet->WSize();
1370 cp->
parms, &ProtInfo,
1372 if (!protNum)
return 1;
1375 if (!strcmp(
"http", cp->
proname) && xport)
1376 {
for (
int i = 0; i < cp->
numP; i++)
1377 {
if (cp->portVec[i] == xport) {xport = 0;
break;}}
1380 Firstcp = cp->
Next;
delete cp;
1392 if (repDest[0] != 0 && repOpts)
1393 ProtInfo.Stats->Report(repDest, repInt, repOpts);
1404int XrdConfig::SetupAPath()
1413 else ProtInfo.AdmPath = AdminPath;
1422 {
Log.
Emsg(
"Config", rc,
"create admin path", AdminPath);
1429 if (chmod(AdminPath, AdminMode & ~S_IWGRP))
1430 {
Log.
Emsg(
"Config", errno,
"set permission for admin path", AdminPath);
1438 return ASocket(AdminPath,
"admin", (mode_t)AdminMode);
1445bool XrdConfig::SetupTLS()
1450 if (!caDir && !caFile && !tlsNoVer)
1452 Log.
Say(
"Config failure: the tlsca directive was not specified!");
1453 else Log.
Say(
"Config failure: the tlsca directive did not specify "
1454 "a certdir or certfile!");
1476 static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1480 if (!xrdTLS.isOK())
return false;
1492void XrdConfig::Usage(
int rc)
1498 std::cerr <<
"\nUsage: " <<myProg <<
" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1499 "[-k {n|sz|sig}] [-l [=]<fn>] [-n <name>] [-N <hname>] [-p <port>]\n"
1500 "[-P <prot>] [-L <libprot>] [-R] [-s pidfile] [-S site] [-v] [-z]\n"
1501 "[<protocol_options>]" <<std::endl;
1502 _exit(rc > 0 ? rc : 0);
1525 mode_t mode = S_IRWXU;
1530 if (!pval || !pval[0])
1531 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1536 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1540 if (AdminPath) free(AdminPath);
1541 AdminPath = strdup(pval);
1545 if ((val =
Config.GetWord()) && val[0])
1546 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1547 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1551 AdminMode = ProtInfo.AdmMode = mode;
1575 if (!(val =
Config.GetWord()))
1576 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1578 if (!strcmp(val,
"host")) ishost = 1;
1579 else if (!strcmp(val,
"netgroup")) ishost = 0;
1580 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1584 if (!(val =
Config.GetWord()))
1585 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1590 if (ishost) Police->
AddHost(val);
1616 {
eDest->
Say(
"Config warning: command line homepath cannot be overridden.");
1623 if (HomePath) {free(HomePath); HomePath = 0;}
1628 return (HomePath ? 0 : 1);
1649 static const long long minBSZ = 1024*1024*2+1;
1650 static const long long maxBSZ = 1024*1024*1024;
1655 if (!(val =
Config.GetWord()))
1656 {
eDest->
Emsg(
"Config",
"buffer memory limit not specified");
return 1;}
1658 if (!strcmp(
"maxbsz", val))
1659 {
if (!(val =
Config.GetWord()))
1660 {
eDest->
Emsg(
"Config",
"max buffer size not specified");
return 1;}
1664 if (!(val =
Config.GetWord()))
return 0;
1668 (
long long)1024*1024))
return 1;
1670 if ((val =
Config.GetWord()))
1696 long long minV = 1024, maxV = 1024LL*1024LL;
1700 if ((val =
Config.GetWord()))
1701 {
if (!strcmp(val,
"strict"))
1704 }
else isStrict =
false;
1708 {
eDest->
Emsg(
"Config",
"file descriptor limit not specified");
return 1;}
1713 maxFD =
static_cast<unsigned int>(fdVal);
1747 int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1748 int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1;
1750 struct netopts {
const char *opname;
int hasarg;
int opval;
1751 int *oploc;
const char *etxt;}
1754 {
"assumev4", 0, 1, &V_assumev4,
"option"},
1755 {
"keepalive", 0, 1, &V_keep,
"option"},
1756 {
"nokeepalive",0, 0, &V_keep,
"option"},
1757 {
"kaparms", 4, 0, &V_keep,
"option"},
1758 {
"buffsz", 1, 0, &V_blen,
"network buffsz"},
1759 {
"cache", 2, 0, &V_ct,
"cache time"},
1760 {
"dnr", 0, 0, &V_nodnr,
"option"},
1761 {
"nodnr", 0, 1, &V_nodnr,
"option"},
1762 {
"dyndns", 0, 1, &V_dyndns,
"option"},
1763 {
"nodyndns", 0, 0, &V_dyndns,
"option"},
1764 {
"routes", 3, 1, 0,
"routes"},
1765 {
"rpipa", 0, 1, &v_rpip,
"rpipa"},
1766 {
"norpipa", 0, 0, &v_rpip,
"norpipa"},
1767 {
"tls", 0, 1, &V_istls,
"option"}
1769 int numopts =
sizeof(ntopts)/
sizeof(
struct netopts);
1771 if (!(val =
Config.GetWord()))
1772 {
eDest->
Emsg(
"Config",
"net option not specified");
return 1;}
1775 {
for (i = 0; i < numopts; i++)
1776 if (!strcmp(val, ntopts[i].opname))
1777 {
if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1778 else {
if (!(val =
Config.GetWord()))
1780 ntopts[i].opname,
"argument missing");
1783 if (ntopts[i].hasarg == 4)
1784 {
if (xnkap(
eDest, val))
return 1;
1787 if (ntopts[i].hasarg == 3)
1788 {
if (!strcmp(val,
"split"))
1790 else if (!strcmp(val,
"common"))
1792 else if (!strcmp(val,
"local"))
1794 else {
eDest->
Emsg(
"Config",
"Invalid routes argument -",val);
1797 if (!(val =
Config.GetWord())|| !(*val))
break;
1798 if (strcmp(val,
"use"))
continue;
1799 if (!(val =
Config.GetWord())|| !(*val))
1800 {
eDest->
Emsg(
"Config",
"network routes i/f names "
1808 if (ntopts[i].hasarg == 2)
1811 *ntopts[i].oploc = n;
1815 *ntopts[i].oploc = (int)llp;
1821 eDest->
Say(
"Config warning: ignoring invalid net option '",val,
"'.");
1822 else if (!val)
break;
1827 {
if (V_blen >= 0) TLS_Blen = V_blen;
1831 if (V_blen >= 0) Net_Blen = V_blen;
1838 {
if (V_dyndns && V_ct < 0) V_ct = 0;
1871 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1878 if (!(karg = val))
return 0;
1879 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1915 if (!val || !val[0])
1916 {
eDest->
Emsg(
"Config",
"pidpath not specified");
return 1;}
1920 if (PidPath) free(PidPath);
1921 PidPath = strdup(val);
1942{
int rc, istls = 0, pnum = 0;
1943 char *val, cport[32];
1945 do {
if (!(val =
Config.GetWord()))
1946 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
1947 if (strcmp(
"tls", val) || istls)
break;
1951 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
1953 if ((val =
Config.GetWord()) && !strcmp(
"if", val))
1955 ProtInfo.myInst, myProg)) <= 0)
1956 {
if (!rc)
Config.noEcho();
return (rc < 0);}
1959 if (istls) PortTLS = pnum;
1960 else PortTCP = PortUDP = pnum;
1987 char *val, *parms, *lib, proname[64], buff[2048];
1991 do {
if (!(val =
Config.GetWord()))
1992 {
eDest->
Emsg(
"Config",
"protocol name not specified");
return 1;}
1993 if (dotls || strcmp(
"tls", val))
break;
1997 if (strlen(val) >
sizeof(proname)-1)
1998 {
eDest->
Emsg(
"Config",
"protocol name is too long");
return 1;}
1999 strcpy(proname, val);
2001 if ((val = index(proname,
':')))
2006 if (!(val =
Config.GetWord()))
2007 {
eDest->
Emsg(
"Config",
"protocol library not specified");
return 1;}
2008 if (!strcmp(
"*", val)) lib = 0;
2009 else if (*val ==
'+')
2010 {
if (strcmp(val,
"+port"))
2011 {
eDest->
Emsg(
"Config",
"invalid library specification -",val);
2014 if ((cpp = Firstcp))
2015 do {
if (!strcmp(proname, cpp->
proname))
2016 {
if (cpp->
AddPort(portnum, dotls))
return 0;
2017 eDest->
Emsg(
"Config",
"port add limit exceeded!");
2020 }
while((cpp = cpp->
Next));
2021 eDest->
Emsg(
"Config",
"protocol",proname,
"not previously defined!");
2024 else lib = strdup(val);
2029 if (!lib && Firstcp && strcmp(proname, Firstcp->
proname))
2031 snprintf(eBuff,
sizeof(eBuff),
"the %s protocol is '%s' not '%s'; "
2032 "assuming you meant '%s'",
2033 (Firstcp->
libpath ?
"assigned" :
"builtin"),
2035 eDest->
Say(
"Config warning: ", eBuff,
" but please correct "
2036 "the following directive!");
2037 snprintf(proname,
sizeof(proname),
"%s", Firstcp->
proname);
2041 if (!
Config.GetRest(buff,
sizeof(buff)))
2042 {
eDest->
Emsg(
"Config",
"Too many parms for protocol", proname);
2045 parms = (*buff ? strdup(buff) : 0);
2047 if ((cpp = Firstcp))
2048 do {
if (!strcmp(proname, cpp->
proname))
2049 {cpp->
Reset(lib, parms, portnum, dotls);
2052 }
while((cpp = cpp->
Next));
2054 cpp =
new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2055 if (!lib) {cpp->
Next = Firstcp; Firstcp = cpp;
2056 if (!Lastcp) Lastcp = cpp;
2058 else {
if (Lastcp) Lastcp->
Next = cpp;
2088 static struct repopts {
const char *opname;
int opval;} rpopts[] =
2103 int i, neg, numopts =
sizeof(rpopts)/
sizeof(
struct repopts);
2106 if (!(val =
Config.GetWord()))
2107 {
eDest->
Emsg(
"Config",
"report parameters not specified");
return 1;}
2111 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2112 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2118 if ((cp = (
char *)index(val,
',')))
2120 {
eDest->
Emsg(
"Config",
"malformed report destination -",val);
return 1;}
2121 else { repDest[1] = cp+1; *cp =
'\0';}
2124 for (i = 0; i < 2; i++)
2125 {
if (!(val = repDest[i]))
break;
2126 if (*val !=
'/' && (!(cp = index(val, (
int)
':')) || !atoi(cp+1)))
2127 {
eDest->
Emsg(
"Config",
"report dest port missing or invalid in",val);
2130 repDest[i] = strdup(val);
2135 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2136 {
eDest->
Emsg(
"Config",
"Warning, report dests are identical.");
2137 free(repDest[1]); repDest[1] = 0;
2143 if (!strcmp(
"every", val))
2144 {
if (!(val =
Config.GetWord()))
2145 {
eDest->
Emsg(
"Config",
"report every value not specified");
return 1;}
2153 {
if (!strcmp(val,
"off")) repOpts = 0;
2154 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2155 for (i = 0; i < numopts; i++)
2156 {
if (!strcmp(val, rpopts[i].opname))
2157 {
if (neg) repOpts &= ~rpopts[i].opval;
2158 else repOpts |= rpopts[i].opval;
2163 eDest->
Say(
"Config warning: ignoring invalid report option '",val,
"'.");
2208 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2209 struct schedopts {
const char *opname;
int minv;
int *oploc;
2210 const char *opmsg;} scopts[] =
2212 {
"stksz", 0, 0,
"sched stksz"},
2213 {
"mint", 1, &V_mint,
"sched mint"},
2214 {
"maxt", 1, &V_maxt,
"sched maxt"},
2215 {
"avlt", 1, &V_avlt,
"sched avlt"},
2216 {
"core", 1, 0,
"sched core"},
2217 {
"idle", 0, &V_idle,
"sched idle"}
2219 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2221 if (!(val =
Config.GetWord()))
2222 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2225 {
for (i = 0; i < numopts; i++)
2226 if (!strcmp(val, scopts[i].opname))
2227 {
if (!(val =
Config.GetWord()))
2228 {
eDest->
Emsg(
"Config",
"sched", scopts[i].opname,
2229 "value not specified");
2232 if (*scopts[i].opname ==
'i')
2234 &ppp, scopts[i].minv))
return 1;
2236 else if (*scopts[i].opname ==
'c')
2237 {
if (!strcmp(
"asis", val)) coreV = -1;
2238 else if (!strcmp(
"max", val)) coreV = 1;
2239 else if (!strcmp(
"off", val)) coreV = 0;
2240 else {
eDest->
Emsg(
"Config",
"invalid sched core value -",val);
2244 else if (*scopts[i].opname ==
's')
2246 &lpp, scopts[i].minv))
return 1;
2251 &ppp,scopts[i].minv))
return 1;
2252 *scopts[i].oploc = ppp;
2256 eDest->
Say(
"Config warning: ignoring invalid sched option '",val,
"'.");
2263 {
if (V_mint > 0 && V_mint > V_maxt)
2264 {
eDest->
Emsg(
"Config",
"sched mint must be less than maxt");
2267 if (V_avlt > 0 && V_avlt > V_maxt)
2268 {
eDest->
Emsg(
"Config",
"sched avlt must be less than maxt");
2298 if (!(val =
Config.GetWord()))
2299 {
eDest->
Emsg(
"Config",
"sitename value not specified");
return 1;}
2301 if (mySitName)
eDest->
Emsg(
"Config",
"sitename already specified, using '",
2324 char *val, parms[2048];
2329 if ((val =
Config.GetWord()))
2330 {
if (!strcmp(val,
"++"))
2339 {
eDest->
Emsg(
"Config",
"tcpmonlib not specified");
return 1;}
2344 {
eDest->
Emsg(
"Config",
"tcpmonlib path is not absolute");
return 1;}
2352 if (!
Config.GetRest(parms,
sizeof(parms)))
2353 {
eDest->
Emsg(
"Config",
"tcpmonlib parameters too long");
return 1;}
2361 tmoInfo->
KingPin.
Add(path.c_str(), (*parms ? parms : 0), push);
2390 if (!(val =
Config.GetWord()))
2391 {
eDest->
Emsg(
"Config",
"tls cert path not specified");
return 1;}
2394 {
eDest->
Emsg(
"Config",
"tls cert path not absolute");
return 1;}
2396 if (tlsCert) free(tlsCert);
2397 tlsCert = strdup(val);
2398 if (tlsKey) free(tlsKey);
2401 if (!(val =
Config.GetWord()))
return 0;
2404 {tlsKey = strdup(val);
2405 if (!(val =
Config.GetWord()))
return 0;
2408do {
if (!strcmp(val,
"detail")) SSLmsgs =
true;
2409 else if (!strcmp(val,
"nodetail")) SSLmsgs =
false;
2410 else if (!strcmp(val,
"hsto" ))
2411 {
if (!(val =
Config.GetWord()))
2412 {
eDest->
Emsg(
"Config",
"tls hsto value not specified");
2419 else {
eDest->
Emsg(
"Config",
"invalid tls option -",val);
return 1;}
2420 }
while ((val =
Config.GetWord()));
2457 char *val, **cadest, kword[16];
2461 if (!(val =
Config.GetWord()))
2462 {
eDest->
Emsg(
"Config",
"tlsca parameter not specified");
return 1;}
2465 if (!strcmp(val,
"noverify"))
2467 if (caDir) {free(caDir); caDir = 0;}
2468 if (caFile) {free(caFile); caFile = 0;}
2474 do {
if (!strcmp(val,
"proxies") || !strcmp(
"noproxies", val))
2480 if (strlen(val) >= (
int)
sizeof(kword))
2481 {
eDest->
Emsg(
"Config",
"Invalid tlsca parameter -", val);
2486 if (!(val =
Config.GetWord()))
2487 {
eDest->
Emsg(
"Config",
"tlsca", kword,
"value not specified");
2490 if ((isdir = !strcmp(kword,
"certdir"))
2491 || !strcmp(kword,
"certfile"))
2493 {
eDest->
Emsg(
"Config",
"tlsca",kword,
"path is not absolute.");
2496 cadest = (isdir ? &caDir : &caFile);
2497 if (*cadest) free(*cadest);
2498 *cadest = strdup(val);
2500 else if (!strcmp(kword,
"crlcheck"))
2504 else if ( strcmp(val,
"external"))
2505 {
eDest->
Emsg(
"Config",
"Invalid tlsca crlcheck "
2510 else if (!strcmp(kword,
"log"))
2511 {
if (!strcmp(val,
"off"))
2513 else if (!strcmp(val,
"failure"))
2515 else {
eDest->
Emsg(
"Config",
"Invalid tlsca log argument -",val);
2519 else if (!strcmp(kword,
"refresh"))
2522 if (rt < 60) rt = 60;
2523 else if (rt % 60) rt += 60;
2527 else if (!strcmp(kword,
"verdepth"))
2532 else {
eDest->
Emsg(
"Config",
"invalid tlsca option -",kword);
return 1;}
2534 }
while((val =
Config.GetWord()));
2554 char *val, *ciphers;
2556 if (!(val =
Config.GetWord()))
2557 {
eDest->
Emsg(
"Config",
"tlsciphers parameter not specified");
return 1;}
2559 ciphers = strdup(val);
2561 if ((val =
Config.GetWord()))
2562 {
eDest->
Emsg(
"Config",
"Invalid tlsciphers argument -",val);
2596 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2597 struct tmoopts {
const char *opname;
int istime;
int minv;
2598 int *oploc;
const char *etxt;}
2601 {
"read", 1, 1, &V_read,
"timeout read"},
2602 {
"hail", 1, 1, &V_hail,
"timeout hail"},
2603 {
"idle", 1, 0, &V_idle,
"timeout idle"},
2604 {
"kill", 1, 0, &V_kill,
"timeout kill"}
2606 int numopts =
sizeof(tmopts)/
sizeof(
struct tmoopts);
2608 if (!(val =
Config.GetWord()))
2609 {
eDest->
Emsg(
"Config",
"timeout option not specified");
return 1;}
2612 {
for (i = 0; i < numopts; i++)
2613 if (!strcmp(val, tmopts[i].opname))
2614 {
if (!(val =
Config.GetWord()))
2615 {
eDest->
Emsg(
"Config",
"timeout", tmopts[i].opname,
2616 "value not specified");
2619 rc = (tmopts[i].istime ?
2625 *tmopts[i].oploc = ppp;
2629 eDest->
Say(
"Config warning: ignoring invalid timeout option '",val,
"'.");
2635 if (V_read > 0) ProtInfo.readWait = V_read*1000;
2636 if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
2637 if (V_idle >= 0) ProtInfo.idleWait = V_idle;
2659 static struct traceopts {
const char *opname;
int opval;} tropts[] =
2676 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
2678 if (!(val =
Config.GetWord()))
2679 {
eDest->
Emsg(
"Config",
"trace option not specified");
return 1;}
2681 {
if (!strcmp(val,
"off")) trval = 0;
2682 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2683 for (i = 0; i < numopts; i++)
2684 {
if (!strcmp(val, tropts[i].opname))
2686 if (tropts[i].opval) trval &= ~tropts[i].opval;
2688 else if (tropts[i].opval) trval |= tropts[i].opval;
2694 eDest->
Say(
"Config warning: ignoring invalid trace option '",val,
"'.");
void Usage(const char *msg)
static XrdSysError eDest(0,"crypto_")
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
#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)
std::vector< XrdInet * > NetTCP
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 void SetFQN(const char *fqn)
void AddHost(char *hname)
void AddNetGroup(char *hname)
void Trace(XrdSysTrace *et=0)
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)
void Add(const char *path, const char *parms, bool push=false)
T * Load(const char *Symbol)
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)