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