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