46#include <sys/resource.h>
53#include "XrdVersion.hh"
95#if defined(__linux__) || defined(__GNU__)
96#include <netinet/tcp.h>
102#include <AvailabilityMacros.h>
146void TlsError(
const char *tid,
const char *msg,
bool sslmsg)
154 const char *XrdConfig::TraceID =
"Config";
160#define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
191 {
for (
int i = 0; i <
numP; i++)
192 if (pnum == portVec[i])
193 {tlsVec[i] = isTLS;
return true;}
195 portVec[
numP] = pnum; tlsVec[
numP] = isTLS;
200void Reset(
char *ln,
char *pp,
int np=-1,
bool to=
false)
205 memset(portVec, 0,
sizeof(portVec));
207 memset(tlsVec, 0,
sizeof(tlsVec));
215 {memset(portVec, 0,
sizeof(portVec)); port = np;
216 memset(tlsVec, 0,
sizeof(tlsVec)); dotls = to;
238 {
theEnv.Put(
"configFN", cfn);}
261 AdminPath= strdup(
"/tmp");
263 PidPath = strdup(
"/tmp");
287 Firstcp = Lastcp = 0;
319 Sched.setNproc(
true);
335 const char *xrdInst=
"XRDINSTANCE=";
337 int retc, NoGo = 0, clPort = -1;
339 char c, buff[512], *dfltProt, *libProt = 0;
343 extern int optind, opterr;
345 int pipeFD[2] = {-1, -1};
346 const char *pidFN = 0;
347 static const int myMaxc = 80;
348 char **urArgv, *myArgv[myMaxc], argBuff[myMaxc*3+8];
349 char *argbP = argBuff, *argbE = argbP+
sizeof(argBuff)-4;
351 int myArgc = 1, urArgc = argc, i;
352 bool noV6, ipV4 =
false, ipV6 =
false, rootChk =
true, optbg =
false;
357 for (
int k = 1; k < argc; k++)
358 {CmdLine +=
' '; CmdLine += argv[k];}
362 retc = strlen(argv[0]);
363 while(retc--)
if (argv[0][retc] ==
'/')
break;
364 myProg = &argv[0][retc+1];
371 {
char *p = dfltProt = strdup(myProg);
372 while(*p && (*p ==
'.' || *p ==
'-')) p++;
374 {
char *dot = index(p,
'.'), *dash = index(p,
'-');
375 if (dot && (dot < dash || !dash)) p = dot;
376 else if (dash) p = dash;
379 if (!strcmp(
"xrootd", dfltProt)) dfltProt[5] = 0;
380 else if (!strcmp(
"cmsd", dfltProt)) dfltProt[3] = 0;
390 {
if (*(argv[i]) ==
'-' && *(argv[i]+1) ==
'+')
391 {
int n = strlen(argv[i]+2), j = i+1, k = 1;
392 if (urArgc == argc) urArgc = i;
393 if (n) memcpy(buff, argv[i]+2, (n > 256 ? 256 : n));
394 strcpy(&(buff[n]),
".argv**");
395 while(j < argc && (*(argv[j]) !=
'-' || *(argv[j]+1) !=
'+')) j++;
396 urArgv =
new char*[j-i+1];
399 while(i < j) urArgv[k++] = argv[i++];
401 theEnv.
PutPtr(buff, urArgv);
402 strcpy(&(buff[n]),
".argc");
403 theEnv.
PutInt(buff,
static_cast<long>(k));
406 theEnv.
PutPtr(
"argv[0]", argv[0]);
412 if (argc > 1 &&
'-' == *argv[1])
413 while ((c = getopt(urArgc,argv,
":a:A:bc:dhHI:k:l:L:n:N:p:P:R:s:S:vw:W:z"))
414 && ((
unsigned char)c != 0xff))
417 case 'a':
if (AdminPath) free(AdminPath);
418 AdminPath = strdup(optarg);
419 AdminMode =
ProtInfo.AdmMode = S_IRWXU;
422 case 'A':
if (AdminPath) free(AdminPath);
423 AdminPath = strdup(optarg);
424 AdminMode =
ProtInfo.AdmMode = S_IRWXU | S_IRWXG;
427 case 'b': optbg =
true;
429 case 'c':
if (ConfigFN) free(ConfigFN);
430 ConfigFN = strdup(optarg);
440 case 'I':
if (!strcmp(
"v4", optarg)) {ipV4 =
true; ipV6 =
false;}
441 else if (!strcmp(
"v6", optarg)) {ipV4 =
false; ipV6 =
true;}
442 else {
Log.Emsg(
"Config",
"Invalid -I argument -",optarg);
446 case 'k':
if (!(LogInfo.
keepV =
Log.logger()->ParseKeep(optarg)))
447 {
Log.Emsg(
"Config",
"Invalid -k argument -",optarg);
451 case 'l': LogInfo.
logArg = optarg;
453 case 'L':
if (!*optarg)
454 {
Log.Emsg(
"Config",
"Protocol library path not specified.");
457 if (libProt) free(libProt);
458 libProt = strdup(optarg);
460 case 'n': myInsName = (!strcmp(optarg,
"anon")||!strcmp(optarg,
"default")
467 case 'P':
if (dfltProt) free(dfltProt);
468 dfltProt = strdup(optarg);
470 case 'R':
if (!(getUG(optarg, myUid, myGid)))
Usage(1);
473 case 's': pidFN = optarg;
475 case 'S': mySitName = optarg;
477 case ':': buff[0] =
'-'; buff[1] =
optopt; buff[2] = 0;
478 Log.Emsg(
"Config", buff,
"parameter not specified.");
481 case 'v': std::cerr <<XrdVSTRING <<std::endl;
484 case 'w':
if (HomePath) free(HomePath);
485 HomePath = strdup(optarg);
489 case 'W':
if (HomePath) free(HomePath);
490 HomePath = strdup(optarg);
491 HomeMode = S_IRWXU | S_IRGRP | S_IXGRP;
494 case 'z': LogInfo.
hiRes =
true;
498 {
Log.Emsg(
"Config",
"Long options are not supported.");
501 if (myArgc >= myMaxc || argbP >= argbE)
502 {
Log.Emsg(
"Config",
"Too many command line arguments.");
505 myArgv[myArgc++] = argbP;
506 *argbP++ =
'-'; *argbP++ =
optopt; *argbP++ = 0;
514 {
Log.Emsg(
"Config",
"Command line adminpath is not absolute.");
520 if (HomePath && *HomePath !=
'/')
521 {
Log.Emsg(
"Config",
"Command line home path is not absolute.");
528 if (ConfigFN) setCFG(
true);
534 else if (ipV6){
if (noV6)
Log.Say(
"Config warning: ipV6 appears to be broken;"
535 " forced ipV6 mode not advised!");
538 else if (noV6)
Log.Say(
"Config warning: ipV6 is misconfigured or "
539 "unavailable; reverting to ipV4.");
547 if (myGid && setegid(myGid))
548 {
Log.Emsg(
"Config", errno,
"set effective gid"); exit(17);}
549 if (myUid && seteuid(myUid))
550 {
Log.Emsg(
"Config", errno,
"set effective uid"); exit(17);}
554 if (rootChk && geteuid() == 0)
555 {
Log.Emsg(
"Config",
"Security reasons prohibit running as "
556 "superuser; program is terminating.");
562 if (urArgc-
optind+2 >= myMaxc)
563 {
Log.Emsg(
"Config",
"Too many command line arguments.");
581 if (pipe( pipeFD ) == -1)
582 {
Log.Emsg(
"Config", errno,
"create a pipe"); exit(17);}
591 if (!(myName = myIPAddr->
Name(0, &temp))) myName =
"";
604 sprintf(buff,
"%s%s %s@%s", xrdInst, myProg,
ProtInfo.myInst, myName);
605 myInstance = strdup(buff);
607 myInstance += strlen(xrdInst);
615 {LogInfo.
xrdEnv = &theEnv;
616 LogInfo.
iName = myInsName;
617 LogInfo.
cfgFn = ConfigFN;
619 Log.logger()->AddMsg(CmdLine.
c_str());
628 {
Log.Emsg(
"Config",
"Unable to determine host name; ",
629 (temp ? temp :
"reason unknown"),
630 "; execution terminated.");
640 strcpy(buff,
"Starting on ");
652 {
Log.Emsg(
"Config",myName,
"does not appear to be registered in the DNS.");
653 Log.Emsg(
"Config",
"Verify that the '/etc/hosts' file is correct and "
654 "this machine is registered in DNS.");
655 Log.Emsg(
"Config",
"Execution continues but connection failures may occur.");
657 }
else if (!(myDomain = index(myName,
'.')))
658 Log.Say(
"Config warning: this hostname, ", myName,
659 ", is registered without a domain qualification.");
663 Firstcp = Lastcp =
new XrdConfigProt(strdup(dfltProt), libProt, 0);
667 Log.Say(
"++++++ ", myInstance,
" initialization started.");
671 devNull = XrdSysFD_Open(
"/dev/null", O_RDONLY);
673 {
Log.Emsg(
"Config", errno,
"open '/dev/null' which is required!");
680 {
Log.Say(
"Config using configuration file ", ConfigFN);
684 if (clPort >= 0) PortTCP = clPort;
692 NoGo |= SetupAPath();
698 else {
Log.Say(
"++++++ ", myInstance,
" TLS initialization started.");
700 {
Log.Say(
"------ ",myInstance,
" TLS initialization ended.");
705 Log.Say(
"------ ",myInstance,
" TLS initialization failed.");
715 {
Log.Say(
"Config TLS port specification ignored; TLS not configured!");
719 ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
735 {
Log.Emsg(
"Config",
"Unable to determine interface addresses!");
741 if ((myInsName || HomePath)
750 if (!PidFile(pidFN, optbg)) NoGo = 1;
754 if (!NoGo) Manifest(pidFN);
758 if (!NoGo) NoGo = Setup(dfltProt, libProt);
767 if (tmoInfo && !NoGo)
768 {
void *theGS = theEnv.
GetPtr(
"TcpMon.gStream*");
769 if (!theGS)
Log.Say(
"Config warning: TCP monitoring not enabled; "
770 "tcpmonlib plugin not loaded!");
771 else {tmoInfo->theEnv.PutPtr(
"TcpMon.gStream*", theGS);
772 TcpMonPin = tmoInfo->KingPin.Load(
"TcpMonPin");
782 int status = NoGo ? 1 : 0;
783 if(
write( pipeFD[1], &status,
sizeof( status ) )) {};
790 temp = (NoGo ?
" initialization failed." :
" initialization completed.");
791 sprintf(buff,
"%s:%d", myInstance, PortTCP);
792 Log.Say(
"------ ", buff, temp);
794 {strcat(buff,
" running ");
797 Log.logger()->AddMsg(buff);
812 if (
eDest) dynamic = 1;
826 TS_Xeq(
"adminpath", xapath);
828 TS_Xeq(
"homepath", xhpath);
832 TS_Xeq(
"protocol", xprot);
835 TS_Xeq(
"tcpmonlib", xtcpmon);
839 TS_Xeq(
"tlsciphers", xtlsci);
844 eDest->Say(
"Config warning: ignoring unknown xrd directive '",var,
"'.");
856int XrdConfig::ASocket(
const char *path,
const char *fname, mode_t mode)
858 struct sockaddr_un unixvar;
859 int plen = strlen(path), flen = strlen(fname);
863 if ((plen + flen + 3) > (
int)
sizeof(unixvar.sun_path))
864 {
Log.Emsg(
"Config",
"admin path", path,
"too long");
899int XrdConfig::ConfigProc()
902 int cfgFD, retc, NoGo = 0;
904 XrdOucStream
Config(&
Log, myInstance, &myEnv,
"=====> ");
908 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
909 {
Log.
Emsg(
"Config", errno,
"open config file", ConfigFN);
916 while((var =
Config.GetMyFirstWord()))
917 if (!strncmp(var,
"xrd.", 4)
918 || !strcmp (var,
"all.adminpath")
919 || !strcmp (var,
"all.pidpath")
920 || !strcmp (var,
"all.sitename" ))
925 if ((retc =
Config.LastError()))
926 NoGo =
Log.
Emsg(
"Config", retc,
"read config file", ConfigFN);
938XrdInet *XrdConfig::getNet(
int port,
bool isTLS)
940 int the_Opts, the_Blen;
944 for (
int i = 0; i < (int)
NetTCP.size(); i++)
949 XrdInet *newNet =
new XrdInet(&
Log, Police);
955 {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
957 the_Opts = Net_Opts; the_Blen = Net_Blen;
959 if (the_Opts || the_Blen) newNet->
setDefaults(the_Opts, the_Blen);
963 if (myDomain) newNet->
setDomain(myDomain);
967 if (newNet->
BindSD(port,
"tcp") == 0)
return newNet;
976int XrdConfig::getUG(
char *parm, uid_t &newUid, gid_t &newGid)
983 {
Log.
Emsg(
"Config",
"-R user not specified.");
return 0;}
986 {
if (!(newUid = atol(parm)))
987 {
Log.
Emsg(
"Config",
"-R", parm,
"is invalid");
return 0;}
988 pp = getpwuid(newUid);
990 else pp = getpwnam(parm);
995 {
Log.
Emsg(
"Config", errno,
"retrieve -R user password entry");
998 if (!(newUid = pp->pw_uid))
999 {
Log.
Emsg(
"Config",
"-R", parm,
"is still unacceptably a superuser!");
1002 newGid = pp->pw_gid;
1010void XrdConfig::Manifest(
const char *pidfn)
1013 char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1018 if (!getcwd(pwdBuff,
sizeof(pwdBuff)))
1019 {
Log.
Emsg(
"Config",
"Unable to get current working directory!");
1025 if (HomePath) free(HomePath);
1026 HomePath = strdup(pwdBuff);
1031 envLen = strlen(envBuff);
1032 if (envBuff[envLen-1] !=
'/') {envBuff[envLen] =
'/'; envLen++;}
1033 strcpy(envBuff+envLen,
".xrd/");
1034 xP = envBuff+envLen+5;
1038 if ((sP = getenv(
"XRDCONFIGFN")))
1039 {sprintf(xP,
"=/conf/%s.cf", myProg);
1045 sprintf(xP,
"=/core/%s", myProg);
1050 if ((sP = getenv(
"XRDLOGDIR")))
1051 {sprintf(xP,
"=/logs/%s", myProg);
1058 sprintf(xP,
"=/proc/%s", myProg);
1059 sprintf(manBuff,
"/proc/%d", getpid());
1065 envLen = snprintf(envBuff,
sizeof(envBuff),
"pid=%d&host=%s&inst=%s&ver=%s"
1066 "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1067 static_cast<int>(getpid()),
ProtInfo.myName,
1068 ProtInfo.myInst, XrdVSTRING, HomePath,
1069 (getenv(
"XRDCONFIGFN") ? getenv(
"XRDCONFIGFN") :
""),
1074 if (pidfn && (Slash = rindex(pidfn,
'/')))
1075 {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1076 else {strcpy(manBuff,
ProtInfo.AdmPath); pidP = manBuff+strlen(
ProtInfo.AdmPath);}
1080 snprintf(pidP,
sizeof(manBuff)-(pidP-manBuff),
"/%s.%s.env",
1086 if ((envFD =
open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1087 {
Log.
Emsg(
"Config", errno,
"create envfile", manBuff);
1093 if (
write(envFD, envBuff, envLen) < 0)
1094 Log.
Emsg(
"Config", errno,
"write to envfile", manBuff);
1102bool XrdConfig::PidFile(
const char *clpFN,
bool optbg)
1105 char *ppath, buff[32], pidFN[1200];
1106 const char *xop = 0;
1120 {xop =
"create"; snprintf(pidFN,
sizeof(pidFN),
"%s", ppath); errno = rc;}
1121 else {snprintf(pidFN,
sizeof(pidFN),
"%s/%s.pid", ppath, myProg);
1123 if ((xfd =
open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1125 else {
if (
write(xfd,buff,snprintf(buff,
sizeof(buff),
"%d",
1126 static_cast<int>(getpid()))) < 0) xop =
"write";
1134 if (xop)
Log.
Emsg(
"Config", errno, xop, pidFN);
1142void XrdConfig::setCFG(
bool start)
1147 if (!ConfigFN || !(*ConfigFN))
1171 if (*ConfigFN !=
'/')
1172 {
char cwdBuff[1024];
1173 if (getcwd(cwdBuff,
sizeof(cwdBuff)-strlen(ConfigFN)-2))
1174 {
int n = strlen(cwdBuff);
1175 if (cwdBuff[n-1] !=
'/') cwdBuff[n++] =
'/';
1176 strcpy(cwdBuff+n, ConfigFN);
1178 ConfigFN = strdup(cwdBuff);
1191 const char *cvec[] = {
"*** ", myProg,
" config from '", ConfigFN,
"':", 0 };
1199int XrdConfig::setFDL()
1206 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1207 return Log.
Emsg(
"Config", errno,
"get FD limit");
1211 if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1212 rlim.rlim_cur = maxFD;
1213 else rlim.rlim_cur = rlim.rlim_max;
1214#if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1215 if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1217#if defined(__linux__)
1219 unsigned int epoll_max_fd = (INT_MAX /
sizeof(
struct epoll_event));
1220 if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1222 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1223 return Log.
Emsg(
"Config", errno,
"set FD limit");
1227 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1228 return Log.
Emsg(
"Config", errno,
"get FD limit");
1233 sprintf(buff,
"%d",
ProtInfo.ConnMax);
1234 Log.
Say(
"Config maximum number of connections restricted to ", buff);
1238#
if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1240 {
if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1241 Log.
Emsg(
"Config", errno,
"get core limit");
1242 else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1243 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1244 Log.
Emsg(
"Config", errno,
"set core limit");
1251#if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1255 if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1256 return Log.
Emsg(
"Config", errno,
"get thread limit");
1260 int nthr =
static_cast<int>(rlim.rlim_cur);
1262 {sprintf(buff,
"%d", static_cast<int>(rlim.rlim_cur));
1263 Log.Say(
"Config maximum number of threads restricted to ", buff);
1274int XrdConfig::Setup(
char *dfltp,
char *libProt)
1277 int xport, protNum = 0;
1281 if (setFDL())
return 1;
1285#if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1286{
int sokFD, setON = 1;
1287 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1289 &setON,
sizeof(setON));
1290 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
1326 for (
int i = 0; i < cp->
numP; i++)
1329 "configured with a TLS-only port "
1330 "but TLS is not configured!");
1334 xport = (cp->dotls ? PortTLS : PortTCP);
1335 ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1338 if (cp->port < 0)
return 1;
1339 for (
int i = 1; i < cp->
numP; i++)
1340 if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1356 xport = (strcmp(
"xroot", Firstcp->proname) ? 0 : Firstcp->port);
1364 XrdInet *arbNet = 0, *theNet;
1365 while((cp = Firstcp))
1366 {
for (
int i = 0; i < cp->
numP; i++)
1367 {
if (cp->portVec[i] < 0)
continue;
1368 if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1369 else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1370 if (!theNet)
return 1;
1371 if (!(cp->portVec[i])) arbNet = theNet;
1385 if (!protNum)
return 1;
1388 if (!strcmp(
"http", cp->
proname) && xport)
1389 {
for (
int i = 0; i < cp->
numP; i++)
1390 {
if (cp->portVec[i] == xport) {xport = 0;
break;}}
1393 Firstcp = cp->
Next;
delete cp;
1405 if (repDest[0] != 0 && (repOpts[0] || repOpts[1]))
1406 ProtInfo.Stats->Init(repDest, repInt, repOpts[0], repOpts[1]);
1417int XrdConfig::SetupAPath()
1435 {
Log.
Emsg(
"Config", rc,
"create admin path", AdminPath);
1442 if (chmod(AdminPath, AdminMode & ~S_IWGRP))
1443 {
Log.
Emsg(
"Config", errno,
"set permission for admin path", AdminPath);
1451 return ASocket(AdminPath,
"admin", (mode_t)AdminMode);
1458bool XrdConfig::SetupTLS()
1463 if (!caDir && !caFile && !tlsNoVer)
1465 Log.
Say(
"Config failure: the tlsca directive was not specified!");
1466 else Log.
Say(
"Config failure: the tlsca directive did not specify "
1467 "a certdir or certfile!");
1473 if (caDir && !getenv(
"X509_CERT_DIR"))
1475 if (caFile && !getenv(
"X509_CERT_FILE"))
1496 static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1500 if (!xrdTLS.isOK())
return false;
1512void XrdConfig::Usage(
int rc)
1518 std::cerr <<
"\nUsage: " <<myProg <<
" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1519 "[-k {n|sz|sig}] [-l [=]<fn>] [-n <name>] [-N <hname>] [-p <port>]\n"
1520 "[-P <prot>] [-L <libprot>] [-R] [-s pidfile] [-S site] [-v] [-z]\n"
1521 "[<protocol_options>]" <<std::endl;
1522 _exit(rc > 0 ? rc : 0);
1545 mode_t mode = S_IRWXU;
1550 if (!pval || !pval[0])
1551 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1556 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1560 if (AdminPath) free(AdminPath);
1561 AdminPath = strdup(pval);
1565 if ((val =
Config.GetWord()) && val[0])
1566 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1567 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1571 AdminMode =
ProtInfo.AdmMode = mode;
1595 if (!(val =
Config.GetWord()))
1596 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1598 if (!strcmp(val,
"host")) ishost = 1;
1599 else if (!strcmp(val,
"netgroup")) ishost = 0;
1600 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1604 if (!(val =
Config.GetWord()))
1605 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1607 if (!Police) {Police =
new XrdNetSecurity();
1610 if (ishost) Police->AddHost(val);
1611 else Police->AddNetGroup(val);
1636 {
eDest->
Say(
"Config warning: command line homepath cannot be overridden.");
1643 if (HomePath) {free(HomePath); HomePath = 0;}
1648 return (HomePath ? 0 : 1);
1669 static const long long minBSZ = 1024*1024*2+1;
1670 static const long long maxBSZ = 1024*1024*1024;
1675 if (!(val =
Config.GetWord()))
1676 {
eDest->
Emsg(
"Config",
"buffer memory limit not specified");
return 1;}
1678 if (!strcmp(
"maxbsz", val))
1679 {
if (!(val =
Config.GetWord()))
1680 {
eDest->
Emsg(
"Config",
"max buffer size not specified");
return 1;}
1684 if (!(val =
Config.GetWord()))
return 0;
1688 (
long long)1024*1024))
return 1;
1690 if ((val =
Config.GetWord()))
1716 long long minV = 1024, maxV = 1024LL*1024LL;
1720 if ((val =
Config.GetWord()))
1721 {
if (!strcmp(val,
"strict"))
1724 }
else isStrict =
false;
1728 {
eDest->
Emsg(
"Config",
"file descriptor limit not specified");
return 1;}
1733 maxFD =
static_cast<unsigned int>(fdVal);
1770 int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1771 int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1, V_udpref = -1;
1773 struct netopts {
const char *opname;
int hasarg;
int opval;
1774 int *oploc;
const char *etxt;}
1777 {
"assumev4", 0, 1, &V_assumev4,
"option"},
1778 {
"keepalive", 0, 1, &V_keep,
"option"},
1779 {
"nokeepalive",0, 0, &V_keep,
"option"},
1780 {
"kaparms", 4, 0, &V_keep,
"option"},
1781 {
"buffsz", 1, 0, &V_blen,
"network buffsz"},
1782 {
"cache", 2, 0, &V_ct,
"cache time"},
1783 {
"dnr", 0, 0, &V_nodnr,
"option"},
1784 {
"nodnr", 0, 1, &V_nodnr,
"option"},
1785 {
"dyndns", 0, 1, &V_dyndns,
"option"},
1786 {
"nodyndns", 0, 0, &V_dyndns,
"option"},
1787 {
"routes", 3, 1, 0,
"routes"},
1788 {
"rpipa", 0, 1, &v_rpip,
"rpipa"},
1789 {
"norpipa", 0, 0, &v_rpip,
"norpipa"},
1790 {
"tls", 0, 1, &V_istls,
"option"},
1791 {
"udprefresh", 2, 1, &V_udpref,
"udprefresh"}
1793 int numopts =
sizeof(ntopts)/
sizeof(
struct netopts);
1795 if (!(val =
Config.GetWord()))
1796 {
eDest->
Emsg(
"Config",
"net option not specified");
return 1;}
1799 {
for (i = 0; i < numopts; i++)
1800 if (!strcmp(val, ntopts[i].opname))
1801 {
if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1802 else {
if (!(val =
Config.GetWord()))
1804 ntopts[i].opname,
"argument missing");
1807 if (ntopts[i].hasarg == 4)
1808 {
if (xnkap(
eDest, val))
return 1;
1811 if (ntopts[i].hasarg == 3)
1812 {
if (!strcmp(val,
"split"))
1814 else if (!strcmp(val,
"common"))
1816 else if (!strcmp(val,
"local"))
1818 else {
eDest->
Emsg(
"Config",
"Invalid routes argument -",val);
1821 if (!(val =
Config.GetWord())|| !(*val))
break;
1822 if (strcmp(val,
"use"))
continue;
1823 if (!(val =
Config.GetWord())|| !(*val))
1824 {
eDest->
Emsg(
"Config",
"network routes i/f names "
1832 if (ntopts[i].hasarg == 2)
1835 *ntopts[i].oploc = n;
1839 *ntopts[i].oploc = (int)llp;
1845 eDest->
Say(
"Config warning: ignoring invalid net option '",val,
"'.");
1846 else if (!val)
break;
1851 {
if (V_blen >= 0) TLS_Blen = V_blen;
1855 if (V_blen >= 0) Net_Blen = V_blen;
1863 {
if (V_dyndns && V_ct < 0) V_ct = 0;
1899 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1906 if (!(karg = val))
return 0;
1907 if ((comma = index(val,
','))) {val = comma+1; *comma = 0;}
1943 if (!val || !val[0])
1944 {
eDest->
Emsg(
"Config",
"pidpath not specified");
return 1;}
1948 if (PidPath) free(PidPath);
1949 PidPath = strdup(val);
1970{
int rc, istls = 0, pnum = 0;
1971 char *val, cport[32];
1973 do {
if (!(val =
Config.GetWord()))
1974 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
1975 if (strcmp(
"tls", val) || istls)
break;
1979 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
1981 if ((val =
Config.GetWord()) && !strcmp(
"if", val))
1984 {
if (!rc)
Config.noEcho();
return (rc < 0);}
1987 if (istls) PortTLS = pnum;
1988 else PortTCP = PortUDP = pnum;
2015 char *val, *parms, *lib, proname[64], buff[2048];
2019 do {
if (!(val =
Config.GetWord()))
2020 {
eDest->
Emsg(
"Config",
"protocol name not specified");
return 1;}
2021 if (dotls || strcmp(
"tls", val))
break;
2025 if (strlen(val) >
sizeof(proname)-1)
2026 {
eDest->
Emsg(
"Config",
"protocol name is too long");
return 1;}
2027 strcpy(proname, val);
2029 if ((val = index(proname,
':')))
2034 if (!(val =
Config.GetWord()))
2035 {
eDest->
Emsg(
"Config",
"protocol library not specified");
return 1;}
2036 if (!strcmp(
"*", val)) lib = 0;
2037 else if (*val ==
'+')
2038 {
if (strcmp(val,
"+port"))
2039 {
eDest->
Emsg(
"Config",
"invalid library specification -",val);
2042 if ((cpp = Firstcp))
2043 do {
if (!strcmp(proname, cpp->
proname))
2044 {
if (cpp->
AddPort(portnum, dotls))
return 0;
2045 eDest->
Emsg(
"Config",
"port add limit exceeded!");
2048 }
while((cpp = cpp->
Next));
2049 eDest->
Emsg(
"Config",
"protocol",proname,
"not previously defined!");
2052 else lib = strdup(val);
2057 if (!lib && Firstcp && strcmp(proname, Firstcp->proname))
2059 snprintf(eBuff,
sizeof(eBuff),
"the %s protocol is '%s' not '%s'; "
2060 "assuming you meant '%s'",
2061 (Firstcp->libpath ?
"assigned" :
"builtin"),
2062 Firstcp->proname, proname, Firstcp->proname);
2063 eDest->
Say(
"Config warning: ", eBuff,
" but please correct "
2064 "the following directive!");
2065 snprintf(proname,
sizeof(proname),
"%s", Firstcp->proname);
2069 if (!
Config.GetRest(buff,
sizeof(buff)))
2070 {
eDest->
Emsg(
"Config",
"Too many parms for protocol", proname);
2073 parms = (*buff ? strdup(buff) : 0);
2075 if ((cpp = Firstcp))
2076 do {
if (!strcmp(proname, cpp->
proname))
2077 {cpp->
Reset(lib, parms, portnum, dotls);
2080 }
while((cpp = cpp->
Next));
2082 cpp =
new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2083 if (!lib) {cpp->
Next = Firstcp; Firstcp = cpp;
2084 if (!Lastcp) Lastcp = cpp;
2086 else {
if (Lastcp) Lastcp->Next = cpp;
2116 static struct repopts {
const char *opname;
int opval;
bool jOK;} rpopts[] =
2133 int i, neg, numopts =
sizeof(rpopts)/
sizeof(
struct repopts);
2137 if (!(val =
Config.GetWord()))
2138 {
eDest->
Emsg(
"Config",
"report parameters not specified");
return 1;}
2142 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2143 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2144 repOpts[0] = 0; repOpts[1] = 0;
2149 if ((cp = (
char *)index(val,
',')))
2151 {
eDest->
Emsg(
"Config",
"malformed report destination -",val);
return 1;}
2152 else { repDest[1] = cp+1; *cp =
'\0';}
2155 for (i = 0; i < 2; i++)
2156 {
if (!(val = repDest[i]))
break;
2157 if (*val !=
'/' && (!(cp = index(val, (
int)
':')) || !atoi(cp+1)))
2158 {
eDest->
Emsg(
"Config",
"report dest port missing or invalid in",val);
2161 repDest[i] = strdup(val);
2166 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2167 {
eDest->
Emsg(
"Config",
"Warning, report dests are identical.");
2168 free(repDest[1]); repDest[1] = 0;
2173 if (!(val =
Config.GetWord()))
2178 if (!strcmp(
"every", val))
2179 {
if (!(val =
Config.GetWord()))
2180 {
eDest->
Emsg(
"Config",
"report every value not specified");
return 1;}
2188 {
if (!strcmp(val,
"json"))
2190 val =
Config.GetWord();
continue;
2192 if (!strcmp(val,
"off"))
2193 {repOpts[isJSON] = 0;
2194 val =
Config.GetWord();
continue;
2196 if ((neg = (val[0] ==
'-' && val[1]))) val++;
2197 for (i = 0; i < numopts; i++)
2198 {
if (!strcmp(val, rpopts[i].opname))
2199 {
if (neg) repOpts[isJSON] &= ~rpopts[i].opval;
2200 else {
if (isJSON && !rpopts[i].jOK)
2201 {
eDest->
Emsg(
"Config",val,
"does not support JSON");
2204 repOpts[isJSON] |= rpopts[i].opval;
2210 eDest->
Say(
"Config warning: ignoring invalid report option '",val,
"'.");
2270 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2271 struct schedopts {
const char *opname;
int minv;
int *oploc;
2272 const char *opmsg;} scopts[] =
2274 {
"stksz", 0, 0,
"sched stksz"},
2275 {
"mint", 1, &V_mint,
"sched mint"},
2276 {
"maxt", 1, &V_maxt,
"sched maxt"},
2277 {
"avlt", 1, &V_avlt,
"sched avlt"},
2278 {
"core", 1, 0,
"sched core"},
2279 {
"idle", 0, &V_idle,
"sched idle"}
2281 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2283 if (!(val =
Config.GetWord()))
2284 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2287 {
for (i = 0; i < numopts; i++)
2288 if (!strcmp(val, scopts[i].opname))
2289 {
if (!(val =
Config.GetWord()))
2290 {
eDest->
Emsg(
"Config",
"sched", scopts[i].opname,
2291 "value not specified");
2294 if (*scopts[i].opname ==
'i')
2296 &ppp, scopts[i].minv))
return 1;
2298 else if (*scopts[i].opname ==
'c')
2299 {
if (!strcmp(
"asis", val)) coreV = -1;
2300 else if (!strcmp(
"max", val)) coreV = 1;
2301 else if (!strcmp(
"off", val)) coreV = 0;
2302 else {
eDest->
Emsg(
"Config",
"invalid sched core value -",val);
2306 else if (*scopts[i].opname ==
's')
2308 &lpp, scopts[i].minv))
return 1;
2313 &ppp,scopts[i].minv))
return 1;
2314 *scopts[i].oploc = ppp;
2318 eDest->
Say(
"Config warning: ignoring invalid sched option '",val,
"'.");
2325 {
if (V_mint > 0 && V_mint > V_maxt)
2326 {
eDest->
Emsg(
"Config",
"sched mint must be less than maxt");
2329 if (V_avlt > 0 && V_avlt > V_maxt)
2330 {
eDest->
Emsg(
"Config",
"sched avlt must be less than maxt");
2360 if (!(val =
Config.GetWord()))
2361 {
eDest->
Emsg(
"Config",
"sitename value not specified");
return 1;}
2363 if (mySitName)
eDest->
Emsg(
"Config",
"sitename already specified, using '",
2386 char *val, parms[2048];
2391 if ((val =
Config.GetWord()))
2392 {
if (!strcmp(val,
"++"))
2401 {
eDest->
Emsg(
"Config",
"tcpmonlib not specified");
return 1;}
2406 {
eDest->
Emsg(
"Config",
"tcpmonlib path is not absolute");
return 1;}
2414 if (!
Config.GetRest(parms,
sizeof(parms)))
2415 {
eDest->
Emsg(
"Config",
"tcpmonlib parameters too long");
return 1;}
2419 if (!tmoInfo) tmoInfo =
new XrdTcpMonInfo(
"xrd.tcpmonlib",ConfigFN,*
eDest);
2423 tmoInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
2452 if (!(val =
Config.GetWord()))
2453 {
eDest->
Emsg(
"Config",
"tls cert path not specified");
return 1;}
2456 {
eDest->
Emsg(
"Config",
"tls cert path not absolute");
return 1;}
2458 if (tlsCert) free(tlsCert);
2459 tlsCert = strdup(val);
2460 if (tlsKey) free(tlsKey);
2463 if (!(val =
Config.GetWord()))
return 0;
2466 {tlsKey = strdup(val);
2467 if (!(val =
Config.GetWord()))
return 0;
2470do {
if (!strcmp(val,
"detail")) SSLmsgs =
true;
2471 else if (!strcmp(val,
"nodetail")) SSLmsgs =
false;
2472 else if (!strcmp(val,
"hsto" ))
2473 {
if (!(val =
Config.GetWord()))
2474 {
eDest->
Emsg(
"Config",
"tls hsto value not specified");
2481 else {
eDest->
Emsg(
"Config",
"invalid tls option -",val);
return 1;}
2482 }
while ((val =
Config.GetWord()));
2524 char *val, **cadest, kword[16];
2528 if (!(val =
Config.GetWord()))
2529 {
eDest->
Emsg(
"Config",
"tlsca parameter not specified");
return 1;}
2532 if (!strcmp(val,
"noverify"))
2534 if (caDir) {free(caDir); caDir = 0;}
2535 if (caFile) {free(caFile); caFile = 0;}
2540 do {
if (!strcmp(val,
"proxies") || !strcmp(
"noproxies", val))
2542 else tlsOpts &= ~XrdTlsContext::nopxy;
2546 if (!strcmp(val,
"allow-missing-crl")) {
2551 if (strlen(val) >= (
int)
sizeof(kword))
2552 {
eDest->
Emsg(
"Config",
"Invalid tlsca parameter -", val);
2557 if (!(val =
Config.GetWord()))
2558 {
eDest->
Emsg(
"Config",
"tlsca", kword,
"value not specified");
2561 if ((isdir = !strcmp(kword,
"certdir"))
2562 || !strcmp(kword,
"certfile"))
2564 {
eDest->
Emsg(
"Config",
"tlsca",kword,
"path is not absolute.");
2567 cadest = (isdir ? &caDir : &caFile);
2568 if (*cadest) free(*cadest);
2569 *cadest = strdup(val);
2571 else if (!strcmp(kword,
"crlcheck"))
2575 else if ( strcmp(val,
"external"))
2576 {
eDest->
Emsg(
"Config",
"Invalid tlsca crlcheck "
2581 else if (!strcmp(kword,
"log"))
2582 {
if (!strcmp(val,
"off"))
2583 tlsOpts &= ~XrdTlsContext::logVF;
2584 else if (!strcmp(val,
"failure"))
2586 else {
eDest->
Emsg(
"Config",
"Invalid tlsca log argument -",val);
2590 else if (!strcmp(kword,
"refresh"))
2593 if (rt < 60) rt = 60;
2594 else if (rt % 60) rt += 60;
2598 else if (!strcmp(kword,
"verdepth"))
2602 }
else {
eDest->
Emsg(
"Config",
"invalid tlsca option -",kword);
return 1;}
2604 }
while((val =
Config.GetWord()));
2624 char *val, *ciphers;
2626 if (!(val =
Config.GetWord()))
2627 {
eDest->
Emsg(
"Config",
"tlsciphers parameter not specified");
return 1;}
2629 ciphers = strdup(val);
2631 if ((val =
Config.GetWord()))
2632 {
eDest->
Emsg(
"Config",
"Invalid tlsciphers argument -",val);
2666 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2667 struct tmoopts {
const char *opname;
int istime;
int minv;
2668 int *oploc;
const char *etxt;}
2671 {
"read", 1, 1, &V_read,
"timeout read"},
2672 {
"hail", 1, 1, &V_hail,
"timeout hail"},
2673 {
"idle", 1, 0, &V_idle,
"timeout idle"},
2674 {
"kill", 1, 0, &V_kill,
"timeout kill"}
2676 int numopts =
sizeof(tmopts)/
sizeof(
struct tmoopts);
2678 if (!(val =
Config.GetWord()))
2679 {
eDest->
Emsg(
"Config",
"timeout option not specified");
return 1;}
2682 {
for (i = 0; i < numopts; i++)
2683 if (!strcmp(val, tmopts[i].opname))
2684 {
if (!(val =
Config.GetWord()))
2685 {
eDest->
Emsg(
"Config",
"timeout", tmopts[i].opname,
2686 "value not specified");
2689 rc = (tmopts[i].istime ?
2692 XrdOuca2x::a2i (*
eDest,tmopts[i].etxt,val,&ppp,
2695 *tmopts[i].oploc = ppp;
2699 eDest->
Say(
"Config warning: ignoring invalid timeout option '",val,
"'.");
2705 if (V_read > 0)
ProtInfo.readWait = V_read*1000;
2706 if (V_hail >= 0)
ProtInfo.hailWait = V_hail*1000;
2707 if (V_idle >= 0)
ProtInfo.idleWait = V_idle;
2729 static struct traceopts {
const char *opname;
int opval;} tropts[] =
2746 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
2748 if (!(val =
Config.GetWord()))
2749 {
eDest->
Emsg(
"Config",
"trace option not specified");
return 1;}
2751 {
if (!strcmp(val,
"off")) trval = 0;
2752 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2753 for (i = 0; i < numopts; i++)
2754 {
if (!strcmp(val, tropts[i].opname))
2756 if (tropts[i].opval) trval &= ~tropts[i].opval;
2758 else if (tropts[i].opval) trval |= tropts[i].opval;
2764 eDest->
Say(
"Config warning: ignoring invalid trace option '",val,
"'.");
void Usage(const char *msg)
int portVec[XrdProtLoad::PortoMax]
bool tlsVec[XrdProtLoad::PortoMax]
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)
XrdProtocol_Config ProtInfo
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)
static void Start(XrdSysLogger *logP, XrdScheduler *sP)
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)
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)
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 crlAM
Allow CA validation when CRL is missing (CRL soft-fail).
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)
XrdNetRefresh * NetRefresh