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