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