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