00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdConfigCVSID = "$Id: XrdConfig.cc 38011 2011-02-08 18:35:57Z ganis $";
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <unistd.h>
00023 #include <ctype.h>
00024 #include <pwd.h>
00025 #include <string.h>
00026 #include <stdio.h>
00027 #include <sys/param.h>
00028 #include <sys/resource.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031
00032 #include "Xrd/XrdBuffer.hh"
00033 #include "Xrd/XrdConfig.hh"
00034 #include "Xrd/XrdInet.hh"
00035 #include "Xrd/XrdLink.hh"
00036 #include "Xrd/XrdPoll.hh"
00037 #include "Xrd/XrdProtLoad.hh"
00038 #include "Xrd/XrdScheduler.hh"
00039 #include "Xrd/XrdStats.hh"
00040 #include "Xrd/XrdTrace.hh"
00041 #include "Xrd/XrdInfo.hh"
00042
00043 #include "XrdNet/XrdNetDNS.hh"
00044 #include "XrdNet/XrdNetSecurity.hh"
00045
00046 #include "XrdOuc/XrdOuca2x.hh"
00047 #include "XrdOuc/XrdOucEnv.hh"
00048 #include "XrdOuc/XrdOucStream.hh"
00049 #include "XrdOuc/XrdOucUtils.hh"
00050 #include "XrdSys/XrdSysError.hh"
00051 #include "XrdSys/XrdSysHeaders.hh"
00052 #include "XrdSys/XrdSysLogger.hh"
00053 #include "XrdSys/XrdSysTimer.hh"
00054
00055 #ifdef __linux__
00056 #include <netinet/tcp.h>
00057 #endif
00058 #ifdef __macos__
00059 #include <AvailabilityMacros.h>
00060 #endif
00061
00062
00063
00064
00065
00066 XrdBuffManager XrdBuffPool;
00067
00068 int XrdNetTCPlep = -1;
00069 XrdInet *XrdNetTCP[XrdProtLoad::ProtoMax+1] = {0};
00070 extern XrdInet *XrdNetADM;
00071
00072 extern XrdScheduler XrdSched;
00073
00074 extern XrdSysError XrdLog;
00075
00076 extern XrdSysLogger XrdLogger;
00077
00078 extern XrdSysThread *XrdThread;
00079
00080 extern XrdOucTrace XrdTrace;
00081
00082 const char *XrdConfig::TraceID = "Config";
00083
00084
00085
00086
00087
00088 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
00089
00090 #ifndef S_IAMB
00091 #define S_IAMB 0x1FF
00092 #endif
00093
00094
00095
00096
00097
00098 class XrdConfigProt
00099 {
00100 public:
00101
00102 XrdConfigProt *Next;
00103 char *proname;
00104 char *libpath;
00105 char *parms;
00106 int port;
00107 int wanopt;
00108
00109 XrdConfigProt(char *pn, char *ln, char *pp, int np=-1, int wo=0)
00110 {Next = 0; proname = pn; libpath = ln; parms = pp;
00111 port=np; wanopt = wo;
00112 }
00113 ~XrdConfigProt()
00114 {free(proname);
00115 if (libpath) free(libpath);
00116 if (parms) free(parms);
00117 }
00118 };
00119
00120 class XrdLogWorker : XrdJob
00121 {
00122 public:
00123
00124 void DoIt() {XrdLog.Say(0, XrdBANNER);
00125 XrdLog.Say(0, mememe, " running.");
00126 midnite += 86400;
00127 XrdSched.Schedule((XrdJob *)this, midnite);
00128 }
00129
00130 XrdLogWorker(char *who) : XrdJob("midnight runner")
00131 {midnite = XrdSysTimer::Midnight() + 86400;
00132 mememe = strdup(who);
00133 XrdSched.Schedule((XrdJob *)this, midnite);
00134 }
00135 ~XrdLogWorker() {}
00136 private:
00137 time_t midnite;
00138 const char *mememe;
00139 };
00140
00141
00142
00143
00144
00145 XrdConfig::XrdConfig(void)
00146 {
00147
00148
00149
00150 PortTCP = -1;
00151 PortUDP = -1;
00152 PortWAN = 0;
00153 ConfigFN = 0;
00154 myInsName= 0;
00155 AdminPath= strdup("/tmp");
00156 AdminMode= 0700;
00157 Police = 0;
00158 Net_Blen = 0;
00159 Net_Opts = 0;
00160 Wan_Blen = 1024*1024;
00161 Wan_Opts = 0;
00162 setSched = 1;
00163 repDest[0] = 0;
00164 repDest[1] = 0;
00165 repInt = 600;
00166 repOpts = 0;
00167
00168 Firstcp = Lastcp = 0;
00169
00170 ProtInfo.eDest = &XrdLog;
00171 ProtInfo.NetTCP = 0;
00172 ProtInfo.BPool = &XrdBuffPool;
00173 ProtInfo.Sched = &XrdSched;
00174 ProtInfo.ConfigFN= 0;
00175 ProtInfo.Stats = 0;
00176 ProtInfo.Trace = &XrdTrace;
00177 ProtInfo.Threads = 0;
00178 ProtInfo.AdmPath = AdminPath;
00179 ProtInfo.AdmMode = AdminMode;
00180
00181 ProtInfo.Format = XrdFORMATB;
00182 ProtInfo.WANPort = 0;
00183 ProtInfo.WANWSize = 0;
00184 ProtInfo.WSize = 0;
00185 ProtInfo.ConnMax = -1;
00186 ProtInfo.readWait = 3*1000;
00187 ProtInfo.idleWait = 0;
00188 ProtInfo.hailWait =30*1000;
00189 ProtInfo.DebugON = 0;
00190 ProtInfo.argc = 0;
00191 ProtInfo.argv = 0;
00192 }
00193
00194
00195
00196
00197
00198 int XrdConfig::Configure(int argc, char **argv)
00199 {
00200
00201
00202
00203
00204
00205
00206
00207 const char *xrdInst="XRDINSTANCE=";
00208
00209 static sockaddr myIPAddr;
00210 int n, retc, dotrim = 1, NoGo = 0, aP = 1, clPort = -1, optbg = 0;
00211 const char *temp;
00212 char c, buff[512], *dfltProt, *logfn = 0;
00213 long long logkeep = 0;
00214 uid_t myUid = 0;
00215 gid_t myGid = 0;
00216 extern char *optarg;
00217 extern int optind, opterr;
00218
00219
00220
00221 retc = strlen(argv[0]);
00222 while(retc--) if (argv[0][retc] == '/') break;
00223 myProg = dfltProt = &argv[0][retc+1];
00224
00225
00226
00227 opterr = 0;
00228 if (argc > 1 && '-' == *argv[1])
00229 while ((c = getopt(argc,argv,"bc:dhHk:l:n:p:P:R:"))
00230 && ((unsigned char)c != 0xff))
00231 { switch(c)
00232 {
00233 case 'b': optbg = 1;
00234 break;
00235 case 'c': if (ConfigFN) free(ConfigFN);
00236 ConfigFN = strdup(optarg);
00237 break;
00238 case 'd': XrdTrace.What |= TRACE_ALL;
00239 ProtInfo.DebugON = 1;
00240 putenv((char *)"XRDDEBUG=1");
00241 break;
00242 case 'h': Usage(0);
00243 break;
00244 case 'H': Usage(-1);
00245 break;
00246 case 'k': n = strlen(optarg)-1;
00247 retc = (isalpha(optarg[n])
00248 ? XrdOuca2x::a2sz(XrdLog,"keep size", optarg,&logkeep)
00249 : XrdOuca2x::a2ll(XrdLog,"keep count",optarg,&logkeep));
00250 if (retc) Usage(1);
00251 if (!isalpha(optarg[n])) logkeep = -logkeep;
00252 break;
00253 case 'l': if (logfn) free(logfn);
00254 logfn = strdup(optarg);
00255 break;
00256 case 'n': myInsName = optarg;
00257 break;
00258 case 'p': if ((clPort = yport(&XrdLog, "tcp", optarg)) < 0) Usage(1);
00259 break;
00260 case 'P': dfltProt = optarg; dotrim = 0;
00261 break;
00262 case 'R': if (!(getUG(optarg, myUid, myGid))) Usage(1);
00263 break;
00264 default: if (index("clpP", (int)(*(argv[optind-1]+1))))
00265 {XrdLog.Emsg("Config", argv[optind-1],
00266 "parameter not specified.");
00267 Usage(1);
00268 }
00269 argv[aP++] = argv[optind-1];
00270 if (argv[optind] && *argv[optind] != '-')
00271 argv[aP++] = argv[optind++];
00272 }
00273 }
00274
00275
00276
00277 if (myGid && setegid(myGid))
00278 {XrdLog.Emsg("Config", errno, "set effective gid"); exit(17);}
00279 if (myUid && seteuid(myUid))
00280 {XrdLog.Emsg("Config", errno, "set effective uid"); exit(17);}
00281
00282
00283
00284 if (aP != optind)
00285 {for ( ; optind < argc; optind++) argv[aP++] = argv[optind];
00286 argv[aP] = 0;
00287 ProtInfo.argc = aP;
00288 } else ProtInfo.argc = argc;
00289 ProtInfo.argv = argv;
00290
00291
00292
00293 if (optbg) XrdOucUtils::Undercover(XrdLog, !logfn);
00294
00295
00296
00297 if (logfn)
00298 {char *lP;
00299 if (!(logfn = XrdOucUtils::subLogfn(XrdLog, myInsName, logfn))) _exit(16);
00300 if (logkeep) XrdLogger.setKeep(logkeep);
00301 XrdLogger.Bind(logfn, 24*60*60);
00302 if ((lP = rindex(logfn,'/'))) {*(lP+1) = '\0'; lP = logfn;}
00303 else lP = (char *)"./";
00304 XrdOucEnv::Export("XRDLOGDIR", lP);
00305 free(logfn);
00306 }
00307
00308
00309
00310 if (!(myName = XrdNetDNS::getHostName()))
00311 {XrdLog.Emsg("Config", "Unable to determine host name; "
00312 "execution terminated.");
00313 _exit(16);
00314 }
00315
00316
00317
00318
00319
00320 if (isdigit(*myName) && (isdigit(*(myName+1)) || *(myName+1) == '.'))
00321 {XrdLog.Emsg("Config", myName, "is not the true host name of this machine.");
00322 XrdLog.Emsg("Config", "Verify that the '/etc/hosts' file is correct and "
00323 "this machine is registered in DNS.");
00324 XrdLog.Emsg("Config", "Execution continues but connection failures may occur.");
00325 myDomain = 0;
00326 } else if (!(myDomain = index(myName, '.')))
00327 XrdLog.Say("Config warning: this hostname, ", myName,
00328 ", is registered without a domain qualification.");
00329
00330
00331
00332 XrdNetDNS::getHostAddr(myName, &myIPAddr);
00333 ProtInfo.myName = myName;
00334 ProtInfo.myAddr = &myIPAddr;
00335 ProtInfo.myInst = XrdOucUtils::InstName(myInsName);
00336 ProtInfo.myProg = myProg;
00337
00338
00339
00340
00341
00342 sprintf(buff,"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName);
00343 myInstance = strdup(buff);
00344 putenv(myInstance);
00345 myInstance += strlen(xrdInst);
00346 XrdOucEnv::Export("XRDHOST", myName);
00347 XrdOucEnv::Export("XRDNAME", ProtInfo.myInst);
00348 XrdOucEnv::Export("XRDPROG", myProg);
00349
00350
00351
00352 XrdLog.Say(0, "Scalla is starting. . .");
00353 XrdLog.Say(XrdBANNER);
00354
00355
00356
00357 if (dotrim && *dfltProt != '.' )
00358 {char *p = dfltProt;
00359 while (*p && *p != '.') p++;
00360 if (*p == '.') *p = '\0';
00361 }
00362 Firstcp = Lastcp = new XrdConfigProt(strdup(dfltProt), 0, 0);
00363
00364
00365
00366 XrdLog.Say("++++++ ", myInstance, " initialization started.");
00367 if (ConfigFN && *ConfigFN)
00368 {XrdLog.Say("Config using configuration file ", ConfigFN);
00369 ProtInfo.ConfigFN = ConfigFN;
00370 XrdOucEnv::Export("XRDCONFIGFN", ConfigFN);
00371 NoGo = ConfigProc();
00372 }
00373 if (clPort >= 0) PortTCP = clPort;
00374 if (ProtInfo.DebugON)
00375 {XrdTrace.What = TRACE_ALL;
00376 XrdSysThread::setDebug(&XrdLog);
00377 }
00378 if (!NoGo) NoGo = Setup(dfltProt);
00379 ProtInfo.Threads = XrdThread;
00380
00381
00382
00383 if (myInsName) XrdOucUtils::makeHome(XrdLog, myInsName);
00384
00385
00386
00387 temp = (NoGo ? " initialization failed." : " initialization completed.");
00388 sprintf(buff, "%s:%d", myInstance, PortTCP);
00389 XrdLog.Say("------ ", buff, temp);
00390 if (logfn) new XrdLogWorker(buff);
00391 return NoGo;
00392 }
00393
00394
00395
00396
00397
00398 int XrdConfig::ConfigXeq(char *var, XrdOucStream &Config, XrdSysError *eDest)
00399 {
00400 int dynamic;
00401
00402
00403
00404 if (eDest) dynamic = 1;
00405 else {dynamic = 0; eDest = &XrdLog;}
00406
00407
00408
00409 TS_Xeq("buffers", xbuf);
00410 TS_Xeq("network", xnet);
00411 TS_Xeq("sched", xsched);
00412 TS_Xeq("trace", xtrace);
00413
00414
00415
00416 if (!dynamic)
00417 {
00418 TS_Xeq("adminpath", xapath);
00419 TS_Xeq("allow", xallow);
00420 TS_Xeq("port", xport);
00421 TS_Xeq("protocol", xprot);
00422 TS_Xeq("report", xrep);
00423 TS_Xeq("timeout", xtmo);
00424 }
00425
00426
00427
00428 eDest->Say("Config warning: ignoring unknown xrd directive '",var,"'.");
00429 Config.Echo();
00430 return 0;
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440 int XrdConfig::ASocket(const char *path, const char *fname, mode_t mode)
00441 {
00442 char xpath[MAXPATHLEN+8], sokpath[108];
00443 int plen = strlen(path), flen = strlen(fname);
00444 int rc;
00445
00446
00447
00448 if ((plen + flen + 3) > (int)sizeof(sokpath))
00449 {XrdLog.Emsg("Config", "admin path", path, "too long");
00450 return 1;
00451 }
00452
00453
00454
00455 strcpy(xpath, path);
00456 if ((rc = XrdOucUtils::makePath(xpath, mode)))
00457 {XrdLog.Emsg("Config", rc, "create admin path", xpath);
00458 return 1;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 return 0;
00484 }
00485
00486
00487
00488
00489
00490 int XrdConfig::ConfigProc()
00491 {
00492 char *var;
00493 int cfgFD, retc, NoGo = 0;
00494 XrdOucEnv myEnv;
00495 XrdOucStream Config(&XrdLog, myInstance, &myEnv, "=====> ");
00496
00497
00498
00499 if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00500 {XrdLog.Emsg("Config", errno, "open config file", ConfigFN);
00501 return 1;
00502 }
00503 Config.Attach(cfgFD);
00504
00505
00506
00507 while((var = Config.GetMyFirstWord()))
00508 if (!strncmp(var, "xrd.", 4)
00509 || !strcmp (var, "all.adminpath"))
00510 if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
00511
00512
00513
00514 if ((retc = Config.LastError()))
00515 NoGo = XrdLog.Emsg("Config", retc, "read config file", ConfigFN);
00516 Config.Close();
00517
00518
00519
00520 return NoGo;
00521 }
00522
00523
00524
00525
00526
00527 int XrdConfig::getUG(char *parm, uid_t &newUid, gid_t &newGid)
00528 {
00529 struct passwd *pp;
00530
00531
00532
00533 if (!(*parm))
00534 {XrdLog.Emsg("Config", "-R user not specified."); return 0;}
00535
00536 if (isdigit(*parm))
00537 {if (!(newUid = atol(parm)))
00538 {XrdLog.Emsg("Config", "-R", parm, "is invalid"); return 0;}
00539 pp = getpwuid(newUid);
00540 }
00541 else pp = getpwnam(parm);
00542
00543
00544
00545 if (!pp)
00546 {XrdLog.Emsg("Config", errno, "retrieve -R user password entry");
00547 return 0;
00548 }
00549 if (!(newUid = pp->pw_uid))
00550 {XrdLog.Emsg("Config", "-R", parm, "is still unacceptably a superuser!");
00551 return 0;
00552 }
00553 newGid = pp->pw_gid;
00554 return 1;
00555 }
00556
00557
00558
00559
00560
00561 int XrdConfig::setFDL()
00562 {
00563 struct rlimit rlim;
00564 char buff[100];
00565
00566
00567
00568 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
00569 return XrdLog.Emsg("Config", errno, "get FD limit");
00570
00571
00572
00573 rlim.rlim_cur = rlim.rlim_max;
00574 #if (defined(__macos__) && defined(MAC_OS_X_VERSION_10_5))
00575 if (rlim.rlim_cur == RLIM_INFINITY || rlim.rlim_cur > OPEN_MAX)
00576 rlim.rlim_cur = OPEN_MAX;
00577 #endif
00578 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
00579 return XrdLog.Emsg("Config", errno,"set FD limit");
00580
00581
00582
00583 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
00584 return XrdLog.Emsg("Config", errno, "get FD limit");
00585
00586
00587
00588 ProtInfo.ConnMax = rlim.rlim_cur;
00589 sprintf(buff, "%d", ProtInfo.ConnMax);
00590 XrdLog.Say("Config maximum number of connections restricted to ", buff);
00591
00592 return 0;
00593 }
00594
00595
00596
00597
00598
00599 int XrdConfig::Setup(char *dfltp)
00600 {
00601 XrdInet *NetWAN;
00602 XrdConfigProt *cp, *pp, *po, *POrder = 0;
00603 int wsz, lastPort = -17;
00604
00605
00606
00607 if (setFDL()) return 1;
00608
00609
00610
00611 #if defined(__linux__) && defined(TCP_CORK)
00612 { int sokFD, setON = 1;
00613 if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
00614 {setsockopt(sokFD, XrdNetDNS::getProtoID("tcp"), TCP_NODELAY,
00615 &setON, sizeof(setON));
00616 if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON, sizeof(setON)) < 0)
00617 XrdLink::sfOK = 0;
00618 close(sokFD);
00619 }
00620 }
00621 #endif
00622
00623
00624
00625 TRACE(NET,"sendfile " <<(XrdLink::sfOK ? "enabled." : "disabled!"));
00626
00627
00628
00629 XrdBuffPool.Init();
00630
00631
00632
00633 XrdSched.Start();
00634
00635
00636
00637 if (!XrdLink::Setup(ProtInfo.ConnMax, ProtInfo.idleWait)
00638 || !XrdPoll::Setup(ProtInfo.ConnMax)) return 1;
00639
00640
00641
00642
00643
00644 if (myInsName) ProtInfo.AdmPath = XrdOucUtils::genPath(AdminPath,myInsName);
00645 else ProtInfo.AdmPath = AdminPath;
00646 XrdOucEnv::Export("XRDADMINPATH", ProtInfo.AdmPath);
00647 AdminPath = XrdOucUtils::genPath(AdminPath, myInsName, ".xrd");
00648
00649
00650
00651 if (ASocket(AdminPath, "admin", (mode_t)AdminMode)) return 1;
00652
00653
00654
00655 if (PortTCP < 0)
00656 {if ((PortTCP = XrdNetDNS::getPort(dfltp, "tcp"))) PortUDP = PortTCP;
00657 else PortTCP = -1;
00658 }
00659
00660
00661
00662
00663
00664 while((cp = Firstcp))
00665 {ProtInfo.Port = (cp->port < 0 ? PortTCP : cp->port);
00666 XrdOucEnv::Export("XRDPORT", ProtInfo.Port);
00667 if ((cp->port = XrdProtLoad::Port(cp->libpath, cp->proname,
00668 cp->parms, &ProtInfo)) < 0) return 1;
00669 pp = 0; po = POrder; Firstcp = cp->Next;
00670 while(po && po->port > cp->port) {pp = po; po = po->Next;}
00671 if (pp) {pp->Next = cp; cp->Next = po;}
00672 else {cp->Next = POrder; POrder = cp;}
00673 }
00674
00675
00676
00677
00678 ProtInfo.Stats = new XrdStats(ProtInfo.myName, POrder->port,
00679 ProtInfo.myInst, ProtInfo.myProg);
00680
00681
00682
00683 if (PortWAN && (NetWAN = new XrdInet(&XrdLog, Police)))
00684 {if (Wan_Opts || Wan_Blen) NetWAN->setDefaults(Wan_Opts, Wan_Blen);
00685 if (myDomain) NetWAN->setDomain(myDomain);
00686 if (NetWAN->Bind((PortWAN > 0 ? PortWAN : 0), "tcp")) return 1;
00687 PortWAN = NetWAN->Port();
00688 wsz = NetWAN->WSize();
00689 Wan_Blen = (wsz < Wan_Blen || !Wan_Blen ? wsz : Wan_Blen);
00690 TRACE(NET,"WAN port " <<PortWAN <<" wsz=" <<Wan_Blen <<" (" <<wsz <<')');
00691 XrdNetTCP[XrdProtLoad::ProtoMax] = NetWAN;
00692 } else {PortWAN = 0; Wan_Blen = 0;}
00693
00694
00695
00696
00697
00698 while((cp= POrder))
00699 {if (cp->port != lastPort)
00700 {XrdNetTCP[++XrdNetTCPlep] = new XrdInet(&XrdLog, Police);
00701 if (Net_Opts || Net_Blen)
00702 XrdNetTCP[XrdNetTCPlep]->setDefaults(Net_Opts, Net_Blen);
00703 if (myDomain) XrdNetTCP[XrdNetTCPlep]->setDomain(myDomain);
00704 if (XrdNetTCP[XrdNetTCPlep]->Bind(cp->port, "tcp")) return 1;
00705 ProtInfo.Port = XrdNetTCP[XrdNetTCPlep]->Port();
00706 ProtInfo.NetTCP = XrdNetTCP[XrdNetTCPlep];
00707 wsz = XrdNetTCP[XrdNetTCPlep]->WSize();
00708 ProtInfo.WSize = (wsz < Net_Blen || !Net_Blen ? wsz : Net_Blen);
00709 TRACE(NET,"LCL port " <<ProtInfo.Port <<" wsz=" <<ProtInfo.WSize
00710 <<" (" <<wsz <<')');
00711 if (cp->wanopt)
00712 {ProtInfo.WANPort = PortWAN;
00713 ProtInfo.WANWSize= Wan_Blen;
00714 } else ProtInfo.WANPort = ProtInfo.WANWSize = 0;
00715 XrdOucEnv::Export("XRDPORT", ProtInfo.Port);
00716 lastPort = cp->port;
00717 }
00718 if (!XrdProtLoad::Load(cp->libpath,cp->proname,cp->parms,&ProtInfo))
00719 return 1;
00720 POrder = cp->Next;
00721 delete cp;
00722 }
00723
00724
00725
00726
00727 ProtInfo.Port = XrdNetTCP[0]->Port();
00728 PortTCP = ProtInfo.Port;
00729 XrdOucEnv::Export("XRDPORT", PortTCP);
00730
00731
00732
00733 if (repDest[0] != 0 && repOpts)
00734 ProtInfo.Stats->Report(repDest, repInt, repOpts);
00735
00736
00737
00738 return 0;
00739 }
00740
00741
00742
00743
00744
00745 void XrdConfig::Usage(int rc)
00746 {
00747 extern const char *XrdLicense;
00748
00749 if (rc < 0) cerr <<XrdLicense;
00750 else
00751 cerr <<"\nUsage: " <<myProg <<" [-b] [-c <cfn>] [-d] [-k {n|sz}] [-l <fn>] "
00752 "[-L] [-n name] [-p <port>] [-P <prot>] [<prot_options>]" <<endl;
00753 _exit(rc > 0 ? rc : 0);
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 int XrdConfig::xapath(XrdSysError *eDest, XrdOucStream &Config)
00774 {
00775 char *pval, *val;
00776 mode_t mode = S_IRWXU;
00777
00778
00779
00780 pval = Config.GetWord();
00781 if (!pval || !pval[0])
00782 {eDest->Emsg("Config", "adminpath not specified"); return 1;}
00783
00784
00785
00786 if (*pval != '/')
00787 {eDest->Emsg("Config", "adminpath not absolute"); return 1;}
00788
00789
00790
00791 if (AdminPath) free(AdminPath);
00792 AdminPath = strdup(pval);
00793
00794
00795
00796 if ((val = Config.GetWord()) && val[0])
00797 {if (!strcmp("group", val)) mode |= S_IRWXG;
00798 else {eDest->Emsg("Config", "invalid admin path modifier -", val);
00799 return 1;
00800 }
00801 }
00802 AdminMode = ProtInfo.AdmMode = mode;
00803 return 0;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 int XrdConfig::xallow(XrdSysError *eDest, XrdOucStream &Config)
00822 {
00823 char *val;
00824 int ishost;
00825
00826 if (!(val = Config.GetWord()))
00827 {eDest->Emsg("Config", "allow type not specified"); return 1;}
00828
00829 if (!strcmp(val, "host")) ishost = 1;
00830 else if (!strcmp(val, "netgroup")) ishost = 0;
00831 else {eDest->Emsg("Config", "invalid allow type -", val);
00832 return 1;
00833 }
00834
00835 if (!(val = Config.GetWord()))
00836 {eDest->Emsg("Config", "allow target name not specified"); return 1;}
00837
00838 if (!Police) Police = new XrdNetSecurity();
00839 if (ishost) Police->AddHost(val);
00840 else Police->AddNetGroup(val);
00841
00842 return 0;
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858 int XrdConfig::xbuf(XrdSysError *eDest, XrdOucStream &Config)
00859 {
00860 int bint = -1;
00861 long long blim;
00862 char *val;
00863
00864 if (!(val = Config.GetWord()))
00865 {eDest->Emsg("Config", "buffer memory limit not specified"); return 1;}
00866 if (XrdOuca2x::a2sz(*eDest,"buffer limit value",val,&blim,
00867 (long long)1024*1024)) return 1;
00868
00869 if ((val = Config.GetWord()))
00870 if (XrdOuca2x::a2tm(*eDest,"reshape interval", val, &bint, 300))
00871 return 1;
00872
00873 XrdBuffPool.Set((int)blim, bint);
00874 return 0;
00875 }
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 int XrdConfig::xnet(XrdSysError *eDest, XrdOucStream &Config)
00895 {
00896 char *val;
00897 int i, V_keep = 0, V_nodnr = 0, V_iswan = 0, V_blen = -1;
00898 long long llp;
00899 static struct netopts {const char *opname; int hasarg; int opval;
00900 int *oploc; const char *etxt;}
00901 ntopts[] =
00902 {
00903 {"keepalive", 0, 1, &V_keep, "option"},
00904 {"buffsz", 1, 0, &V_blen, "network buffsz"},
00905 {"dnr", 0, 0, &V_nodnr, "option"},
00906 {"nodnr", 0, 1, &V_nodnr, "option"},
00907 {"wan", 0, 1, &V_iswan, "option"}
00908 };
00909 int numopts = sizeof(ntopts)/sizeof(struct netopts);
00910
00911 if (!(val = Config.GetWord()))
00912 {eDest->Emsg("Config", "net option not specified"); return 1;}
00913
00914 while (val)
00915 {for (i = 0; i < numopts; i++)
00916 if (!strcmp(val, ntopts[i].opname))
00917 {if (!ntopts[i].hasarg) llp=static_cast<long long>(ntopts[i].opval);
00918 else {if (!(val = Config.GetWord()))
00919 {eDest->Emsg("Config", "network",
00920 ntopts[i].opname, ntopts[i].etxt);
00921 return 1;
00922 }
00923 if (XrdOuca2x::a2sz(*eDest,ntopts[i].etxt,val,&llp,0))
00924 return 1;
00925 }
00926 *ntopts[i].oploc = (int)llp;
00927 break;
00928 }
00929 if (i >= numopts)
00930 eDest->Say("Config warning: ignoring invalid net option '",val,"'.");
00931 val = Config.GetWord();
00932 }
00933
00934 if (V_iswan)
00935 {if (V_blen >= 0) Wan_Blen = V_blen;
00936 Wan_Opts = (V_keep ? XRDNET_KEEPALIVE : 0)
00937 | (V_nodnr ? XRDNET_NORLKUP : 0);
00938 if (!PortWAN) PortWAN = -1;
00939 } else {
00940 if (V_blen >= 0) Net_Blen = V_blen;
00941 Net_Opts = (V_keep ? XRDNET_KEEPALIVE : 0)
00942 | (V_nodnr ? XRDNET_NORLKUP : 0);
00943 }
00944 return 0;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 int XrdConfig::xport(XrdSysError *eDest, XrdOucStream &Config)
00964 { int rc, iswan = 0, pnum = 0;
00965 char *val, cport[32];
00966
00967 do {if (!(val = Config.GetWord()))
00968 {eDest->Emsg("Config", "tcp port not specified"); return 1;}
00969 if (strcmp("wan", val) || iswan) break;
00970 iswan = 1;
00971 } while(1);
00972
00973 strncpy(cport, val, sizeof(cport)-1); cport[sizeof(cport)-1] = '\0';
00974
00975 if ((val = Config.GetWord()) && !strcmp("if", val))
00976 if ((rc = XrdOucUtils::doIf(eDest,Config, "port directive", myName,
00977 ProtInfo.myInst, myProg)) <= 0) return (rc < 0);
00978
00979 if ((pnum = yport(eDest, "tcp", cport)) < 0) return 1;
00980 if (iswan) PortWAN = pnum;
00981 else PortTCP = PortUDP = pnum;
00982
00983 return 0;
00984 }
00985
00986
00987
00988 int XrdConfig::yport(XrdSysError *eDest, const char *ptype, const char *val)
00989 {
00990 int pnum;
00991 if (!strcmp("any", val)) return 0;
00992
00993 const char *invp = (*ptype == 't' ? "tcp port" : "udp port" );
00994 const char *invs = (*ptype == 't' ? "Unable to find tcp service" :
00995 "Unable to find udp service" );
00996
00997 if (isdigit(*val))
00998 {if (XrdOuca2x::a2i(*eDest,invp,val,&pnum,1,65535)) return 0;}
00999 else if (!(pnum = XrdNetDNS::getPort(val, "tcp")))
01000 {eDest->Emsg("Config", invs, val);
01001 return -1;
01002 }
01003 return pnum;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023 int XrdConfig::xprot(XrdSysError *eDest, XrdOucStream &Config)
01024 {
01025 XrdConfigProt *cpp;
01026 char *val, *parms, *lib, proname[64], buff[1024];
01027 int vlen, bleft = sizeof(buff), portnum = -1, wanopt = 0;
01028
01029 do {if (!(val = Config.GetWord()))
01030 {eDest->Emsg("Config", "protocol name not specified"); return 1;}
01031 if (wanopt || strcmp("wan", val)) break;
01032 wanopt = 1;
01033 } while(1);
01034
01035 if (strlen(val) > sizeof(proname)-1)
01036 {eDest->Emsg("Config", "protocol name is too long"); return 1;}
01037 strcpy(proname, val);
01038
01039 if (!(val = Config.GetWord()))
01040 {eDest->Emsg("Config", "protocol library not specified"); return 1;}
01041 if (strcmp("*", val)) lib = strdup(val);
01042 else lib = 0;
01043
01044 parms = buff;
01045 while((val = Config.GetWord()))
01046 {vlen = strlen(val); bleft -= (vlen+1);
01047 if (bleft <= 0)
01048 {eDest->Emsg("Config", "Too many parms for protocol", proname);
01049 return 1;
01050 }
01051 *parms = ' '; parms++; strcpy(parms, val); parms += vlen;
01052 }
01053 if (parms != buff) parms = strdup(buff+1);
01054 else parms = 0;
01055
01056 if ((val = index(proname, ':')))
01057 {if ((portnum = yport(&XrdLog, "tcp", val+1)) < 0) return 1;
01058 else *val = '\0';
01059 }
01060
01061 if (wanopt && !PortWAN) PortWAN = 1;
01062
01063 if ((cpp = Firstcp))
01064 do {if (!strcmp(proname, cpp->proname))
01065 {if (cpp->libpath) free(cpp->libpath);
01066 if (cpp->parms) free(cpp->parms);
01067 cpp->libpath = lib;
01068 cpp->parms = parms;
01069 cpp->wanopt = wanopt;
01070 return 0;
01071 }
01072 } while((cpp = cpp->Next));
01073
01074 if (lib)
01075 {cpp = new XrdConfigProt(strdup(proname), lib, parms, portnum, wanopt);
01076 if (Lastcp) Lastcp->Next = cpp;
01077 else Firstcp = cpp;
01078 Lastcp = cpp;
01079 }
01080
01081 return 0;
01082 }
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105 int XrdConfig::xrep(XrdSysError *eDest, XrdOucStream &Config)
01106 {
01107 static struct repopts {const char *opname; int opval;} rpopts[] =
01108 {
01109 {"all", XRD_STATS_ALL},
01110 {"buff", XRD_STATS_BUFF},
01111 {"info", XRD_STATS_INFO},
01112 {"link", XRD_STATS_LINK},
01113 {"poll", XRD_STATS_POLL},
01114 {"process", XRD_STATS_PROC},
01115 {"protocols",XRD_STATS_PROT},
01116 {"prot", XRD_STATS_PROT},
01117 {"sched", XRD_STATS_SCHD},
01118 {"sgen", XRD_STATS_SGEN},
01119 {"sync", XRD_STATS_SYNC},
01120 {"syncwp", XRD_STATS_SYNCA}
01121 };
01122 int i, neg, numopts = sizeof(rpopts)/sizeof(struct repopts);
01123 char *val, *cp;
01124
01125 if (!(val = Config.GetWord()))
01126 {eDest->Emsg("Config", "report parameters not specified"); return 1;}
01127
01128
01129
01130 if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
01131 if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
01132 repOpts = 0;
01133 repInt = 600;
01134
01135
01136
01137 if ((cp = (char *)index(val, ',')))
01138 {if (!*(cp+1))
01139 {eDest->Emsg("Config","malformed report destination -",val); return 1;}
01140 else { repDest[1] = cp+1; *cp = '\0';}
01141 }
01142 repDest[0] = val;
01143 for (i = 0; i < 2; i++)
01144 {if (!(val = repDest[i])) break;
01145 if (*val != '/' && (!(cp = index(val, (int)':')) || !atoi(cp+1)))
01146 {eDest->Emsg("Config","report dest port missing or invalid in",val);
01147 return 1;
01148 }
01149 repDest[i] = strdup(val);
01150 }
01151
01152
01153
01154 if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
01155 {eDest->Emsg("Config", "Warning, report dests are identical.");
01156 free(repDest[1]); repDest[1] = 0;
01157 }
01158
01159
01160
01161 if (!(val = Config.GetWord())) {repOpts = XRD_STATS_ALL; return 0;}
01162 if (!strcmp("every", val))
01163 {if (!(val = Config.GetWord()))
01164 {eDest->Emsg("Config", "report every value not specified"); return 1;}
01165 if (XrdOuca2x::a2tm(*eDest,"report every",val,&repInt,1)) return 1;
01166 val = Config.GetWord();
01167 }
01168
01169
01170
01171 while(val)
01172 {if (!strcmp(val, "off")) repOpts = 0;
01173 else {if ((neg = (val[0] == '-' && val[1]))) val++;
01174 for (i = 0; i < numopts; i++)
01175 {if (!strcmp(val, rpopts[i].opname))
01176 {if (neg) repOpts &= ~rpopts[i].opval;
01177 else repOpts |= rpopts[i].opval;
01178 break;
01179 }
01180 }
01181 if (i >= numopts)
01182 eDest->Say("Config warning: ignoring invalid report option '",val,"'.");
01183 }
01184 val = Config.GetWord();
01185 }
01186
01187
01188
01189 if (!(repOpts & XRD_STATS_ALL)) repOpts = XRD_STATS_ALL & ~XRD_STATS_INFO;
01190 return 0;
01191 }
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 int XrdConfig::xsched(XrdSysError *eDest, XrdOucStream &Config)
01219 {
01220 char *val;
01221 long long lpp;
01222 int i, ppp;
01223 int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
01224 static struct schedopts {const char *opname; int minv; int *oploc;
01225 const char *opmsg;} scopts[] =
01226 {
01227 {"stksz", 0, 0, "sched stksz"},
01228 {"mint", 1, &V_mint, "sched mint"},
01229 {"maxt", 1, &V_maxt, "sched maxt"},
01230 {"avlt", 1, &V_avlt, "sched avlt"},
01231 {"idle", 0, &V_idle, "sched idle"}
01232 };
01233 int numopts = sizeof(scopts)/sizeof(struct schedopts);
01234
01235 if (!(val = Config.GetWord()))
01236 {eDest->Emsg("Config", "sched option not specified"); return 1;}
01237
01238 while (val)
01239 {for (i = 0; i < numopts; i++)
01240 if (!strcmp(val, scopts[i].opname))
01241 {if (!(val = Config.GetWord()))
01242 {eDest->Emsg("Config", "sched", scopts[i].opname,
01243 "value not specified");
01244 return 1;
01245 }
01246 if (*scopts[i].opname == 'i')
01247 {if (XrdOuca2x::a2tm(*eDest, scopts[i].opmsg, val,
01248 &ppp, scopts[i].minv)) return 1;
01249 }
01250 else if (*scopts[i].opname == 's')
01251 {if (XrdOuca2x::a2sz(*eDest, scopts[i].opmsg, val,
01252 &lpp, scopts[i].minv)) return 1;
01253 XrdSysThread::setStackSize((size_t)lpp);
01254 break;
01255 }
01256 else if (XrdOuca2x::a2i(*eDest, scopts[i].opmsg, val,
01257 &ppp,scopts[i].minv)) return 1;
01258 *scopts[i].oploc = ppp;
01259 break;
01260 }
01261 if (i >= numopts)
01262 eDest->Say("Config warning: ignoring invalid sched option '",val,"'.");
01263 val = Config.GetWord();
01264 }
01265
01266
01267
01268 if (V_maxt > 0)
01269 {if (V_mint > 0 && V_mint > V_maxt)
01270 {eDest->Emsg("Config", "sched mint must be less than maxt");
01271 return 1;
01272 }
01273 if (V_avlt > 0 && V_avlt > V_maxt)
01274 {eDest->Emsg("Config", "sched avlt must be less than maxt");
01275 return 1;
01276 }
01277 }
01278
01279
01280
01281 if (V_mint > 0 || V_maxt > 0 || V_avlt > 0) setSched = 0;
01282 XrdSched.setParms(V_mint, V_maxt, V_avlt, V_idle);
01283 return 0;
01284 }
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 int XrdConfig::xtmo(XrdSysError *eDest, XrdOucStream &Config)
01309 {
01310 char *val;
01311 int i, ppp, rc;
01312 int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
01313 static struct tmoopts { const char *opname; int istime; int minv;
01314 int *oploc; const char *etxt;}
01315 tmopts[] =
01316 {
01317 {"read", 1, 1, &V_read, "timeout read"},
01318 {"hail", 1, 1, &V_hail, "timeout hail"},
01319 {"idle", 1, 0, &V_idle, "timeout idle"},
01320 {"kill", 1, 0, &V_kill, "timeout kill"}
01321 };
01322 int numopts = sizeof(tmopts)/sizeof(struct tmoopts);
01323
01324 if (!(val = Config.GetWord()))
01325 {eDest->Emsg("Config", "timeout option not specified"); return 1;}
01326
01327 while (val)
01328 {for (i = 0; i < numopts; i++)
01329 if (!strcmp(val, tmopts[i].opname))
01330 {if (!(val = Config.GetWord()))
01331 {eDest->Emsg("Config","timeout", tmopts[i].opname,
01332 "value not specified");
01333 return 1;
01334 }
01335 rc = (tmopts[i].istime ?
01336 XrdOuca2x::a2tm(*eDest,tmopts[i].etxt,val,&ppp,
01337 tmopts[i].minv) :
01338 XrdOuca2x::a2i (*eDest,tmopts[i].etxt,val,&ppp,
01339 tmopts[i].minv));
01340 if (rc) return 1;
01341 *tmopts[i].oploc = ppp;
01342 break;
01343 }
01344 if (i >= numopts)
01345 eDest->Say("Config warning: ignoring invalid timeout option '",val,"'.");
01346 val = Config.GetWord();
01347 }
01348
01349
01350
01351 if (V_read > 0) ProtInfo.readWait = V_read*1000;
01352 if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
01353 if (V_idle >= 0) ProtInfo.idleWait = V_idle;
01354 XrdLink::setKWT(V_read, V_kill);
01355 return 0;
01356 }
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 int XrdConfig::xtrace(XrdSysError *eDest, XrdOucStream &Config)
01373 {
01374 char *val;
01375 static struct traceopts {const char *opname; int opval;} tropts[] =
01376 {
01377 {"all", TRACE_ALL},
01378 {"off", TRACE_NONE},
01379 {"none", TRACE_NONE},
01380 {"conn", TRACE_CONN},
01381 {"debug", TRACE_DEBUG},
01382 {"mem", TRACE_MEM},
01383 {"net", TRACE_NET},
01384 {"poll", TRACE_POLL},
01385 {"protocol", TRACE_PROT},
01386 {"sched", TRACE_SCHED}
01387 };
01388 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
01389
01390 if (!(val = Config.GetWord()))
01391 {eDest->Emsg("Config", "trace option not specified"); return 1;}
01392 while (val)
01393 {if (!strcmp(val, "off")) trval = 0;
01394 else {if ((neg = (val[0] == '-' && val[1]))) val++;
01395 for (i = 0; i < numopts; i++)
01396 {if (!strcmp(val, tropts[i].opname))
01397 {if (neg)
01398 if (tropts[i].opval) trval &= ~tropts[i].opval;
01399 else trval = TRACE_ALL;
01400 else if (tropts[i].opval) trval |= tropts[i].opval;
01401 else trval = TRACE_NONE;
01402 break;
01403 }
01404 }
01405 if (i >= numopts)
01406 eDest->Say("Config warning: ignoring invalid trace option '",val,"'.");
01407 }
01408 val = Config.GetWord();
01409 }
01410 XrdTrace.What = trval;
01411 return 0;
01412 }