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