XRootD
XrdConfig.cc
Go to the documentation of this file.
1 /*******************************************************************************/
2 /* */
3 /* X r d C o n f i g . c c */
4 /* */
5 /* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Deprtment of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 /*
31  The default port number comes from:
32  1) The command line option,
33  2) The config file,
34  3) The /etc/services file for service corresponding to the program name.
35 */
36 
37 #include <unistd.h>
38 #include <cctype>
39 #include <fcntl.h>
40 #include <pwd.h>
41 #include <cstdint>
42 #include <string>
43 #include <cstring>
44 #include <cstdio>
45 #include <sys/param.h>
46 #include <sys/resource.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <sys/un.h>
50 #include <algorithm>
51 #include <limits>
52 
53 #include "XrdVersion.hh"
54 
55 #include "Xrd/XrdBuffer.hh"
56 #include "Xrd/XrdBuffXL.hh"
57 #include "Xrd/XrdConfig.hh"
58 #include "Xrd/XrdInet.hh"
59 #include "Xrd/XrdInfo.hh"
60 #include "Xrd/XrdLink.hh"
61 #include "Xrd/XrdLinkCtl.hh"
62 #include "Xrd/XrdPoll.hh"
63 #include "Xrd/XrdScheduler.hh"
64 #include "Xrd/XrdStats.hh"
65 #include "Xrd/XrdTrace.hh"
66 
67 #include "XrdNet/XrdNetAddr.hh"
68 #include "XrdNet/XrdNetIF.hh"
69 #include "XrdNet/XrdNetSecurity.hh"
70 #include "XrdNet/XrdNetUtils.hh"
71 
72 #include "XrdOuc/XrdOuca2x.hh"
73 #include "XrdOuc/XrdOucEnv.hh"
74 #include "XrdOuc/XrdOucLogging.hh"
75 #include "XrdOuc/XrdOucPinKing.hh"
76 #include "XrdOuc/XrdOucSiteName.hh"
77 #include "XrdOuc/XrdOucStream.hh"
78 #include "XrdOuc/XrdOucString.hh"
79 #include "XrdOuc/XrdOucUtils.hh"
80 
81 #include "XrdSys/XrdSysError.hh"
82 #include "XrdSys/XrdSysFD.hh"
83 #include "XrdSys/XrdSysHeaders.hh"
84 #include "XrdSys/XrdSysLogger.hh"
85 #include "XrdSys/XrdSysTimer.hh"
86 #include "XrdSys/XrdSysUtils.hh"
87 
88 #include "XrdTcpMonPin.hh"
89 
90 #include "XrdTls/XrdTls.hh"
91 #include "XrdTls/XrdTlsContext.hh"
92 
93 #if defined(__linux__) || defined(__GNU__)
94 #include <netinet/tcp.h>
95 #endif
96 #if defined(__linux__)
97 #include <sys/epoll.h>
98 #endif
99 #ifdef __APPLE__
100 #include <AvailabilityMacros.h>
101 #endif
102 
103 /******************************************************************************/
104 /* G l o b a l O b j e c t s */
105 /******************************************************************************/
106 
107 namespace XrdGlobal
108 {
110 extern XrdSysLogger Logger;
112 extern XrdSysTrace XrdTrace;
113 extern XrdScheduler Sched;
114 extern XrdBuffManager BuffPool;
115 extern XrdTlsContext *tlsCtx;
116 extern XrdInet *XrdNetTCP;
117 extern XrdBuffXL xlBuff;
118 extern XrdTcpMonPin *TcpMonPin;
119 extern int devNull;
120 };
121 
122 using namespace XrdGlobal;
123 
125 {
126 extern int ka_Idle;
127 extern int ka_Itvl;
128 extern int ka_Icnt;
129 };
130 
131 /******************************************************************************/
132 /* F i l e L o c a l O b j e c t s */
133 /******************************************************************************/
134 
135 namespace
136 {
138 XrdVERSIONINFODEF(myVer, Xrd, XrdVNUMBER, XrdVERSION);
139 bool SSLmsgs = true;
140 
141 void TlsError(const char *tid, const char *msg, bool sslmsg)
142  {if (!sslmsg || SSLmsgs) XrdGlobal::Log.Emsg("TLS", tid, msg);}
143 };
144 
145 /******************************************************************************/
146 /* S t a t i c M e m b e r s */
147 /******************************************************************************/
148 
149  const char *XrdConfig::TraceID = "Config";
150 
151 /******************************************************************************/
152 /* d e f i n e s */
153 /******************************************************************************/
154 
155 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, Config);
156 
157 #ifndef S_IAMB
158 #define S_IAMB 0x1FF
159 #endif
160 
161 /******************************************************************************/
162 /* L o c a l C l a s s e s */
163 /******************************************************************************/
164 /******************************************************************************/
165 /* X r d C o n f i g P r o t */
166 /******************************************************************************/
167 
169 {
170 public:
171 
173 char *proname;
174 char *libpath;
175 char *parms;
176 
177 int numP;
178 union {int port;
179  int portVec[XrdProtLoad::PortoMax];
180  };
181 union {bool dotls;
182  bool tlsVec[XrdProtLoad::PortoMax];
183  };
184 
185 bool AddPort(int pnum, bool isTLS)
186  {for (int i = 0; i < numP; i++)
187  if (pnum == portVec[i])
188  {tlsVec[i] = isTLS; return true;}
189  if (numP >= (XrdProtLoad::PortoMax)) return false;
190  portVec[numP] = pnum; tlsVec[numP] = isTLS;
191  numP++;
192  return true;
193  }
194 
195 void Reset(char *ln, char *pp, int np=-1, bool to=false)
196  {if (libpath) free(libpath);
197  libpath = ln;
198  if (parms) free(parms);
199  parms = pp;
200  memset(portVec, 0, sizeof(portVec));
201  port = np;
202  memset(tlsVec, 0, sizeof(tlsVec));
203  dotls = to;
204  numP = 1;
205  }
206 
207  XrdConfigProt(char *pn, char *ln, char *pp, int np=-1,
208  bool to=false)
209  : Next(0), proname(pn), libpath(ln), parms(pp), numP(1)
210  {memset(portVec, 0, sizeof(portVec)); port = np;
211  memset(tlsVec, 0, sizeof(tlsVec)); dotls = to;
212  }
213 
215  {free(proname);
216  if (libpath) free(libpath);
217  if (parms) free(parms);
218  }
219 };
220 
221 /******************************************************************************/
222 /* X r d T c p M o n I n f o */
223 /******************************************************************************/
224 
226 {
227 public:
228 
230 
231  XrdTcpMonInfo(const char *drctv, const char *cfn, XrdSysError &errR)
232  : KingPin(drctv, theEnv, errR, &myVer)
233  {theEnv.Put("configFN", cfn);}
234 
236 
238 };
239 
240 /******************************************************************************/
241 /* C o n s t r u c t o r */
242 /******************************************************************************/
243 
245 {
246 
247 // Preset all variables with common defaults
248 //
249  PortTCP = -1;
250  PortUDP = -1;
251  PortTLS = -1;
252  ConfigFN = 0;
253  tmoInfo = 0;
254  myInsName= 0;
255  mySitName= 0;
256  AdminPath= strdup("/tmp");
257  HomePath = 0;
258  PidPath = strdup("/tmp");
259  tlsCert = 0;
260  tlsKey = 0;
261  caDir = 0;
262  caFile = 0;
263  AdminMode= S_IRWXU;
264  HomeMode = S_IRWXU;
265  Police = 0;
266  Net_Opts = XRDNET_KEEPALIVE;
267  TLS_Blen = 0; // Accept OS default (leave Linux autotune in effect)
268  TLS_Opts = XRDNET_KEEPALIVE | XRDNET_USETLS;
269  repDest[0] = 0;
270  repDest[1] = 0;
271  repInt = 600;
272  repOpts = 0;
273  ppNet = 0;
274  tlsOpts = 9ULL | XrdTlsContext::servr | XrdTlsContext::logVF;
275  tlsNoVer = false;
276  tlsNoCAD = true;
277  NetADM = 0;
278  coreV = 1;
279  Specs = 0;
280  isStrict = false;
281  maxFD = 256*1024; // 256K default
282 
283  Firstcp = Lastcp = 0;
284 
285  ProtInfo.eDest = &Log; // Stable -> Error Message/Logging Handler
286  ProtInfo.NetTCP = 0; // Stable -> Network Object
287  ProtInfo.BPool = &BuffPool; // Stable -> Buffer Pool Manager
288  ProtInfo.Sched = &Sched; // Stable -> System Scheduler
289  ProtInfo.ConfigFN= 0; // We will fill this in later
290  ProtInfo.Stats = 0; // We will fill this in later
291  ProtInfo.AdmPath = AdminPath; // Stable -> The admin path
292  ProtInfo.AdmMode = AdminMode; // Stable -> The admin path mode
293  ProtInfo.theEnv = &theEnv; // Additional information
294  ProtInfo.xrdFlags= 0; // Additional information
295 
296  ProtInfo.Format = XrdFORMATB;
297  memset(ProtInfo.rsvd3, 0, sizeof(ProtInfo.rsvd3));
298  ProtInfo.WSize = 0;
299  ProtInfo.ConnMax = -1; // Max connections (fd limit)
300  ProtInfo.readWait = 3*1000; // Wait time for data before we reschedule
301  ProtInfo.idleWait = 0; // Seconds connection may remain idle (0=off)
302  ProtInfo.hailWait =30*1000; // Wait time for data before we drop connection
303  ProtInfo.DebugON = 0; // 1 if started with -d
304  ProtInfo.argc = 0;
305  ProtInfo.argv = 0;
306  ProtInfo.tlsPort = 0;
307  ProtInfo.tlsCtx = 0;
308  ProtInfo.totalCF = &totalCF;
309 
310  XrdNetAddr::SetCache(3*60*60); // Cache address resolutions for 3 hours
311 }
312 
313 /******************************************************************************/
314 /* C o n f i g u r e */
315 /******************************************************************************/
316 
317 int XrdConfig::Configure(int argc, char **argv)
318 {
319 /*
320  Function: Establish configuration at start up time.
321 
322  Input: None.
323 
324  Output: 0 upon success or !0 otherwise.
325 */
326  const char *xrdInst="XRDINSTANCE=";
327 
328  int retc, NoGo = 0, clPort = -1;
329  const char *temp;
330  char c, buff[512], *dfltProt, *libProt = 0;
331  uid_t myUid = 0;
332  gid_t myGid = 0;
333  extern char *optarg;
334  extern int optind, opterr;
335  struct XrdOucLogging::configLogInfo LogInfo;
336  int pipeFD[2] = {-1, -1};
337  const char *pidFN = 0;
338  static const int myMaxc = 80;
339  char **urArgv, *myArgv[myMaxc], argBuff[myMaxc*3+8];
340  char *argbP = argBuff, *argbE = argbP+sizeof(argBuff)-4;
341  char *ifList = 0;
342  int myArgc = 1, urArgc = argc, i;
343  bool noV6, ipV4 = false, ipV6 = false, rootChk = true, optbg = false;
344 
345 // Reconstruct the command line so we can put it in the log
346 //
347  XrdOucString CmdLine(argv[0]);
348  for (int k = 1; k < argc; k++)
349  {CmdLine += ' '; CmdLine += argv[k];}
350 
351 // Obtain the program name we will be using
352 //
353  retc = strlen(argv[0]);
354  while(retc--) if (argv[0][retc] == '/') break;
355  myProg = &argv[0][retc+1];
356 
357 // Setup the initial required protocol. The program name matches the protocol
358 // name but may be arbitrarily suffixed. We need to ignore this suffix. So we
359 // look for it here and it it exists we duplicate argv[0] (yes, loosing some
360 // bytes - sorry valgrind) without the suffix.
361 //
362  {char *p = dfltProt = strdup(myProg);
363  while(*p && (*p == '.' || *p == '-')) p++;
364  if (*p)
365  {char *dot = index(p, '.'), *dash = index(p, '-');
366  if (dot && (dot < dash || !dash)) p = dot;
367  else if (dash) p = dash;
368  else p = 0;
369  if (p) *p = '\0';
370  if (!strcmp("xrootd", dfltProt)) dfltProt[5] = 0;
371  else if (!strcmp("cmsd", dfltProt)) dfltProt[3] = 0;
372  }
373  }
374  myArgv[0] = argv[0];
375 
376 // Prescan the argument list to see if there is a passthrough option. In any
377 // case, we will set the ephemeral argv/arg in the environment.
378 //
379  i = 1;
380  while(i < argc)
381  {if (*(argv[i]) == '-' && *(argv[i]+1) == '+')
382  {int n = strlen(argv[i]+2), j = i+1, k = 1;
383  if (urArgc == argc) urArgc = i;
384  if (n) memcpy(buff, argv[i]+2, (n > 256 ? 256 : n));
385  strcpy(&(buff[n]), ".argv**");
386  while(j < argc && (*(argv[j]) != '-' || *(argv[j]+1) != '+')) j++;
387  urArgv = new char*[j-i+1];
388  urArgv[0] = argv[0];
389  i++;
390  while(i < j) urArgv[k++] = argv[i++];
391  urArgv[k] = 0;
392  theEnv.PutPtr(buff, urArgv);
393  strcpy(&(buff[n]), ".argc");
394  theEnv.PutInt(buff, static_cast<long>(k));
395  } else i++;
396  }
397  theEnv.PutPtr("argv[0]", argv[0]);
398 
399 // Process the options. Note that we cannot passthrough long options or
400 // options that take arguments because getopt permutes the arguments.
401 //
402  opterr = 0;
403  if (argc > 1 && '-' == *argv[1])
404  while ((c = getopt(urArgc,argv,":a:A:bc:dhHI:k:l:L:n:p:P:R:s:S:vw:W:z"))
405  && ((unsigned char)c != 0xff))
406  { switch(c)
407  {
408  case 'a': if (AdminPath) free(AdminPath);
409  AdminPath = strdup(optarg);
410  AdminMode = ProtInfo.AdmMode = S_IRWXU;
411  ProtInfo.xrdFlags |= XrdProtocol_Config::admPSet;
412  break;
413  case 'A': if (AdminPath) free(AdminPath);
414  AdminPath = strdup(optarg);
415  AdminMode = ProtInfo.AdmMode = S_IRWXU | S_IRWXG;
416  ProtInfo.xrdFlags |= XrdProtocol_Config::admPSet;
417  break;
418  case 'b': optbg = true;
419  break;
420  case 'c': if (ConfigFN) free(ConfigFN);
421  ConfigFN = strdup(optarg);
422  break;
423  case 'd': XrdTrace.What |= TRACE_ALL;
424  ProtInfo.DebugON = 1;
425  XrdOucEnv::Export("XRDDEBUG", "1");
426  break;
427  case 'h': Usage(0);
428  break;
429  case 'H': Usage(-1);
430  break;
431  case 'I': if (!strcmp("v4", optarg)) {ipV4 = true; ipV6 = false;}
432  else if (!strcmp("v6", optarg)) {ipV4 = false; ipV6 = true;}
433  else {Log.Emsg("Config", "Invalid -I argument -",optarg);
434  Usage(1);
435  }
436  break;
437  case 'k': if (!(LogInfo.keepV = Log.logger()->ParseKeep(optarg)))
438  {Log.Emsg("Config","Invalid -k argument -",optarg);
439  Usage(1);
440  }
441  break;
442  case 'l': LogInfo.logArg = optarg;
443  break;
444  case 'L': if (!*optarg)
445  {Log.Emsg("Config", "Protocol library path not specified.");
446  Usage(1);
447  }
448  if (libProt) free(libProt);
449  libProt = strdup(optarg);
450  break;
451  case 'n': myInsName = (!strcmp(optarg,"anon")||!strcmp(optarg,"default")
452  ? 0 : optarg);
453  break;
454  case 'p': if ((clPort = XrdOuca2x::a2p(Log,"tcp",optarg)) < 0) Usage(1);
455  break;
456  case 'P': if (dfltProt) free(dfltProt);
457  dfltProt = strdup(optarg);
458  break;
459  case 'R': if (!(getUG(optarg, myUid, myGid))) Usage(1);
460  rootChk = false;
461  break;
462  case 's': pidFN = optarg;
463  break;
464  case 'S': mySitName = optarg;
465  break;
466  case ':': buff[0] = '-'; buff[1] = optopt; buff[2] = 0;
467  Log.Emsg("Config", buff, "parameter not specified.");
468  Usage(1);
469  break;
470  case 'v': std::cerr <<XrdVSTRING <<std::endl;
471  _exit(0);
472  break;
473  case 'w': if (HomePath) free(HomePath);
474  HomePath = strdup(optarg);
475  HomeMode = S_IRWXU;
476  Specs |= hpSpec;
477  break;
478  case 'W': if (HomePath) free(HomePath);
479  HomePath = strdup(optarg);
480  HomeMode = S_IRWXU | S_IRGRP | S_IXGRP;
481  Specs |= hpSpec;
482  break;
483  case 'z': LogInfo.hiRes = true;
484  break;
485 
486  default: if (optopt == '-' && *(argv[optind]+1) == '-')
487  {Log.Emsg("Config", "Long options are not supported.");
488  Usage(1);
489  }
490  if (myArgc >= myMaxc || argbP >= argbE)
491  {Log.Emsg("Config", "Too many command line arguments.");
492  Usage(1);
493  }
494  myArgv[myArgc++] = argbP;
495  *argbP++ = '-'; *argbP++ = optopt; *argbP++ = 0;
496  break;
497  }
498  }
499 
500 // If an adminpath specified, make sure it's absolute
501 //
502  if ((ProtInfo.xrdFlags & XrdProtocol_Config::admPSet) && *AdminPath != '/')
503  {Log.Emsg("Config", "Command line adminpath is not absolute.");
504  exit(17);
505  }
506 
507 // If an homepath specified, make sure it's absolute
508 //
509  if (HomePath && *HomePath != '/')
510  {Log.Emsg("Config", "Command line home path is not absolute.");
511  exit(17);
512  }
513 
514 // If the configuration file is relative to where we are, get the absolute
515 // path as we may be changing the home path. This also starts capturing.
516 //
517  if (ConfigFN) setCFG(true);
518 
519 // The first thing we must do is to set the correct networking mode
520 //
521  noV6 = XrdNetAddr::IPV4Set();
522  if (ipV4) XrdNetAddr::SetIPV4();
523  else if (ipV6){if (noV6) Log.Say("Config warning: ipV6 appears to be broken;"
524  " forced ipV6 mode not advised!");
526  }
527  else if (noV6) Log.Say("Config warning: ipV6 is misconfigured or "
528  "unavailable; reverting to ipV4.");
529 
530 // Set the site name if we have one
531 //
532  if (mySitName) mySitName = XrdOucSiteName::Set(mySitName, 63);
533 
534 // Drop into non-privileged state if so requested
535 //
536  if (myGid && setegid(myGid))
537  {Log.Emsg("Config", errno, "set effective gid"); exit(17);}
538  if (myUid && seteuid(myUid))
539  {Log.Emsg("Config", errno, "set effective uid"); exit(17);}
540 
541 // Prohibit this program from executing as superuser unless -R was specified.
542 //
543  if (rootChk && geteuid() == 0)
544  {Log.Emsg("Config", "Security reasons prohibit running as "
545  "superuser; program is terminating.");
546  _exit(8);
547  }
548 
549 // Pass over any parameters
550 //
551  if (urArgc-optind+2 >= myMaxc)
552  {Log.Emsg("Config", "Too many command line arguments.");
553  Usage(1);
554  }
555  for ( ; optind < urArgc; optind++) myArgv[myArgc++] = argv[optind];
556 
557 // Record the actual arguments that we will pass on
558 //
559  myArgv[myArgc] = 0;
560  ProtInfo.argc = myArgc;
561  ProtInfo.argv = myArgv;
562 
563 // Resolve background/foreground issues
564 //
565  if (optbg)
566  {
567 #ifdef WIN32
568  XrdOucUtils::Undercover(&Log, !LogInfo.logArg);
569 #else
570  if (pipe( pipeFD ) == -1)
571  {Log.Emsg("Config", errno, "create a pipe"); exit(17);}
572  XrdOucUtils::Undercover(Log, !LogInfo.logArg, pipeFD);
573 #endif
574  }
575 
576 // Get the full host name. We must define myIPAddr here because we may need to
577 // run in v4 mode and that doesn't get set until after the options are scanned.
578 //
579  static XrdNetAddr *myIPAddr = new XrdNetAddr((int)0);
580  auto envName = getenv("XRDHOST");
581  const char *ipAddrName;
582  if (envName) {
583  myName = envName;
584  XrdOucEnv::Export("OVERRIDEXRDHOST", myName.c_str());
585  } else if ((ipAddrName = myIPAddr->Name(0, &temp))) {
586  myName = ipAddrName;
587  } else {
588  myName = "";
589  }
590 
591 // Get our IP address and FQN
592 //
593  ProtInfo.myName = myName.c_str();
594  ProtInfo.myAddr = myIPAddr->SockAddr();
595  ProtInfo.myInst = XrdOucUtils::InstName(myInsName);
596  ProtInfo.myProg = myProg;
597 
598 // Set the Environmental variable to hold the instance name
599 // XRDINSTANCE=<pgm> <instance name>@<host name>
600 // XrdOucEnv::Export("XRDINSTANCE")
601 //
602  sprintf(buff,"%s%s %s@%s", xrdInst, myProg, ProtInfo.myInst, myName.c_str());
603  myInstance = strdup(buff);
604  putenv(myInstance); // XrdOucEnv::Export("XRDINSTANCE",...)
605  myInstance += strlen(xrdInst);
606  XrdOucEnv::Export("XRDHOST", myName.c_str());
607  XrdOucEnv::Export("XRDNAME", ProtInfo.myInst);
608  XrdOucEnv::Export("XRDPROG", myProg);
609 
610 // Bind the log file if we have one
611 //
612  if (LogInfo.logArg)
613  {LogInfo.xrdEnv = &theEnv;
614  LogInfo.iName = myInsName;
615  LogInfo.cfgFn = ConfigFN;
616  if (!XrdOucLogging::configLog(Log, LogInfo)) _exit(16);
617  Log.logger()->AddMsg(CmdLine.c_str());
619  }
620 
621 // We now test for host name. In theory, we should always get some kind of name.
622 // We can't really continue without some kind of name at this point. Note that
623 // vriable temp should still be valid from the previous NetAddr call.
624 //
625  if (myName.empty())
626  {Log.Emsg("Config", "Unable to determine host name; ",
627  (temp ? temp : "reason unknown"),
628  "; execution terminated.");
629  _exit(16);
630  }
631 
632 // Tell NetIF what logger to use as it's been properly setup by now.
633 //
635 
636 // Put out the herald
637 //
638  strcpy(buff, "Starting on ");
639  retc = strlen(buff);
640  XrdSysUtils::FmtUname(buff+retc, sizeof(buff)-retc);
641  Log.Say(0, buff);
642  Log.Say(0, CmdLine.c_str());
643  Log.Say(XrdBANNER);
644 
645 // Verify that we have a real name. We've had problems with people setting up
646 // bad /etc/hosts files that can cause connection failures if "allow" is used.
647 // Otherwise, determine our domain name.
648 //
649  if (!myIPAddr->isRegistered())
650  {Log.Emsg("Config",myName.c_str(),"does not appear to be registered in the DNS.");
651  Log.Emsg("Config","Verify that the '/etc/hosts' file is correct and "
652  "this machine is registered in DNS.");
653  Log.Emsg("Config", "Execution continues but connection failures may occur.");
654  myDomain = 0;
655  } else if (!(myDomain = index(myName.c_str(), '.')))
656  Log.Say("Config warning: this hostname, ", myName.c_str(),
657  ", is registered without a domain qualification.");
658 
659 // Setup the initial required protocol.
660 //
661  Firstcp = Lastcp = new XrdConfigProt(strdup(dfltProt), libProt, 0);
662 
663 // Let start it up!
664 //
665  Log.Say("++++++ ", myInstance, " initialization started.");
666 
667 // Allocate /dev/null as we need it and can't live without it
668 //
669  devNull = XrdSysFD_Open("/dev/null", O_RDONLY);
670  if (devNull < 0)
671  {Log.Emsg("Config", errno, "open '/dev/null' which is required!");
672  NoGo = 1;
673  }
674 
675 // Process the configuration file, if one is present
676 //
677  if (ConfigFN)
678  {Log.Say("Config using configuration file ", ConfigFN);
679  ProtInfo.ConfigFN = ConfigFN;
680  NoGo = ConfigProc();
681  }
682  if (clPort >= 0) PortTCP = clPort;
683  if (ProtInfo.DebugON)
686  }
687 
688 // Setup the admin path now
689 //
690  NoGo |= SetupAPath();
691 
692 // If tls enabled, set it up. We skip this if we failed to avoid confusing msgs
693 //
694  if (!NoGo)
695  {if (!tlsCert) ProtInfo.tlsCtx= 0;
696  else {Log.Say("++++++ ", myInstance, " TLS initialization started.");
697  if (SetupTLS())
698  {Log.Say("------ ",myInstance," TLS initialization ended.");
699  if ((ProtInfo.tlsCtx = XrdGlobal::tlsCtx))
700  theEnv.PutPtr("XrdTlsContext*", XrdGlobal::tlsCtx);
701  } else {
702  NoGo = 1;
703  Log.Say("------ ",myInstance," TLS initialization failed.");
704  }
705  }
706  }
707 
708 // If there is TLS port verify that it can be used. We ignore this if we
709 // will fail anyway so as to not issue confusing messages.
710 //
711  if (!NoGo)
712  {if (PortTLS > 0 && !XrdGlobal::tlsCtx)
713  {Log.Say("Config TLS port specification ignored; TLS not configured!");
714  PortTLS = -1;
715  } else {
716  ProtInfo.tlsCtx = XrdGlobal::tlsCtx;
717  ProtInfo.tlsPort = (PortTLS > 0 ? PortTLS : 0);
718  }
719  }
720 
721 // Put largest buffer size in the env
722 //
723  theEnv.PutInt("MaxBuffSize", XrdGlobal::xlBuff.MaxSize());
724 
725 // Export the network interface list at this point
726 //
727  if (ppNet && XrdNetIF::GetIF(ifList, 0, true))
728  XrdOucEnv::Export("XRDIFADDRS",ifList);
729 
730 // Configure network routing
731 //
732  if (!XrdInet::netIF.SetIF(myIPAddr, ifList))
733  {Log.Emsg("Config", "Unable to determine interface addresses!");
734  NoGo = 1;
735  }
736 
737 // If we have an instance name change the working directory
738 //
739  if ((myInsName || HomePath)
740  && !XrdOucUtils::makeHome(Log, myInsName, HomePath, HomeMode)) NoGo = 1;
741 
742 // Create the pid file
743 //
744  if (!PidFile(pidFN, optbg)) NoGo = 1;
745 
746 // Establish a manifest file for auto-collection
747 //
748  if (!NoGo) Manifest(pidFN);
749 
750 // Now initialize the protocols and other stuff
751 //
752  if (!NoGo) NoGo = Setup(dfltProt, libProt);
753 
754 // End config capture
755 //
756  setCFG(false);
757 
758 // If we have a tcpmon plug-in try loading it now. We won't do that unless
759 // tcp monitoring was enabled by the monitoring framework.
760 //
761  if (tmoInfo && !NoGo)
762  {void *theGS = theEnv.GetPtr("TcpMon.gStream*");
763  if (!theGS) Log.Say("Config warning: TCP monitoring not enabled; "
764  "tcpmonlib plugin not loaded!");
765  else {tmoInfo->theEnv.PutPtr("TcpMon.gStream*", theGS);
766  TcpMonPin = tmoInfo->KingPin.Load("TcpMonPin");
767  if (!TcpMonPin) NoGo = 1;
768  }
769  }
770 
771  // if we call this it means that the daemon has forked and we are
772  // in the child process
773 #ifndef WIN32
774  if (optbg)
775  {
776  int status = NoGo ? 1 : 0;
777  if(write( pipeFD[1], &status, sizeof( status ) )) {};
778  close( pipeFD[1]);
779  }
780 #endif
781 
782 // All done, close the stream and return the return code.
783 //
784  temp = (NoGo ? " initialization failed." : " initialization completed.");
785  sprintf(buff, "%s:%d", myInstance, PortTCP);
786  Log.Say("------ ", buff, temp);
787  if (LogInfo.logArg)
788  {strcat(buff, " running ");
789  retc = strlen(buff);
790  XrdSysUtils::FmtUname(buff+retc, sizeof(buff)-retc);
791  Log.logger()->AddMsg(buff);
792  }
793  return NoGo;
794 }
795 
796 /******************************************************************************/
797 /* C o n f i g X e q */
798 /******************************************************************************/
799 
801 {
802  int dynamic;
803 
804  // Determine whether is is dynamic or not
805  //
806  if (eDest) dynamic = 1;
807  else {dynamic = 0; eDest = &Log;}
808 
809  // Process common items
810  //
811  TS_Xeq("buffers", xbuf);
812  TS_Xeq("network", xnet);
813  TS_Xeq("sched", xsched);
814  TS_Xeq("trace", xtrace);
815 
816  // Process items that can only be processed once
817  //
818  if (!dynamic)
819  {
820  TS_Xeq("adminpath", xapath);
821  TS_Xeq("allow", xallow);
822  TS_Xeq("homepath", xhpath);
823  TS_Xeq("maxfd", xmaxfd);
824  TS_Xeq("pidpath", xpidf);
825  TS_Xeq("port", xport);
826  TS_Xeq("protocol", xprot);
827  TS_Xeq("report", xrep);
828  TS_Xeq("sitename", xsit);
829  TS_Xeq("tcpmonlib", xtcpmon);
830  TS_Xeq("timeout", xtmo);
831  TS_Xeq("tls", xtls);
832  TS_Xeq("tlsca", xtlsca);
833  TS_Xeq("tlsciphers", xtlsci);
834  }
835 
836  // No match found, complain.
837  //
838  eDest->Say("Config warning: ignoring unknown xrd directive '",var,"'.");
839  Config.Echo();
840  return 0;
841 }
842 
843 /******************************************************************************/
844 /* P r i v a t e F u n c t i o n s */
845 /******************************************************************************/
846 /******************************************************************************/
847 /* A S o c k e t */
848 /******************************************************************************/
849 
850 int XrdConfig::ASocket(const char *path, const char *fname, mode_t mode)
851 {
852  struct sockaddr_un unixvar;
853  int plen = strlen(path), flen = strlen(fname);
854 
855 // Make sure we can fit everything in our buffer
856 //
857  if ((plen + flen + 3) > (int)sizeof(unixvar.sun_path))
858  {Log.Emsg("Config", "admin path", path, "too long");
859  return 1;
860  }
861 
862 // *!*!* At this point we do not yet support the admin path for xrd.
863 // sp we comment out all of the following code.
864 
865 /*
866 // Construct the actual socket name
867 //
868  char sokpath[sizeof(Unix.sun_path)];
869 
870  if (sokpath[plen-1] != '/') sokpath[plen++] = '/';
871  strcpy(&sokpath[plen], fname);
872 
873 // Create an admin network
874 //
875  NetADM = new XrdInet(&Log);
876  if (myDomain) NetADM->setDomain(myDomain);
877 
878 // Bind the netwok to the named socket
879 //
880  if (!NetADM->Bind(sokpath)) return 1;
881 
882 // Set the mode and return
883 //
884  chmod(sokpath, mode); // This may fail on some platforms
885 */
886  return 0;
887 }
888 
889 /******************************************************************************/
890 /* C o n f i g P r o c */
891 /******************************************************************************/
892 
893 int XrdConfig::ConfigProc()
894 {
895  char *var;
896  int cfgFD, retc, NoGo = 0;
897  XrdOucEnv myEnv;
898  XrdOucStream Config(&Log, myInstance, &myEnv, "=====> ");
899 
900 // Try to open the configuration file.
901 //
902  if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
903  {Log.Emsg("Config", errno, "open config file", ConfigFN);
904  return 1;
905  }
906  Config.Attach(cfgFD);
907 
908 // Now start reading records until eof.
909 //
910  while((var = Config.GetMyFirstWord()))
911  if (!strncmp(var, "xrd.", 4)
912  || !strcmp (var, "all.adminpath")
913  || !strcmp (var, "all.pidpath")
914  || !strcmp (var, "all.sitename" ))
915  if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
916 
917 // Now check if any errors occurred during file i/o
918 //
919  if ((retc = Config.LastError()))
920  NoGo = Log.Emsg("Config", retc, "read config file", ConfigFN);
921  Config.Close();
922 
923 // Return final return code
924 //
925  return NoGo;
926 }
927 
928 /******************************************************************************/
929 /* g e t N e t */
930 /******************************************************************************/
931 
932 XrdInet *XrdConfig::getNet(int port, bool isTLS)
933 {
934  int the_Opts, the_Blen;
935 
936 // Try to find an existing network for this port
937 //
938  for (int i = 0; i < (int)NetTCP.size(); i++)
939  if (port == NetTCP[i]->Port()) return NetTCP[i];
940 
941 // Create a new network for this port
942 //
943  XrdInet *newNet = new XrdInet(&Log, Police);
944  NetTCP.push_back(newNet);
945 
946 // Set options
947 //
948  if (isTLS)
949  {the_Opts = TLS_Opts; the_Blen = TLS_Blen;
950  } else {
951  the_Opts = Net_Opts; the_Blen = Net_Blen;
952  }
953  if (the_Opts || the_Blen) newNet->setDefaults(the_Opts, the_Blen);
954 
955 // Set the domain if we have one
956 //
957  if (myDomain) newNet->setDomain(myDomain);
958 
959 // Attempt to bind to this socket.
960 //
961  if (newNet->BindSD(port, "tcp") == 0) return newNet;
962  delete newNet;
963  return 0;
964 }
965 
966 /******************************************************************************/
967 /* g e t U G */
968 /******************************************************************************/
969 
970 int XrdConfig::getUG(char *parm, uid_t &newUid, gid_t &newGid)
971 {
972  struct passwd *pp;
973 
974 // Get the userid entry
975 //
976  if (!(*parm))
977  {Log.Emsg("Config", "-R user not specified."); return 0;}
978 
979  if (isdigit(*parm))
980  {if (!(newUid = atol(parm)))
981  {Log.Emsg("Config", "-R", parm, "is invalid"); return 0;}
982  pp = getpwuid(newUid);
983  }
984  else pp = getpwnam(parm);
985 
986 // Make sure it is valid and acceptable
987 //
988  if (!pp)
989  {Log.Emsg("Config", errno, "retrieve -R user password entry");
990  return 0;
991  }
992  if (!(newUid = pp->pw_uid))
993  {Log.Emsg("Config", "-R", parm, "is still unacceptably a superuser!");
994  return 0;
995  }
996  newGid = pp->pw_gid;
997  return 1;
998 }
999 
1000 /******************************************************************************/
1001 /* M a n i f e s t */
1002 /******************************************************************************/
1003 
1004 void XrdConfig::Manifest(const char *pidfn)
1005 {
1006  const char *Slash;
1007  char envBuff[8192], pwdBuff[2048], manBuff[1024], *pidP, *sP, *xP;
1008  int envFD, envLen;
1009 
1010 // Get the current working directory
1011 //
1012  if (!getcwd(pwdBuff, sizeof(pwdBuff)))
1013  {Log.Emsg("Config", "Unable to get current working directory!");
1014  return;
1015  }
1016 
1017 // The above is the authoratative home directory, so recorded here.
1018 //
1019  if (HomePath) free(HomePath);
1020  HomePath = strdup(pwdBuff);
1021 
1022 // Prepare for symlinks
1023 //
1024  strcpy(envBuff, ProtInfo.AdmPath);
1025  envLen = strlen(envBuff);
1026  if (envBuff[envLen-1] != '/') {envBuff[envLen] = '/'; envLen++;}
1027  strcpy(envBuff+envLen, ".xrd/");
1028  xP = envBuff+envLen+5;
1029 
1030 // Create a symlink to the configuration file
1031 //
1032  if ((sP = getenv("XRDCONFIGFN")))
1033  {sprintf(xP, "=/conf/%s.cf", myProg);
1034  XrdOucUtils::ReLink(envBuff, sP);
1035  }
1036 
1037 // Create a symlink to where core files will be found
1038 //
1039  sprintf(xP, "=/core/%s", myProg);
1040  XrdOucUtils::ReLink(envBuff, pwdBuff);
1041 
1042 // Create a symlink to where log files will be found
1043 //
1044  if ((sP = getenv("XRDLOGDIR")))
1045  {sprintf(xP, "=/logs/%s", myProg);
1046  XrdOucUtils::ReLink(envBuff, sP);
1047  }
1048 
1049 // Create a symlink to out proc information (Linux only)
1050 //
1051 #ifdef __linux__
1052  sprintf(xP, "=/proc/%s", myProg);
1053  sprintf(manBuff, "/proc/%d", getpid());
1054  XrdOucUtils::ReLink(envBuff, manBuff);
1055 #endif
1056 
1057 // Create environment string
1058 //
1059  envLen = snprintf(envBuff, sizeof(envBuff), "pid=%d&host=%s&inst=%s&ver=%s"
1060  "&home=%s&cfgfn=%s&cwd=%s&apath=%s&logfn=%s",
1061  static_cast<int>(getpid()), ProtInfo.myName,
1062  ProtInfo.myInst, XrdVSTRING, HomePath,
1063  (getenv("XRDCONFIGFN") ? getenv("XRDCONFIGFN") : ""),
1064  pwdBuff, ProtInfo.AdmPath, Log.logger()->xlogFN());
1065 
1066 // Find out where we should write this
1067 //
1068  if (pidfn && (Slash = rindex(pidfn, '/')))
1069  {strncpy(manBuff, pidfn, Slash-pidfn); pidP = manBuff+(Slash-pidfn);}
1070  else {strcpy(manBuff, ProtInfo.AdmPath); pidP = manBuff+strlen(ProtInfo.AdmPath);}
1071 
1072 // Construct the pid file name for ourselves
1073 //
1074  snprintf(pidP, sizeof(manBuff)-(pidP-manBuff), "/%s.%s.env",
1075  ProtInfo.myProg, ProtInfo.myInst);
1076  theEnv.Put("envFile", manBuff);
1077 
1078 // Open the file
1079 //
1080  if ((envFD = open(manBuff, O_WRONLY|O_CREAT|O_TRUNC, 0664)) < 0)
1081  {Log.Emsg("Config", errno, "create envfile", manBuff);
1082  return;
1083  }
1084 
1085 // Write out environmental information
1086 //
1087  if (write(envFD, envBuff, envLen) < 0)
1088  Log.Emsg("Config", errno, "write to envfile", manBuff);
1089  close(envFD);
1090 }
1091 
1092 /******************************************************************************/
1093 /* P i d F i l e */
1094 /******************************************************************************/
1095 
1096 bool XrdConfig::PidFile(const char *clpFN, bool optbg)
1097 {
1098  int rc, xfd;
1099  char *ppath, buff[32], pidFN[1200];
1100  const char *xop = 0;
1101 
1102 // If a command line pidfn was specified, we must successfully write it
1103 // if we are in background mode. Otherwise, we simply continue.
1104 //
1105  if (clpFN && !XrdOucUtils::PidFile(Log, clpFN) && optbg) return false;
1106 
1107 // Generate the old-style pidpath we will use
1108 //
1109  ppath=XrdOucUtils::genPath(PidPath,XrdOucUtils::InstName(-1));
1110 
1111 // Create the path if it does not exist and write out the pid
1112 //
1113  if ((rc = XrdOucUtils::makePath(ppath,XrdOucUtils::pathMode)))
1114  {xop = "create"; snprintf(pidFN, sizeof(pidFN), "%s", ppath); errno = rc;}
1115  else {snprintf(pidFN, sizeof(pidFN), "%s/%s.pid", ppath, myProg);
1116 
1117  if ((xfd = open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
1118  xop = "open";
1119  else {if (write(xfd,buff,snprintf(buff,sizeof(buff),"%d",
1120  static_cast<int>(getpid()))) < 0) xop = "write";
1121  close(xfd);
1122  }
1123  }
1124 
1125 // All done
1126 //
1127  free(ppath);
1128  if (xop) Log.Emsg("Config", errno, xop, pidFN);
1129  return true;
1130 }
1131 
1132 /******************************************************************************/
1133 /* s e t C F G */
1134 /******************************************************************************/
1135 
1136 void XrdConfig::setCFG(bool start)
1137 {
1138 
1139 // If there is no config file there is nothing to do
1140 //
1141  if (!ConfigFN || !(*ConfigFN))
1142  {if (ConfigFN)
1143  {free(ConfigFN);
1144  ConfigFN = 0;
1145  }
1146  return;
1147  }
1148 
1149 // If ending, post process the config capture
1150 //
1151  if (!start)
1153  if (totalCF.length())
1154  {char *temp = (char *)malloc(totalCF.length()+1);
1155  strcpy(temp, totalCF.c_str());
1156  totalCF.resize();
1157  totalCF = temp;
1158  free(temp);
1159  }
1160  return;
1161  }
1162 
1163 // Prefix current working directory to the config file if not absolute
1164 //
1165  if (*ConfigFN != '/')
1166  {char cwdBuff[1024];
1167  if (getcwd(cwdBuff,sizeof(cwdBuff)-strlen(ConfigFN)-2))
1168  {int n = strlen(cwdBuff);
1169  if (cwdBuff[n-1] != '/') cwdBuff[n++] = '/';
1170  strcpy(cwdBuff+n, ConfigFN);
1171  free(ConfigFN);
1172  ConfigFN = strdup(cwdBuff);
1173  }
1174  }
1175 
1176 // Export result
1177 //
1178  XrdOucEnv::Export("XRDCONFIGFN", ConfigFN);
1179 
1180 // Setup capturing for the XrdOucStream that will be used by all others to
1181 // process config files.
1182 //
1184  totalCF.resize(1024*1024);
1185  const char *cvec[] = { "*** ", myProg, " config from '", ConfigFN, "':", 0 };
1186  XrdOucStream::Capture(cvec);
1187 }
1188 
1189 /******************************************************************************/
1190 /* s e t F D L */
1191 /******************************************************************************/
1192 
1193 int XrdConfig::setFDL()
1194 {
1195  struct rlimit rlim;
1196  char buff[100];
1197 
1198 // Get the resource limit
1199 //
1200  if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1201  return Log.Emsg("Config", errno, "get FD limit");
1202 
1203 // Set the limit to the maximum allowed
1204 //
1205  if (rlim.rlim_max == RLIM_INFINITY || (isStrict && rlim.rlim_max > maxFD))
1206  rlim.rlim_cur = maxFD;
1207  else rlim.rlim_cur = rlim.rlim_max;
1208 #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5))
1209  if (rlim.rlim_cur > OPEN_MAX) rlim.rlim_max = rlim.rlim_cur = OPEN_MAX;
1210 #endif
1211 #if defined(__linux__)
1212 // Setting a limit beyond this value on Linux is guaranteed to fail during epoll_wait()
1213  unsigned int epoll_max_fd = (INT_MAX / sizeof(struct epoll_event));
1214  if (rlim.rlim_cur > (rlim_t)epoll_max_fd) rlim.rlim_max = rlim.rlim_cur = epoll_max_fd;
1215 #endif
1216  if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
1217  return Log.Emsg("Config", errno,"set FD limit");
1218 
1219 // Obtain the actual limit now
1220 //
1221  if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
1222  return Log.Emsg("Config", errno, "get FD limit");
1223 
1224 // Establish operating limit
1225 //
1226  ProtInfo.ConnMax = rlim.rlim_cur;
1227  sprintf(buff, "%d", ProtInfo.ConnMax);
1228  Log.Say("Config maximum number of connections restricted to ", buff);
1229 
1230 // Set core limit and but Solaris
1231 //
1232 #if !defined( __solaris__ ) && defined(RLIMIT_CORE)
1233  if (coreV >= 0)
1234  {if (getrlimit(RLIMIT_CORE, &rlim) < 0)
1235  Log.Emsg("Config", errno, "get core limit");
1236  else {rlim.rlim_cur = (coreV ? rlim.rlim_max : 0);
1237  if (setrlimit(RLIMIT_CORE, &rlim) < 0)
1238  Log.Emsg("Config", errno,"set core limit");
1239  }
1240  }
1241 #endif
1242 
1243 // The scheduler will have already set the thread limit. We just report it
1244 //
1245 #if ( defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) ) && defined(RLIMIT_NPROC)
1246 
1247 // Obtain the actual limit now (Scheduler construction sets this to rlim_max)
1248 //
1249  if (getrlimit(RLIMIT_NPROC, &rlim) < 0)
1250  return Log.Emsg("Config", errno, "get thread limit");
1251 
1252 // Establish operating limit
1253 //
1254  int nthr = static_cast<int>(rlim.rlim_cur);
1255  if (nthr < 8192 || ProtInfo.DebugON)
1256  {sprintf(buff, "%d", static_cast<int>(rlim.rlim_cur));
1257  Log.Say("Config maximum number of threads restricted to ", buff);
1258  }
1259 #endif
1260 
1261  return 0;
1262 }
1263 
1264 /******************************************************************************/
1265 /* S e t u p */
1266 /******************************************************************************/
1267 
1268 int XrdConfig::Setup(char *dfltp, char *libProt)
1269 {
1270  XrdConfigProt *cp;
1271  int xport, protNum = 0;
1272 
1273 // Establish the FD limit
1274 //
1275  if (setFDL()) return 1;
1276 
1277 // Special handling for Linux sendfile()
1278 //
1279 #if ( defined(__linux__) || defined(__GNU__) ) && defined(TCP_CORK)
1280 { int sokFD, setON = 1;
1281  if ((sokFD = socket(PF_INET, SOCK_STREAM, 0)) >= 0)
1282  {setsockopt(sokFD, XrdNetUtils::ProtoID("tcp"), TCP_NODELAY,
1283  &setON, sizeof(setON));
1284  if (setsockopt(sokFD, SOL_TCP, TCP_CORK, &setON, sizeof(setON)) < 0)
1285  XrdLink::sfOK = 0;
1286  close(sokFD);
1287  }
1288 }
1289 #endif
1290 
1291 // Indicate how sendfile is being handled
1292 //
1293  TRACE(NET,"sendfile " <<(XrdLink::sfOK ? "enabled." : "disabled!"));
1294 
1295 // Initialize the buffer manager
1296 //
1297  BuffPool.Init();
1298 
1299 // Start the scheduler
1300 //
1301  Sched.Start();
1302 
1303 // Setup the link and socket polling infrastructure
1304 //
1305  if (!XrdLinkCtl::Setup(ProtInfo.ConnMax, ProtInfo.idleWait)
1306  || !XrdPoll::Setup(ProtInfo.ConnMax)) return 1;
1307 
1308 // Determine the default port number (only for xrootd) if not specified.
1309 //
1310  if (PortTCP < 0)
1311  {if ((PortTCP = XrdNetUtils::ServPort(dfltp))) PortUDP = PortTCP;
1312  else PortTCP = -1;
1313  }
1314 
1315 // We now go through all of the protocols and get each respective port number.
1316 //
1317  cp = Firstcp;
1318  while(cp)
1319  {if (!tlsCtx)
1320  for (int i = 0; i < cp->numP; i++)
1321  {if (cp->tlsVec[i])
1322  {Log.Emsg("Config", "protocol", cp->proname,
1323  "configured with a TLS-only port "
1324  "but TLS is not configured!");
1325  return 1;
1326  }
1327  }
1328  xport = (cp->dotls ? PortTLS : PortTCP);
1329  ProtInfo.Port = (cp->port < 0 ? xport : cp->port);
1330  XrdOucEnv::Export("XRDPORT", ProtInfo.Port);
1331  cp->port = XrdProtLoad::Port(cp->libpath,cp->proname,cp->parms,&ProtInfo);
1332  if (cp->port < 0) return 1;
1333  for (int i = 1; i < cp->numP; i++)
1334  if (cp->port == cp->portVec[i]) cp->portVec[i] = -1;
1335  cp = cp->Next;
1336  }
1337 
1338 // Allocate the statistics object. This is akward since we only know part
1339 // of the current configuration. The object will figure this out later.
1340 //
1341  ProtInfo.Stats = new XrdStats(&Log, &Sched, &BuffPool,
1342  ProtInfo.myName, Firstcp->port,
1343  ProtInfo.myInst, ProtInfo.myProg, mySitName);
1344 
1345 // If the base protocol is xroot, then save the base port number so we can
1346 // extend the port to the http protocol should it have been loaded. That way
1347 // redirects via xroot will also work for http.
1348 //
1349  xport = (strcmp("xroot", Firstcp->proname) ? 0 : Firstcp->port);
1350 
1351 // Load the protocols. For each new protocol port number, create a new
1352 // network object to handle the port dependent communications part. All
1353 // port issues will have been resolved at this point. Note that we need
1354 // to set default network object from the first protocol before loading
1355 // any protocol in case one of them starts using the default network.
1356 //
1357  XrdInet *arbNet = 0, *theNet;
1358  while((cp = Firstcp))
1359  {for (int i = 0; i < cp->numP; i++)
1360  {if (cp->portVec[i] < 0) continue;
1361  if (!(cp->portVec[i]) && arbNet) theNet = arbNet;
1362  else {theNet = getNet(cp->portVec[i], cp->tlsVec[i]);
1363  if (!theNet) return 1;
1364  if (!(cp->portVec[i])) arbNet = theNet;
1365  }
1366  if (i == 0) XrdNetTCP = theNet; // Avoid race condition!!!
1367  ProtInfo.Port = theNet->Port();
1368  ProtInfo.NetTCP = theNet;
1369  ProtInfo.WSize = theNet->WSize();
1370  TRACE(NET, cp->proname <<':' <<ProtInfo.Port <<" wsz="
1371  <<ProtInfo.WSize);
1372 
1373  if (i) XrdProtLoad::Port(protNum, ProtInfo.Port, cp->tlsVec[i]);
1374  else {XrdOucEnv::Export("XRDPORT", ProtInfo.Port);
1375  protNum = XrdProtLoad::Load(cp->libpath, cp->proname,
1376  cp->parms, &ProtInfo,
1377  cp->dotls);
1378  if (!protNum) return 1;
1379  }
1380  }
1381  if (!strcmp("http", cp->proname) && xport)
1382  {for (int i = 0; i < cp->numP; i++)
1383  {if (cp->portVec[i] == xport) {xport = 0; break;}}
1384  if (xport) XrdProtLoad::Port(protNum, xport, false);
1385  }
1386  Firstcp = cp->Next; delete cp;
1387  }
1388 
1389 // Leave the env port number to be the first used port number. This may
1390 // or may not be the same as the default port number. This corresponds to
1391 // the default network object.
1392 //
1393  PortTCP = ProtInfo.Port = XrdNetTCP->Port();
1394  XrdOucEnv::Export("XRDPORT", PortTCP);
1395 
1396 // Now check if we have to setup automatic reporting
1397 //
1398  if (repDest[0] != 0 && repOpts)
1399  ProtInfo.Stats->Report(repDest, repInt, repOpts);
1400 
1401 // All done
1402 //
1403  return 0;
1404 }
1405 
1406 /******************************************************************************/
1407 /* S e t u p A P a t h */
1408 /******************************************************************************/
1409 
1410 int XrdConfig::SetupAPath()
1411 {
1412  int rc;
1413 
1414 // Modify the AdminPath to account for any instance name. Note that there is
1415 // a negligible memory leak under certain path combinations. Not enough to
1416 // warrant a lot of logic to get around.
1417 //
1418  if (myInsName) ProtInfo.AdmPath = XrdOucUtils::genPath(AdminPath,myInsName);
1419  else ProtInfo.AdmPath = AdminPath;
1420  XrdOucEnv::Export("XRDADMINPATH", ProtInfo.AdmPath);
1421  AdminPath = XrdOucUtils::genPath(AdminPath, myInsName, ".xrd");
1422 
1423 // Create the path. Only sockets are group writable but allow read access to
1424 // the path for group members.
1425 //
1426 //
1427  if ((rc = XrdOucUtils::makePath(AdminPath, AdminMode & ~S_IWGRP, true)))
1428  {Log.Emsg("Config", rc, "create admin path", AdminPath);
1429  return 1;
1430  }
1431 
1432 // Setup admin connection now
1433 //
1434  return ASocket(AdminPath, "admin", (mode_t)AdminMode);
1435 }
1436 
1437 /******************************************************************************/
1438 /* S e t u p T L S */
1439 /******************************************************************************/
1440 
1441 bool XrdConfig::SetupTLS()
1442 {
1443 
1444 // Check if we should issue a verification error
1445 //
1446  if (!caDir && !caFile && !tlsNoVer)
1447  {if (tlsNoCAD)
1448  Log.Say("Config failure: the tlsca directive was not specified!");
1449  else Log.Say("Config failure: the tlsca directive did not specify "
1450  "a certdir or certfile!");
1451  return false;
1452  }
1453 
1454 // Set the message callback before doing anything else
1455 //
1456  XrdTls::SetMsgCB(TlsError);
1457 
1458 // Set tracing options as needed
1459 //
1460  if (TRACING((TRACE_DEBUG|TRACE_TLS)))
1461  {int tlsdbg = 0;
1462  if (TRACING(TRACE_DEBUG)) tlsdbg = XrdTls::dbgALL;
1463  else {if (TRACING(TRACE_TLSCTX)) tlsdbg |= XrdTls::dbgCTX;
1464  if (TRACING(TRACE_TLSSIO)) tlsdbg |= XrdTls::dbgSIO;
1465  if (TRACING(TRACE_TLSSOK)) tlsdbg |= XrdTls::dbgSOK;
1466  }
1467  XrdTls::SetDebug(tlsdbg, &Logger);
1468  }
1469 
1470 // Create a context
1471 //
1472  static XrdTlsContext xrdTLS(tlsCert, tlsKey, caDir, caFile, tlsOpts);
1473 
1474 // Check if all went well
1475 //
1476  if (!xrdTLS.isOK()) return false;
1477 
1478 // Set address of out TLS object in the global area
1479 //
1480  XrdGlobal::tlsCtx = &xrdTLS;
1481  return true;
1482 }
1483 
1484 /******************************************************************************/
1485 /* U s a g e */
1486 /******************************************************************************/
1487 
1488 void XrdConfig::Usage(int rc)
1489 {
1490  extern const char *XrdLicense;
1491 
1492  if (rc < 0) std::cerr <<XrdLicense;
1493  else
1494  std::cerr <<"\nUsage: " <<myProg <<" [-b] [-c <cfn>] [-d] [-h] [-H] [-I {v4|v6}]\n"
1495  "[-k {n|sz|sig}] [-l [=]<fn>] [-n name] [-p <port>] [-P <prot>] [-L <libprot>]\n"
1496  "[-R] [-s pidfile] [-S site] [-v] [-z] [<prot_options>]" <<std::endl;
1497  _exit(rc > 0 ? rc : 0);
1498 }
1499 
1500 /******************************************************************************/
1501 /* x a p a t h */
1502 /******************************************************************************/
1503 
1504 /* Function: xapath
1505 
1506  Purpose: To parse the directive: adminpath <path> [group]
1507 
1508  <path> the path of the FIFO to use for admin requests.
1509 
1510  group allows group access to the admin path
1511 
1512  Note: A named socket is created <path>/<name>/.xrd/admin
1513 
1514  Output: 0 upon success or !0 upon failure.
1515 */
1516 
1517 int XrdConfig::xapath(XrdSysError *eDest, XrdOucStream &Config)
1518 {
1519  char *pval, *val;
1520  mode_t mode = S_IRWXU;
1521 
1522 // Get the path
1523 //
1524  pval = Config.GetWord();
1525  if (!pval || !pval[0])
1526  {eDest->Emsg("Config", "adminpath not specified"); return 1;}
1527 
1528 // Make sure it's an absolute path
1529 //
1530  if (*pval != '/')
1531  {eDest->Emsg("Config", "adminpath not absolute"); return 1;}
1532 
1533 // Record the path
1534 //
1535  if (AdminPath) free(AdminPath);
1536  AdminPath = strdup(pval);
1537 
1538 // Get the optional access rights
1539 //
1540  if ((val = Config.GetWord()) && val[0])
1541  {if (!strcmp("group", val)) mode |= S_IRWXG;
1542  else {eDest->Emsg("Config", "invalid admin path modifier -", val);
1543  return 1;
1544  }
1545  }
1546  AdminMode = ProtInfo.AdmMode = mode;
1547  return 0;
1548 }
1549 
1550 /******************************************************************************/
1551 /* x a l l o w */
1552 /******************************************************************************/
1553 
1554 /* Function: xallow
1555 
1556  Purpose: To parse the directive: allow {host | netgroup} <name>
1557 
1558  <name> The dns name of the host that is allowed to connect or the
1559  netgroup name the host must be a member of. For DNS names,
1560  a single asterisk may be specified anywhere in the name.
1561 
1562  Output: 0 upon success or !0 upon failure.
1563 */
1564 
1565 int XrdConfig::xallow(XrdSysError *eDest, XrdOucStream &Config)
1566 {
1567  char *val;
1568  int ishost;
1569 
1570  if (!(val = Config.GetWord()))
1571  {eDest->Emsg("Config", "allow type not specified"); return 1;}
1572 
1573  if (!strcmp(val, "host")) ishost = 1;
1574  else if (!strcmp(val, "netgroup")) ishost = 0;
1575  else {eDest->Emsg("Config", "invalid allow type -", val);
1576  return 1;
1577  }
1578 
1579  if (!(val = Config.GetWord()))
1580  {eDest->Emsg("Config", "allow target name not specified"); return 1;}
1581 
1582  if (!Police) {Police = new XrdNetSecurity();
1583  if (XrdTrace.What == TRACE_ALL) Police->Trace(&XrdTrace);
1584  }
1585  if (ishost) Police->AddHost(val);
1586  else Police->AddNetGroup(val);
1587 
1588  return 0;
1589 }
1590 
1591 /******************************************************************************/
1592 /* x h p a t h */
1593 /******************************************************************************/
1594 
1595 /* Function: xhpath
1596 
1597  Purpose: To parse the directive: homepath <path> [group]
1598 
1599  <path> the path of the home director to be made as the cwd.
1600 
1601  group allows group access to the home path
1602 
1603  Output: 0 upon success or !0 upon failure.
1604 */
1605 
1606 int XrdConfig::xhpath(XrdSysError *eDest, XrdOucStream &Config)
1607 {
1608 // If the command line specified he home, it cannot be undone
1609 //
1610  if (Specs & hpSpec)
1611  {eDest->Say("Config warning: command line homepath cannot be overridden.");
1612  Config.GetWord();
1613  return 0;
1614  }
1615 
1616 // Free existing home path, if any
1617 //
1618  if (HomePath) {free(HomePath); HomePath = 0;}
1619 
1620 // Parse the home path and return success or failure
1621 //
1622  HomePath = XrdOucUtils::parseHome(*eDest, Config, HomeMode);
1623  return (HomePath ? 0 : 1);
1624 }
1625 
1626 /******************************************************************************/
1627 /* x b u f */
1628 /******************************************************************************/
1629 
1630 /* Function: xbuf
1631 
1632  Purpose: To parse the directive: buffers [maxbsz <bsz>] <memsz> [<rint>]
1633 
1634  <bsz> maximum size of an individualbuffer. The default is 2m.
1635  Specify any value 2m < bsz <= 1g; if specified, it must
1636  appear before the <memsz> and <memsz> becomes optional.
1637  <memsz> maximum amount of memory devoted to buffers
1638  <rint> minimum buffer reshape interval in seconds
1639 
1640  Output: 0 upon success or !0 upon failure.
1641 */
1642 int XrdConfig::xbuf(XrdSysError *eDest, XrdOucStream &Config)
1643 {
1644  static const long long minBSZ = 1024*1024*2+1; // 2mb
1645  static const long long maxBSZ = 1024*1024*1024; // 1gb
1646  int bint = -1;
1647  long long blim;
1648  char *val;
1649 
1650  if (!(val = Config.GetWord()))
1651  {eDest->Emsg("Config", "buffer memory limit not specified"); return 1;}
1652 
1653  if (!strcmp("maxbsz", val))
1654  {if (!(val = Config.GetWord()))
1655  {eDest->Emsg("Config", "max buffer size not specified"); return 1;}
1656  if (XrdOuca2x::a2sz(*eDest,"maxbz value",val,&blim,minBSZ,maxBSZ))
1657  return 1;
1658  XrdGlobal::xlBuff.Init(blim);
1659  if (!(val = Config.GetWord())) return 0;
1660  }
1661 
1662  if (XrdOuca2x::a2sz(*eDest,"buffer limit value",val,&blim,
1663  (long long)1024*1024)) return 1;
1664 
1665  if ((val = Config.GetWord()))
1666  if (XrdOuca2x::a2tm(*eDest,"reshape interval", val, &bint, 300))
1667  return 1;
1668 
1669  BuffPool.Set((int)blim, bint);
1670  return 0;
1671 }
1672 
1673 
1674 /******************************************************************************/
1675 /* x m a x f d */
1676 /******************************************************************************/
1677 
1678 /* Function: xmaxfd
1679 
1680  Purpose: To parse the directive: maxfd [strict] <numfd>
1681 
1682  strict when specified, the limits is always applied. Otherwise,
1683  it is only applied when rlimit is infinite.
1684  <numfd> maximum number of fs that can be established.
1685  Specify a value optionally suffixed with 'k'.
1686 
1687  Output: 0 upon success or !0 upon failure.
1688 */
1689 int XrdConfig::xmaxfd(XrdSysError *eDest, XrdOucStream &Config)
1690 {
1691  long long minV = 1024, maxV = 1024LL*1024LL; // between 1k and 1m
1692  long long fdVal;
1693  char *val;
1694 
1695  if ((val = Config.GetWord()))
1696  {if (!strcmp(val, "strict"))
1697  {isStrict = true;
1698  val = Config.GetWord();
1699  } else isStrict = false;
1700  }
1701 
1702  if (!val)
1703  {eDest->Emsg("Config", "file descriptor limit not specified"); return 1;}
1704 
1705 
1706  if (XrdOuca2x::a2sz(*eDest,"maxfd value",val,&fdVal,minV,maxV)) return 1;
1707 
1708  maxFD = static_cast<unsigned int>(fdVal);
1709 
1710  return 0;
1711 }
1712 
1713 /******************************************************************************/
1714 /* x n e t */
1715 /******************************************************************************/
1716 
1717 /* Function: xnet
1718 
1719  Purpose: To parse directive: network [tls] [[no]keepalive] [buffsz <blen>]
1720  [kaparms parms] [cache <ct>] [[no]dnr]
1721  [routes <rtype> [use <ifn1>,<ifn2>]]
1722  [[no]rpipa] [[no]dyndns]
1723 
1724  <rtype>: split | common | local
1725 
1726  tls parameters apply only to the tls port
1727  keepalive do [not] set the socket keepalive option.
1728  kaparms keepalive paramters as specified by parms.
1729  <blen> is the socket's send/rcv buffer size.
1730  <ct> Seconds to cache address to name resolutions.
1731  [no]dnr do [not] perform a reverse DNS lookup if not needed.
1732  routes specifies the network configuration (see reference)
1733  [no]rpipa do [not] resolve private IP addresses.
1734  [no]dyndns This network does [not] use a dynamic DNS.
1735 
1736  Output: 0 upon success or !0 upon failure.
1737 */
1738 
1739 int XrdConfig::xnet(XrdSysError *eDest, XrdOucStream &Config)
1740 {
1741  char *val;
1742  int i, n, V_keep = -1, V_nodnr = 0, V_istls = 0, V_blen = -1, V_ct = -1;
1743  int V_assumev4 = -1, v_rpip = -1, V_dyndns = -1;
1744  long long llp;
1745  struct netopts {const char *opname; int hasarg; int opval;
1746  int *oploc; const char *etxt;}
1747  ntopts[] =
1748  {
1749  {"assumev4", 0, 1, &V_assumev4, "option"},
1750  {"keepalive", 0, 1, &V_keep, "option"},
1751  {"nokeepalive",0, 0, &V_keep, "option"},
1752  {"kaparms", 4, 0, &V_keep, "option"},
1753  {"buffsz", 1, 0, &V_blen, "network buffsz"},
1754  {"cache", 2, 0, &V_ct, "cache time"},
1755  {"dnr", 0, 0, &V_nodnr, "option"},
1756  {"nodnr", 0, 1, &V_nodnr, "option"},
1757  {"dyndns", 0, 1, &V_dyndns, "option"},
1758  {"nodyndns", 0, 0, &V_dyndns, "option"},
1759  {"routes", 3, 1, 0, "routes"},
1760  {"rpipa", 0, 1, &v_rpip, "rpipa"},
1761  {"norpipa", 0, 0, &v_rpip, "norpipa"},
1762  {"tls", 0, 1, &V_istls, "option"}
1763  };
1764  int numopts = sizeof(ntopts)/sizeof(struct netopts);
1765 
1766  if (!(val = Config.GetWord()))
1767  {eDest->Emsg("Config", "net option not specified"); return 1;}
1768 
1769  while (val)
1770  {for (i = 0; i < numopts; i++)
1771  if (!strcmp(val, ntopts[i].opname))
1772  {if (!ntopts[i].hasarg) *ntopts[i].oploc = ntopts[i].opval;
1773  else {if (!(val = Config.GetWord()))
1774  {eDest->Emsg("Config", "network",
1775  ntopts[i].opname, "argument missing");
1776  return 1;
1777  }
1778  if (ntopts[i].hasarg == 4)
1779  {if (xnkap(eDest, val)) return 1;
1780  break;
1781  }
1782  if (ntopts[i].hasarg == 3)
1783  { if (!strcmp(val, "split"))
1785  else if (!strcmp(val, "common"))
1787  else if (!strcmp(val, "local"))
1789  else {eDest->Emsg("Config","Invalid routes argument -",val);
1790  return 1;
1791  }
1792  if (!(val = Config.GetWord())|| !(*val)) break;
1793  if (strcmp(val, "use")) continue;
1794  if (!(val = Config.GetWord())|| !(*val))
1795  {eDest->Emsg("Config", "network routes i/f names "
1796  "not specified.");
1797  return 1;
1798  }
1799  if (!XrdNetIF::SetIFNames(val)) return 1;
1800  ppNet = 1;
1801  break;
1802  }
1803  if (ntopts[i].hasarg == 2)
1804  {if (XrdOuca2x::a2tm(*eDest,ntopts[i].etxt,val,&n,0))
1805  return 1;
1806  *ntopts[i].oploc = n;
1807  } else {
1808  if (XrdOuca2x::a2sz(*eDest,ntopts[i].etxt,val,&llp,0))
1809  return 1;
1810  *ntopts[i].oploc = (int)llp;
1811  }
1812  }
1813  break;
1814  }
1815  if (i >= numopts)
1816  eDest->Say("Config warning: ignoring invalid net option '",val,"'.");
1817  else if (!val) break;
1818  val = Config.GetWord();
1819  }
1820 
1821  if (V_istls)
1822  {if (V_blen >= 0) TLS_Blen = V_blen;
1823  if (V_keep >= 0) TLS_Opts = (V_keep ? XRDNET_KEEPALIVE : 0);
1824  TLS_Opts |= (V_nodnr ? XRDNET_NORLKUP : 0) | XRDNET_USETLS;
1825  } else {
1826  if (V_blen >= 0) Net_Blen = V_blen;
1827  if (V_keep >= 0) Net_Opts = (V_keep ? XRDNET_KEEPALIVE : 0);
1828  Net_Opts |= (V_nodnr ? XRDNET_NORLKUP : 0);
1829  }
1830  // Turn off name chaing if not specified and dynamic dns was specified
1831  //
1832  if (V_dyndns >= 0)
1833  {if (V_dyndns && V_ct < 0) V_ct = 0;
1834  XrdNetAddr::SetDynDNS(V_dyndns != 0);
1835  }
1836  if (V_ct >= 0) XrdNetAddr::SetCache(V_ct);
1837 
1838  if (v_rpip >= 0) XrdInet::netIF.SetRPIPA(v_rpip != 0);
1839  if (V_assumev4 >= 0) XrdInet::SetAssumeV4(true);
1840  return 0;
1841 }
1842 
1843 /******************************************************************************/
1844 /* x n k a p */
1845 /******************************************************************************/
1846 
1847 /* Function: xnkap
1848 
1849  Purpose: To parse the directive: kaparms idle[,itvl[,cnt]]
1850 
1851  idle Seconds the connection needs to remain idle before TCP
1852  should start sending keepalive probes.
1853  itvl Seconds between individual keepalive probes.
1854  icnt Maximum number of keepalive probes TCP should send
1855  before dropping the connection,
1856 */
1857 
1858 int XrdConfig::xnkap(XrdSysError *eDest, char *val)
1859 {
1860  char *karg, *comma;
1861  int knum;
1862 
1863 // Get the first parameter, idle seconds
1864 //
1865  karg = val;
1866  if ((comma = index(val, ','))) {val = comma+1; *comma = 0;}
1867  else val = 0;
1868  if (XrdOuca2x::a2tm(*eDest,"kaparms idle", karg, &knum, 0)) return 1;
1869  XrdNetSocketCFG::ka_Idle = knum;
1870 
1871 // Get the second parameter, interval seconds
1872 //
1873  if (!(karg = val)) return 0;
1874  if ((comma = index(val, ','))) {val = comma+1; *comma = 0;}
1875  else val = 0;
1876  if (XrdOuca2x::a2tm(*eDest,"kaparms interval", karg, &knum, 0)) return 1;
1877  XrdNetSocketCFG::ka_Itvl = knum;
1878 
1879 // Get the third parameter, count
1880 //
1881  if (!val) return 0;
1882  if (XrdOuca2x::a2i(*eDest,"kaparms count", val, &knum, 0)) return 1;
1883  XrdNetSocketCFG::ka_Icnt = knum;
1884 
1885 // All done
1886 //
1887  return 0;
1888 }
1889 
1890 /******************************************************************************/
1891 /* x p i d f */
1892 /******************************************************************************/
1893 
1894 /* Function: xpidf
1895 
1896  Purpose: To parse the directive: pidpath <path>
1897 
1898  <path> the path where the pid file is to be created.
1899 
1900  Output: 0 upon success or !0 upon failure.
1901 */
1902 
1903 int XrdConfig::xpidf(XrdSysError *eDest, XrdOucStream &Config)
1904 {
1905  char *val;
1906 
1907 // Get the path
1908 //
1909  val = Config.GetWord();
1910  if (!val || !val[0])
1911  {eDest->Emsg("Config", "pidpath not specified"); return 1;}
1912 
1913 // Record the path
1914 //
1915  if (PidPath) free(PidPath);
1916  PidPath = strdup(val);
1917  return 0;
1918 }
1919 
1920 /******************************************************************************/
1921 /* x p o r t */
1922 /******************************************************************************/
1923 
1924 /* Function: xport
1925 
1926  Purpose: To parse the directive: port [tls] <tcpnum>
1927  [if [<hlst>] [named <nlst>]]
1928 
1929  tls apply this to the tls port
1930  <tcpnum> number of the tcp port for incoming requests
1931  <hlst> list of applicable host patterns
1932  <nlst> list of applicable instance names.
1933 
1934  Output: 0 upon success or !0 upon failure.
1935 */
1936 int XrdConfig::xport(XrdSysError *eDest, XrdOucStream &Config)
1937 { int rc, istls = 0, pnum = 0;
1938  char *val, cport[32];
1939 
1940  do {if (!(val = Config.GetWord()))
1941  {eDest->Emsg("Config", "tcp port not specified"); return 1;}
1942  if (strcmp("tls", val) || istls) break;
1943  istls = 1;
1944  } while(1);
1945 
1946  strncpy(cport, val, sizeof(cport)-1); cport[sizeof(cport)-1] = '\0';
1947 
1948  if ((val = Config.GetWord()) && !strcmp("if", val))
1949  if ((rc = XrdOucUtils::doIf(eDest,Config, "port directive", myName.c_str(),
1950  ProtInfo.myInst, myProg)) <= 0)
1951  {if (!rc) Config.noEcho(); return (rc < 0);}
1952 
1953  if ((pnum = XrdOuca2x::a2p(*eDest, "tcp", cport)) < 0) return 1;
1954  if (istls) PortTLS = pnum;
1955  else PortTCP = PortUDP = pnum;
1956 
1957  return 0;
1958 }
1959 
1960 
1961 /******************************************************************************/
1962 /* x p r o t */
1963 /******************************************************************************/
1964 
1965 /* Function: xprot
1966 
1967  Purpose: To parse the directive: protocol [tls] <name>[:<port>] <args>
1968 
1969  <args> {+port | <loc> [<parm>]}
1970  tls The protocol requires tls.
1971  <name> The name of the protocol (e.g., rootd)
1972  <port> Port binding for the protocol, if not the default.
1973  <loc> The shared library in which it is located.
1974  <parm> A one line parameter to be passed to the protocol.
1975 
1976  Output: 0 upon success or !0 upon failure.
1977 */
1978 
1979 int XrdConfig::xprot(XrdSysError *eDest, XrdOucStream &Config)
1980 {
1981  XrdConfigProt *cpp;
1982  char *val, *parms, *lib, proname[64], buff[2048];
1983  int portnum = -1;
1984  bool dotls = false;
1985 
1986  do {if (!(val = Config.GetWord()))
1987  {eDest->Emsg("Config", "protocol name not specified"); return 1;}
1988  if (dotls || strcmp("tls", val)) break;
1989  dotls = true;
1990  } while(1);
1991 
1992  if (strlen(val) > sizeof(proname)-1)
1993  {eDest->Emsg("Config", "protocol name is too long"); return 1;}
1994  strcpy(proname, val);
1995 
1996  if ((val = index(proname, ':')))
1997  {if ((portnum = XrdOuca2x::a2p(*eDest, "tcp", val+1)) < 0) return 1;
1998  else *val = '\0';
1999  }
2000 
2001  if (!(val = Config.GetWord()))
2002  {eDest->Emsg("Config", "protocol library not specified"); return 1;}
2003  if (!strcmp("*", val)) lib = 0;
2004  else if (*val == '+')
2005  {if (strcmp(val, "+port"))
2006  {eDest->Emsg("Config","invalid library specification -",val);
2007  return 1;
2008  }
2009  if ((cpp = Firstcp))
2010  do {if (!strcmp(proname, cpp->proname))
2011  {if (cpp->AddPort(portnum, dotls)) return 0;
2012  eDest->Emsg("Config", "port add limit exceeded!");
2013  return 1;
2014  }
2015  } while((cpp = cpp->Next));
2016  eDest->Emsg("Config","protocol",proname,"not previously defined!");
2017  return 1;
2018  }
2019  else lib = strdup(val);
2020 
2021 // If no library was specified then this is a default protocol. We must make sure
2022 // sure it is consistent with whatever default we have.
2023 //
2024  if (!lib && Firstcp && strcmp(proname, Firstcp->proname))
2025  {char eBuff[512];
2026  snprintf(eBuff, sizeof(eBuff), "the %s protocol is '%s' not '%s'; "
2027  "assuming you meant '%s'",
2028  (Firstcp->libpath ? "assigned" : "builtin"),
2029  Firstcp->proname, proname, Firstcp->proname);
2030  eDest->Say("Config warning: ", eBuff, " but please correct "
2031  "the following directive!");
2032  snprintf(proname, sizeof(proname), "%s", Firstcp->proname);
2033  }
2034 
2035  *buff = 0;
2036  if (!Config.GetRest(buff, sizeof(buff)))
2037  {eDest->Emsg("Config", "Too many parms for protocol", proname);
2038  return 1;
2039  }
2040  parms = (*buff ? strdup(buff) : 0);
2041 
2042  if ((cpp = Firstcp))
2043  do {if (!strcmp(proname, cpp->proname))
2044  {cpp->Reset(lib, parms, portnum, dotls);
2045  return 0;
2046  }
2047  } while((cpp = cpp->Next));
2048 
2049  cpp = new XrdConfigProt(strdup(proname), lib, parms, portnum, dotls);
2050  if (!lib) {cpp->Next = Firstcp; Firstcp = cpp;
2051  if (!Lastcp) Lastcp = cpp;
2052  }
2053  else {if (Lastcp) Lastcp->Next = cpp;
2054  else Firstcp = cpp;
2055  Lastcp = cpp;
2056  }
2057  return 0;
2058 }
2059 
2060 /******************************************************************************/
2061 /* x r e p */
2062 /******************************************************************************/
2063 
2064 /* Function: xrep
2065 
2066  Purpose: To parse the directive: report <dest1>[,<dest2>]
2067  [every <sec>] <opts>
2068 
2069  <dest1> where a UDP based report is to be sent. It may be a
2070  <host:port> or a local named UDP pipe (i.e., "/...").
2071 
2072  <dest2> A secondary destination.
2073 
2074  <sec> the reporting interval. The default is 10 minutes.
2075 
2076  <opts> What to report. "all" is the default.
2077 
2078  Output: 0 upon success or !0 upon failure.
2079 */
2080 
2081 int XrdConfig::xrep(XrdSysError *eDest, XrdOucStream &Config)
2082 {
2083  static struct repopts {const char *opname; int opval;} rpopts[] =
2084  {
2085  {"all", XRD_STATS_ALL},
2086  {"buff", XRD_STATS_BUFF},
2087  {"info", XRD_STATS_INFO},
2088  {"link", XRD_STATS_LINK},
2089  {"poll", XRD_STATS_POLL},
2090  {"process", XRD_STATS_PROC},
2091  {"protocols",XRD_STATS_PROT},
2092  {"prot", XRD_STATS_PROT},
2093  {"sched", XRD_STATS_SCHD},
2094  {"sgen", XRD_STATS_SGEN},
2095  {"sync", XRD_STATS_SYNC},
2096  {"syncwp", XRD_STATS_SYNCA}
2097  };
2098  int i, neg, numopts = sizeof(rpopts)/sizeof(struct repopts);
2099  char *val, *cp;
2100 
2101  if (!(val = Config.GetWord()))
2102  {eDest->Emsg("Config", "report parameters not specified"); return 1;}
2103 
2104 // Cleanup to start anew
2105 //
2106  if (repDest[0]) {free(repDest[0]); repDest[0] = 0;}
2107  if (repDest[1]) {free(repDest[1]); repDest[1] = 0;}
2108  repOpts = 0;
2109  repInt = 600;
2110 
2111 // Decode the destination
2112 //
2113  if ((cp = (char *)index(val, ',')))
2114  {if (!*(cp+1))
2115  {eDest->Emsg("Config","malformed report destination -",val); return 1;}
2116  else { repDest[1] = cp+1; *cp = '\0';}
2117  }
2118  repDest[0] = val;
2119  for (i = 0; i < 2; i++)
2120  {if (!(val = repDest[i])) break;
2121  if (*val != '/' && (!(cp = index(val, (int)':')) || !atoi(cp+1)))
2122  {eDest->Emsg("Config","report dest port missing or invalid in",val);
2123  return 1;
2124  }
2125  repDest[i] = strdup(val);
2126  }
2127 
2128 // Make sure dests differ
2129 //
2130  if (repDest[0] && repDest[1] && !strcmp(repDest[0], repDest[1]))
2131  {eDest->Emsg("Config", "Warning, report dests are identical.");
2132  free(repDest[1]); repDest[1] = 0;
2133  }
2134 
2135 // Get optional "every"
2136 //
2137  if (!(val = Config.GetWord())) {repOpts = XRD_STATS_ALL; return 0;}
2138  if (!strcmp("every", val))
2139  {if (!(val = Config.GetWord()))
2140  {eDest->Emsg("Config", "report every value not specified"); return 1;}
2141  if (XrdOuca2x::a2tm(*eDest,"report every",val,&repInt,1)) return 1;
2142  val = Config.GetWord();
2143  }
2144 
2145 // Get reporting options
2146 //
2147  while(val)
2148  {if (!strcmp(val, "off")) repOpts = 0;
2149  else {if ((neg = (val[0] == '-' && val[1]))) val++;
2150  for (i = 0; i < numopts; i++)
2151  {if (!strcmp(val, rpopts[i].opname))
2152  {if (neg) repOpts &= ~rpopts[i].opval;
2153  else repOpts |= rpopts[i].opval;
2154  break;
2155  }
2156  }
2157  if (i >= numopts)
2158  eDest->Say("Config warning: ignoring invalid report option '",val,"'.");
2159  }
2160  val = Config.GetWord();
2161  }
2162 
2163 // All done
2164 //
2165  if (!(repOpts & XRD_STATS_ALL))
2166  repOpts = char(XRD_STATS_ALL & ~XRD_STATS_INFO);
2167  return 0;
2168 }
2169 
2170 /******************************************************************************/
2171 /* x s c h e d */
2172 /******************************************************************************/
2173 
2174 /* Function: xsched
2175 
2176  Purpose: To parse directive: sched [mint <mint>] [maxt <maxt>] [avlt <at>]
2177  [idle <idle>] [stksz <qnt>] [core <cv>]
2178 
2179  <mint> is the minimum number of threads that we need. Once
2180  this number of threads is created, it does not decrease.
2181  <maxt> maximum number of threads that may be created. The
2182  actual number of threads will vary between <mint> and
2183  <maxt>.
2184  <avlt> Are the number of threads that must be available for
2185  immediate dispatch. These threads are never bound to a
2186  connection (i.e., made stickied). Any available threads
2187  above <ft> will be allowed to stick to a connection.
2188  <cv> asis - leave current value alone.
2189  max - set value to maximum allowed (hard limit).
2190  off - turn off core files.
2191  <idle> The time (in time spec) between checks for underused
2192  threads. Those found will be terminated. Default is 780.
2193  <qnt> The thread stack size in bytes or K, M, or G.
2194 
2195  Output: 0 upon success or 1 upon failure.
2196 */
2197 
2198 int XrdConfig::xsched(XrdSysError *eDest, XrdOucStream &Config)
2199 {
2200  char *val;
2201  long long lpp;
2202  int i, ppp = 0;
2203  int V_mint = -1, V_maxt = -1, V_idle = -1, V_avlt = -1;
2204  struct schedopts {const char *opname; int minv; int *oploc;
2205  const char *opmsg;} scopts[] =
2206  {
2207  {"stksz", 0, 0, "sched stksz"},
2208  {"mint", 1, &V_mint, "sched mint"},
2209  {"maxt", 1, &V_maxt, "sched maxt"},
2210  {"avlt", 1, &V_avlt, "sched avlt"},
2211  {"core", 1, 0, "sched core"},
2212  {"idle", 0, &V_idle, "sched idle"}
2213  };
2214  int numopts = sizeof(scopts)/sizeof(struct schedopts);
2215 
2216  if (!(val = Config.GetWord()))
2217  {eDest->Emsg("Config", "sched option not specified"); return 1;}
2218 
2219  while (val)
2220  {for (i = 0; i < numopts; i++)
2221  if (!strcmp(val, scopts[i].opname))
2222  {if (!(val = Config.GetWord()))
2223  {eDest->Emsg("Config", "sched", scopts[i].opname,
2224  "value not specified");
2225  return 1;
2226  }
2227  if (*scopts[i].opname == 'i')
2228  {if (XrdOuca2x::a2tm(*eDest, scopts[i].opmsg, val,
2229  &ppp, scopts[i].minv)) return 1;
2230  }
2231  else if (*scopts[i].opname == 'c')
2232  { if (!strcmp("asis", val)) coreV = -1;
2233  else if (!strcmp("max", val)) coreV = 1;
2234  else if (!strcmp("off", val)) coreV = 0;
2235  else {eDest->Emsg("Config","invalid sched core value -",val);
2236  return 1;
2237  }
2238  }
2239  else if (*scopts[i].opname == 's')
2240  {if (XrdOuca2x::a2sz(*eDest, scopts[i].opmsg, val,
2241  &lpp, scopts[i].minv)) return 1;
2242  XrdSysThread::setStackSize((size_t)lpp);
2243  break;
2244  }
2245  else if (XrdOuca2x::a2i(*eDest, scopts[i].opmsg, val,
2246  &ppp,scopts[i].minv)) return 1;
2247  *scopts[i].oploc = ppp;
2248  break;
2249  }
2250  if (i >= numopts)
2251  eDest->Say("Config warning: ignoring invalid sched option '",val,"'.");
2252  val = Config.GetWord();
2253  }
2254 
2255 // Make sure specified quantities are consistent
2256 //
2257  if (V_maxt > 0)
2258  {if (V_mint > 0 && V_mint > V_maxt)
2259  {eDest->Emsg("Config", "sched mint must be less than maxt");
2260  return 1;
2261  }
2262  if (V_avlt > 0 && V_avlt > V_maxt)
2263  {eDest->Emsg("Config", "sched avlt must be less than maxt");
2264  return 1;
2265  }
2266  }
2267 
2268 // Establish scheduler options
2269 //
2270  Sched.setParms(V_mint, V_maxt, V_avlt, V_idle);
2271  return 0;
2272 }
2273 
2274 /******************************************************************************/
2275 /* x s i t */
2276 /******************************************************************************/
2277 
2278 /* Function: xsit
2279 
2280  Purpose: To parse directive: sitename <name>
2281 
2282  <name> is the 1- to 15-character site name to be included in
2283  monitoring information. This can also come from the
2284  command line -N option. The first such name is used.
2285 
2286  Output: 0 upon success or 1 upon failure.
2287 */
2288 
2289 int XrdConfig::xsit(XrdSysError *eDest, XrdOucStream &Config)
2290 {
2291  char *val;
2292 
2293  if (!(val = Config.GetWord()))
2294  {eDest->Emsg("Config", "sitename value not specified"); return 1;}
2295 
2296  if (mySitName) eDest->Emsg("Config", "sitename already specified, using '",
2297  mySitName, "'.");
2298  else mySitName = XrdOucSiteName::Set(val, 63);
2299  return 0;
2300 }
2301 
2302 /******************************************************************************/
2303 /* x t c p m o n */
2304 /******************************************************************************/
2305 
2306 /* Function: xtcpmon
2307 
2308  Purpose: To parse the directive: tcpmonlib [++] <path> [<parms>]
2309 
2310  <path> absolute path to the tcp monitor plugin.
2311  <parms> optional parameters passed to the plugin.
2312 
2313  Output: 0 upon success or !0 upon failure.
2314 */
2315 
2316 int XrdConfig::xtcpmon(XrdSysError *eDest, XrdOucStream &Config)
2317 {
2318  std::string path;
2319  char *val, parms[2048];
2320  bool push = false;
2321 
2322 // Get the path or the push token
2323 //
2324  if ((val = Config.GetWord()))
2325  {if (!strcmp(val, "++"))
2326  {push = true;
2327  val = Config.GetWord();
2328  }
2329  }
2330 
2331 // Make sure a path was specified
2332 //
2333  if (!val || !*val)
2334  {eDest->Emsg("Config", "tcpmonlib not specified"); return 1;}
2335 
2336 // Make sure the path is absolute
2337 //
2338  if (*val != '/')
2339  {eDest->Emsg("Config", "tcpmonlib path is not absolute"); return 1;}
2340 
2341 // Sequester the path as we will get additional tokens
2342 //
2343  path = val;
2344 
2345 // Record any parms
2346 //
2347  if (!Config.GetRest(parms, sizeof(parms)))
2348  {eDest->Emsg("Config", "tcpmonlib parameters too long"); return 1;}
2349 
2350 // Check if we have a plugin info object (we will need one for this)
2351 //
2352  if (!tmoInfo) tmoInfo = new XrdTcpMonInfo("xrd.tcpmonlib",ConfigFN,*eDest);
2353 
2354 // Add the plugin
2355 //
2356  tmoInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
2357 
2358 // All done
2359 //
2360  return 0;
2361 }
2362 
2363 /******************************************************************************/
2364 /* x t l s */
2365 /******************************************************************************/
2366 
2367 /* Function: xtls
2368 
2369  Purpose: To parse directive: tls <cpath> [<kpath>] [<opts>]
2370 
2371  <cpath> is the the certificate file to be used.
2372  <kpath> is the the private key file to be used.
2373  <opts> options:
2374  [no]detail do [not] print TLS library msgs
2375  hsto <sec> handshake timeout (default 10).
2376 
2377  Output: 0 upon success or 1 upon failure.
2378 */
2379 
2380 int XrdConfig::xtls(XrdSysError *eDest, XrdOucStream &Config)
2381 {
2382  char *val;
2383  int num;
2384 
2385  if (!(val = Config.GetWord()))
2386  {eDest->Emsg("Config", "tls cert path not specified"); return 1;}
2387 
2388  if (*val != '/')
2389  {eDest->Emsg("Config", "tls cert path not absolute"); return 1;}
2390 
2391  if (tlsCert) free(tlsCert);
2392  tlsCert = strdup(val);
2393  if (tlsKey) free(tlsKey);
2394  tlsKey = 0;
2395 
2396  if (!(val = Config.GetWord())) return 0;
2397 
2398  if (*val == '/')
2399  {tlsKey = strdup(val);
2400  if (!(val = Config.GetWord())) return 0;
2401  }
2402 
2403 do { if (!strcmp(val, "detail")) SSLmsgs = true;
2404  else if (!strcmp(val, "nodetail")) SSLmsgs = false;
2405  else if (!strcmp(val, "hsto" ))
2406  {if (!(val = Config.GetWord()))
2407  {eDest->Emsg("Config", "tls hsto value not specified");
2408  return 1;
2409  }
2410  if (XrdOuca2x::a2tm(*eDest,"tls hsto",val,&num,1,255))
2411  return 1;
2412  tlsOpts = TLS_SET_HSTO(tlsOpts,num);
2413  }
2414  else {eDest->Emsg("Config", "invalid tls option -",val); return 1;}
2415  } while ((val = Config.GetWord()));
2416 
2417  return 0;
2418 }
2419 
2420 /******************************************************************************/
2421 /* x t l s c a */
2422 /******************************************************************************/
2423 
2424 /* Function: xtlsca
2425 
2426  Purpose: To parse directive: tlsca noverify | <parms> [<opts>]
2427 
2428  parms: {certdir | certfile} <path>
2429 
2430  opts: [crlcheck {all | external | last}] [log {failure | off}]
2431 
2432  [[no]proxies] [refresh t[m|h|s]] [verdepth <n>]
2433 
2434  noverify client's cert need not be verified.
2435  <path> is the the certificate path or file to be used.
2436  Both a file and a directory path can be specified.
2437  crlcheck Controls internal crl checks:
2438  all applies crls to the full chain
2439  external leaves crl checking to an external plug-in
2440  last applies crl check to the last cert only
2441  log logs verification attempts: "failure" (the default) logs
2442  verification failures, while "off" logs nothing.
2443  proxies allows proxy certs while noproxies does not.
2444  <t> the crl/ca refresh interval.
2445  <n> the maximum certificate depth to be check.
2446 
2447  Output: 0 upon success or 1 upon failure.
2448 */
2449 
2450 int XrdConfig::xtlsca(XrdSysError *eDest, XrdOucStream &Config)
2451 {
2452  char *val, **cadest, kword[16];
2453  int vd, rt;
2454  bool isdir;
2455 
2456  if (!(val = Config.GetWord()))
2457  {eDest->Emsg("Config", "tlsca parameter not specified"); return 1;}
2458  tlsNoCAD = false;
2459 
2460  if (!strcmp(val, "noverify"))
2461  {tlsNoVer = true;
2462  if (caDir) {free(caDir); caDir = 0;}
2463  if (caFile) {free(caFile); caFile = 0;}
2464  return 0;
2465  }
2466  tlsNoVer = false;
2467 
2468 
2469  do {if (!strcmp(val, "proxies") || !strcmp("noproxies", val))
2470  {if (*val == 'n') tlsOpts |= XrdTlsContext::nopxy;
2471  else tlsOpts &= ~XrdTlsContext::nopxy;
2472  continue;
2473  }
2474 
2475  if (strlen(val) >= (int)sizeof(kword))
2476  {eDest->Emsg("Config", "Invalid tlsca parameter -", val);
2477  return 1;
2478  }
2479  strcpy(kword, val);
2480 
2481  if (!(val = Config.GetWord()))
2482  {eDest->Emsg("Config", "tlsca", kword, "value not specified");
2483  return 1;
2484  }
2485  if ((isdir = !strcmp(kword, "certdir"))
2486  || !strcmp(kword, "certfile"))
2487  {if (*val != '/')
2488  {eDest->Emsg("Config","tlsca",kword,"path is not absolute.");
2489  return 1;
2490  }
2491  cadest = (isdir ? &caDir : &caFile);
2492  if (*cadest) free(*cadest);
2493  *cadest = strdup(val);
2494  }
2495  else if (!strcmp(kword, "crlcheck"))
2496  {tlsOpts &= ~(XrdTlsContext::crlON | XrdTlsContext::crlFC);
2497  if (!strcmp(val, "all")) tlsOpts |= XrdTlsContext::crlFC;
2498  else if (!strcmp(val, "last")) tlsOpts |= XrdTlsContext::crlON;
2499  else if ( strcmp(val, "external"))
2500  {eDest->Emsg("Config","Invalid tlsca crlcheck "
2501  " argument -",val);
2502  return 1;
2503  }
2504  }
2505  else if (!strcmp(kword, "log"))
2506  { if (!strcmp(val, "off"))
2507  tlsOpts &= ~XrdTlsContext::logVF;
2508  else if (!strcmp(val, "failure"))
2509  tlsOpts |= XrdTlsContext::logVF;
2510  else {eDest->Emsg("Config","Invalid tlsca log argument -",val);
2511  return 1;
2512  }
2513  }
2514  else if (!strcmp(kword, "refresh"))
2515  {if (XrdOuca2x::a2tm(*eDest, "tlsca refresh interval",
2516  val, &rt,1,std::min(int((XrdTlsContext::crlRF >> XrdTlsContext::crlRS) * 60),std::numeric_limits<int>::max()))) return 1;
2517  if (rt < 60) rt = 60;
2518  else if (rt % 60) rt += 60;
2519  rt = rt/60;
2520  tlsOpts = TLS_SET_REFINT(tlsOpts,rt);
2521  }
2522  else if (!strcmp(kword, "verdepth"))
2523  {if (XrdOuca2x::a2i(*eDest,"tlsca verdepth",val,&vd,1,255))
2524  return 1;
2525  tlsOpts = TLS_SET_VDEPTH(tlsOpts,vd);
2526  }
2527  else {eDest->Emsg("Config", "invalid tlsca option -",kword); return 1;}
2528 
2529  } while((val = Config.GetWord()));
2530 
2531  return 0;
2532 }
2533 
2534 /******************************************************************************/
2535 /* x t l s c i */
2536 /******************************************************************************/
2537 
2538 /* Function: xtlsci
2539 
2540  Purpose: To parse directive: tlsciphers <ciphers>
2541 
2542  <ciphers> list of colon sperated ciphers to use.
2543 
2544  Output: 0 upon success or 1 upon failure.
2545 */
2546 
2547 int XrdConfig::xtlsci(XrdSysError *eDest, XrdOucStream &Config)
2548 {
2549  char *val, *ciphers;
2550 
2551  if (!(val = Config.GetWord()))
2552  {eDest->Emsg("Config", "tlsciphers parameter not specified"); return 1;}
2553 
2554  ciphers = strdup(val);
2555 
2556  if ((val = Config.GetWord()))
2557  {eDest->Emsg("Config","Invalid tlsciphers argument -",val);
2558  return 1;
2559  }
2560 
2562  return 0;
2563 }
2564 
2565 /******************************************************************************/
2566 /* x t m o */
2567 /******************************************************************************/
2568 
2569 /* Function: xtmo
2570 
2571  Purpose: To parse directive: timeout [read <msd>] [hail <msh>]
2572  [idle <msi>] [kill <msk>]
2573 
2574  <msd> is the maximum number of seconds to wait for pending
2575  data to arrive before we reschedule the link
2576  (default is 5 seconds).
2577  <msh> is the maximum number of seconds to wait for the initial
2578  data after a connection (default is 30 seconds)
2579  <msi> is the minimum number of seconds a connection may remain
2580  idle before it is closed (default is 5400 = 90 minutes)
2581  <msk> is the minimum number of seconds to wait after killing a
2582  connection for it to end (default is 3 seconds)
2583 
2584  Output: 0 upon success or 1 upon failure.
2585 */
2586 
2587 int XrdConfig::xtmo(XrdSysError *eDest, XrdOucStream &Config)
2588 {
2589  char *val;
2590  int i, ppp, rc;
2591  int V_read = -1, V_idle = -1, V_hail = -1, V_kill = -1;
2592  struct tmoopts { const char *opname; int istime; int minv;
2593  int *oploc; const char *etxt;}
2594  tmopts[] =
2595  {
2596  {"read", 1, 1, &V_read, "timeout read"},
2597  {"hail", 1, 1, &V_hail, "timeout hail"},
2598  {"idle", 1, 0, &V_idle, "timeout idle"},
2599  {"kill", 1, 0, &V_kill, "timeout kill"}
2600  };
2601  int numopts = sizeof(tmopts)/sizeof(struct tmoopts);
2602 
2603  if (!(val = Config.GetWord()))
2604  {eDest->Emsg("Config", "timeout option not specified"); return 1;}
2605 
2606  while (val)
2607  {for (i = 0; i < numopts; i++)
2608  if (!strcmp(val, tmopts[i].opname))
2609  {if (!(val = Config.GetWord()))
2610  {eDest->Emsg("Config","timeout", tmopts[i].opname,
2611  "value not specified");
2612  return 1;
2613  }
2614  rc = (tmopts[i].istime ?
2615  XrdOuca2x::a2tm(*eDest,tmopts[i].etxt,val,&ppp,
2616  tmopts[i].minv) :
2617  XrdOuca2x::a2i (*eDest,tmopts[i].etxt,val,&ppp,
2618  tmopts[i].minv));
2619  if (rc) return 1;
2620  *tmopts[i].oploc = ppp;
2621  break;
2622  }
2623  if (i >= numopts)
2624  eDest->Say("Config warning: ignoring invalid timeout option '",val,"'.");
2625  val = Config.GetWord();
2626  }
2627 
2628 // Set values and return
2629 //
2630  if (V_read > 0) ProtInfo.readWait = V_read*1000;
2631  if (V_hail >= 0) ProtInfo.hailWait = V_hail*1000;
2632  if (V_idle >= 0) ProtInfo.idleWait = V_idle;
2633  XrdLinkCtl::setKWT(V_read, V_kill);
2634  return 0;
2635 }
2636 
2637 /******************************************************************************/
2638 /* x t r a c e */
2639 /******************************************************************************/
2640 
2641 /* Function: xtrace
2642 
2643  Purpose: To parse the directive: trace <events>
2644 
2645  <events> the blank separated list of events to trace. Trace
2646  directives are cummalative.
2647 
2648  Output: 0 upon success or 1 upon failure.
2649 */
2650 
2651 int XrdConfig::xtrace(XrdSysError *eDest, XrdOucStream &Config)
2652 {
2653  char *val;
2654  static struct traceopts {const char *opname; int opval;} tropts[] =
2655  {
2656  {"all", TRACE_ALL},
2657  {"off", TRACE_NONE},
2658  {"none", TRACE_NONE},
2659  {"conn", TRACE_CONN},
2660  {"debug", TRACE_DEBUG},
2661  {"mem", TRACE_MEM},
2662  {"net", TRACE_NET},
2663  {"poll", TRACE_POLL},
2664  {"protocol", TRACE_PROT},
2665  {"sched", TRACE_SCHED},
2666  {"tls", TRACE_TLS},
2667  {"tlsctx", TRACE_TLSCTX},
2668  {"tlssio", TRACE_TLSSIO},
2669  {"tlssok", TRACE_TLSSOK}
2670  };
2671  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
2672 
2673  if (!(val = Config.GetWord()))
2674  {eDest->Emsg("Config", "trace option not specified"); return 1;}
2675  while (val)
2676  {if (!strcmp(val, "off")) trval = 0;
2677  else {if ((neg = (val[0] == '-' && val[1]))) val++;
2678  for (i = 0; i < numopts; i++)
2679  {if (!strcmp(val, tropts[i].opname))
2680  {if (neg)
2681  if (tropts[i].opval) trval &= ~tropts[i].opval;
2682  else trval = TRACE_ALL;
2683  else if (tropts[i].opval) trval |= tropts[i].opval;
2684  else trval = TRACE_NONE;
2685  break;
2686  }
2687  }
2688  if (i >= numopts)
2689  eDest->Say("Config warning: ignoring invalid trace option '",val,"'.");
2690  }
2691  val = Config.GetWord();
2692  }
2693  XrdTrace.What = trval;
2694  return 0;
2695 }
void Usage(const char *msg)
Definition: XrdAccTest.cc:105
#define TS_Xeq(x, m)
Definition: XrdConfig.cc:155
static XrdSysError eDest(0,"crypto_")
const char * XrdLicense
Definition: XrdInfo.cc:39
#define XrdBANNER
Definition: XrdInfo.hh:38
#define XrdFORMATB
Definition: XrdInfo.hh:36
int optopt
int optind
#define XRDNET_NORLKUP
Definition: XrdNetOpts.hh:87
#define XRDNET_KEEPALIVE
Definition: XrdNetOpts.hh:63
#define XRDNET_USETLS
Definition: XrdNetOpts.hh:91
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
#define close(a)
Definition: XrdPosix.hh:43
#define XRD_STATS_POLL
Definition: XrdStats.hh:40
#define XRD_STATS_SYNC
Definition: XrdStats.hh:45
#define XRD_STATS_INFO
Definition: XrdStats.hh:37
#define XRD_STATS_LINK
Definition: XrdStats.hh:39
#define XRD_STATS_BUFF
Definition: XrdStats.hh:38
#define XRD_STATS_SYNCA
Definition: XrdStats.hh:46
#define XRD_STATS_SCHD
Definition: XrdStats.hh:43
#define XRD_STATS_ALL
Definition: XrdStats.hh:36
#define XRD_STATS_PROT
Definition: XrdStats.hh:42
#define XRD_STATS_PROC
Definition: XrdStats.hh:41
#define XRD_STATS_SGEN
Definition: XrdStats.hh:44
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_HSTO(cOpts, hstv)
#define TLS_SET_REFINT(cOpts, refi)
#define TRACE_NONE
Definition: XrdTrace.hh:34
#define TRACE_DEBUG
Definition: XrdTrace.hh:36
#define TRACE_NET
Definition: XrdTrace.hh:39
#define TRACE_TLS
Definition: XrdTrace.hh:44
#define TRACE_TLSCTX
Definition: XrdTrace.hh:45
#define TRACE_TLSSOK
Definition: XrdTrace.hh:47
#define TRACE_CONN
Definition: XrdTrace.hh:37
#define TRACE_TLSSIO
Definition: XrdTrace.hh:46
#define TRACE_MEM
Definition: XrdTrace.hh:38
#define TRACE_POLL
Definition: XrdTrace.hh:40
#define TRACE_PROT
Definition: XrdTrace.hh:41
#define TRACE_SCHED
Definition: XrdTrace.hh:42
#define TRACE(act, x)
Definition: XrdTrace.hh:63
#define TRACE_ALL
Definition: XrdTrace.hh:35
#define TRACING(x)
Definition: XrdTrace.hh:70
void Set(int maxmem=-1, int minw=-1)
Definition: XrdBuffer.cc:308
void Init(int maxMSZ)
Definition: XrdBuffXL.cc:64
char * libpath
Definition: XrdConfig.cc:174
XrdConfigProt * Next
Definition: XrdConfig.cc:172
void Reset(char *ln, char *pp, int np=-1, bool to=false)
Definition: XrdConfig.cc:195
char * parms
Definition: XrdConfig.cc:175
char * proname
Definition: XrdConfig.cc:173
XrdConfigProt(char *pn, char *ln, char *pp, int np=-1, bool to=false)
Definition: XrdConfig.cc:207
bool AddPort(int pnum, bool isTLS)
Definition: XrdConfig.cc:185
int ConfigXeq(char *var, XrdOucStream &Config, XrdSysError *eDest=0)
Definition: XrdConfig.cc:800
int Configure(int argc, char **argv)
Definition: XrdConfig.cc:317
int BindSD(int port, const char *contype="tcp")
Definition: XrdInet.cc:130
static void SetAssumeV4(bool newVal)
Definition: XrdInet.hh:63
static XrdNetIF netIF
Definition: XrdInet.hh:68
static int Setup(int maxfds, int idlewt)
Definition: XrdLinkCtl.cc:329
static void setKWT(int wkSec, int kwSec)
Definition: XrdLinkCtl.cc:319
const sockaddr * SockAddr()
const char * Name(const char *eName=0, const char **eText=0)
static void SetIPV4()
Definition: XrdNetAddr.cc:519
static void SetCache(int keeptime)
Definition: XrdNetAddr.cc:499
static void SetIPV6()
Definition: XrdNetAddr.cc:545
static void SetDynDNS(bool onoff)
Definition: XrdNetAddr.cc:513
static bool IPV4Set()
Definition: XrdNetAddr.hh:61
static void SetRPIPA(bool rval)
Definition: XrdNetIF.cc:893
static int GetIF(XrdOucTList **ifList, const char **eText=0)
Definition: XrdNetIF.cc:429
static void Routing(netType nettype)
Definition: XrdNetIF.cc:686
static void SetMsgs(XrdSysError *erp)
Definition: XrdNetIF.cc:887
static bool SetIFNames(char *ifnames)
Definition: XrdNetIF.cc:780
@ netSplit
Definition: XrdNetIF.hh:364
@ netCommon
Definition: XrdNetIF.hh:364
@ netLocal
Definition: XrdNetIF.hh:364
static int ProtoID(const char *pName)
Definition: XrdNetUtils.cc:801
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
Definition: XrdNetUtils.cc:837
int Port()
Definition: XrdNet.hh:191
void setDomain(const char *dname)
Definition: XrdNet.hh:233
void setDefaults(int options, int buffsz=0)
Definition: XrdNet.hh:223
void PutInt(const char *varname, long value)
Definition: XrdOucEnv.cc:250
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:170
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:263
void PutPtr(const char *varname, void *value)
Definition: XrdOucEnv.cc:298
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
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
int length() const
void resize(int lmx=0)
static char * parseHome(XrdSysError &eDest, XrdOucStream &Config, int &mode)
static const mode_t pathMode
Definition: XrdOucUtils.hh:48
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:414
static int ReLink(const char *path, const char *target, mode_t mode=0)
static const char * InstName(int TranOpt=0)
Definition: XrdOucUtils.cc:729
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
Definition: XrdOucUtils.cc:228
static int makePath(char *path, mode_t mode, bool reset=false)
Definition: XrdOucUtils.cc:914
static bool PidFile(XrdSysError &eDest, const char *path)
static void makeHome(XrdSysError &eDest, const char *inst)
Definition: XrdOucUtils.cc:847
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)
Definition: XrdOuca2x.cc:45
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition: XrdOuca2x.cc:257
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
static int a2p(XrdSysError &, const char *ptype, const char *val, bool anyOK=true)
Definition: XrdOuca2x.cc:140
static int Setup(int numfd)
Definition: XrdPoll.cc:291
static const int PortoMax
Definition: XrdProtLoad.hh:64
static int Port(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi)
Definition: XrdProtLoad.cc:156
static int Load(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi, bool istls)
Definition: XrdProtLoad.cc:116
static const int admPSet
Definition: XrdProtocol.hh:79
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)
Definition: XrdSysError.cc:95
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)
Definition: XrdSysError.cc:141
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
const char * xlogFN()
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)
Definition: XrdSysUtils.cc:117
XrdOucPinKing< XrdTcpMonPin > KingPin
Definition: XrdConfig.cc:229
XrdOucEnv theEnv
Definition: XrdConfig.cc:237
XrdTcpMonInfo(const char *drctv, const char *cfn, XrdSysError &errR)
Definition: XrdConfig.cc:231
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)
Definition: XrdTls.cc:196
static const int dbgSIO
Turn debugging in for socket I/O.
Definition: XrdTls.hh:102
static const int dbgSOK
Turn debugging in for socket operations.
Definition: XrdTls.hh:101
static const int dbgALL
Turn debugging for everything.
Definition: XrdTls.hh:103
static const int dbgCTX
Turn debugging in for context operations.
Definition: XrdTls.hh:100
static void SetDebug(int opts, XrdSysLogger *logP=0)
Definition: XrdTls.cc:177
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
XrdCmsConfig Config
XrdOucEnv theEnv
XrdTlsContext * tlsCtx
Definition: XrdGlobals.cc:52
XrdTcpMonPin * TcpMonPin
Definition: XrdLinkXeq.cc:96
XrdInet * XrdNetTCP
Definition: XrdGlobals.cc:53
XrdSysError Log
Definition: XrdConfig.cc:111
XrdBuffXL xlBuff
Definition: XrdBuffer.cc:68
XrdScheduler Sched
Definition: XrdLinkCtl.cc:54
XrdSysLogger Logger
Definition: XrdGlobals.cc:47
XrdSysTrace XrdTrace
Definition: XrdTrace.hh:56
XrdOucString totalCF
Definition: XrdConfig.cc:109
XrdBuffManager BuffPool
Definition: XrdGlobals.cc:51
int devNull
Definition: XrdGlobals.cc:55
const char * myDomain
static INT to(const char *buffer)
Definition: XrdZipUtils.hh:91