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