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