XRootD
XrdXrootdConfig.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X r o o t d C o n f i g . c c */
4 /* */
5 /* (c) 2010 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 #include <unistd.h>
31 #include <cctype>
32 #include <fcntl.h>
33 #include <string>
34 #include <cstring>
35 #include <cstdio>
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <vector>
40 
41 #ifdef __solaris__
42 #include <sys/isa_defs.h>
43 #endif
44 
45 #include "XrdVersion.hh"
46 
47 #include "XProtocol/XProtocol.hh"
48 
49 #include "XrdSfs/XrdSfsFlags.hh"
51 #include "XrdNet/XrdNetOpts.hh"
52 #include "XrdNet/XrdNetPMarkCfg.hh"
53 #include "XrdNet/XrdNetSocket.hh"
54 #include "XrdOuc/XrdOuca2x.hh"
55 #include "XrdOuc/XrdOucEnv.hh"
56 #include "XrdOuc/XrdOucProg.hh"
57 #include "XrdOuc/XrdOucReqID.hh"
58 #include "XrdOuc/XrdOucString.hh"
59 #include "XrdOuc/XrdOucStream.hh"
60 #include "XrdOuc/XrdOucUtils.hh"
62 #include "XrdSys/XrdSysError.hh"
63 #include "XrdSys/XrdSysHeaders.hh"
64 #include "XrdSys/XrdSysLogger.hh"
65 
66 #include "XrdTls/XrdTlsContext.hh"
67 
81 
82 #include "Xrd/XrdBuffer.hh"
83 #include "Xrd/XrdInet.hh"
84 #include "Xrd/XrdLink.hh"
85 
86 /******************************************************************************/
87 /* P r o t o c o l C o m m a n d L i n e O p t i o n s */
88 /******************************************************************************/
89 
90 /* This is the XRootd server. The syntax is:
91 
92  xrootd [options]
93 
94  options: [<xopt>] [-r] [-t] [-y] [path]
95 
96 Where:
97  xopt are xrd specified options that are screened out.
98 
99  -r This is a redirecting server.
100 
101  -t This server is a redirection target.
102 
103  -y This server is a proxy server.
104 
105  path Export path. Any number of paths may be specified.
106  By default, only '/tmp' is exported.
107 
108 */
109 /******************************************************************************/
110 /* G l o b a l s */
111 /******************************************************************************/
112 
114 
116 
118 
119  const char *XrdXrootdInstance;
120 
122 
125  const char *,
126  const char *, XrdOucEnv *);
127 
130  const char *, const char *,
131  const char *, XrdOucEnv *);
132 
134  (XrdSfsFileSystem *nativeFS,
136  const char *configFn,
137  XrdOucEnv *EnvInfo);
138 
139 /******************************************************************************/
140 /* G l o b a l S t a t i c s */
141 /******************************************************************************/
142 
143 namespace XrdXrootd
144 {
145 extern XrdBuffManager *BPool;
146 extern XrdScheduler *Sched;
147 extern XrdXrootdStats *SI;
148 }
149 
150 /******************************************************************************/
151 /* L o c a l S t a t i c s */
152 /******************************************************************************/
153 
154 namespace
155 {
156 char *digParm = 0;
157 char *FSLib[2] = {0,0};
158 std::vector<std::string> FSLPath; // fslib
159 std::vector<std::string> RDLPath; // redirlib
160 std::vector<std::string> RDLParm; // redirlib
161 char *gpfLib = 0;// Normally zero for default
162 char *gpfParm = 0;
163 char *SecLib;
165 int asyncFlags = 0;
166 
167 static const int asDebug = 0x01;
168 static const int asNoCache = 0x02;
169 }
170 
171 /******************************************************************************/
172 /* C o n f i g u r e */
173 /******************************************************************************/
174 
176 {
177 /*
178  Function: Establish configuration at load time.
179 
180  Input: None.
181 
182  Output: 0 upon success or !0 otherwise.
183 */
184 
186  (XrdSfsFileSystem *nativeFS,
188  const char *configFn,
189  const char *theParms);
190 
191  XrdOucEnv xrootdEnv;
192  XrdXrootdXPath *xp;
193  char *adminp, *rdf, *bP, *tmp, buff[1024];
194  int i, n;
195 
196 // Copy out the special info we want to use at top level
197 //
198  eDest.logger(pi->eDest->logger());
200  SI = new XrdXrootdStats(pi->Stats);
201  XrdXrootd::SI= SI;
202  Sched = pi->Sched; XrdXrootd::Sched = pi->Sched;
203  BPool = pi->BPool; XrdXrootd::BPool = pi->BPool;
204  hailWait = pi->hailWait;
205  readWait = pi->readWait;
206  Port = pi->Port;
207  myInst = pi->myInst;
208  Window = pi->WSize;
209  tlsPort = pi->tlsPort;
210  tlsCtx = pi->tlsCtx;
211  XrdXrootdCF = pi->totalCF;
212 
213 // Record globally accessible values
214 //
216  XrdXrootdPort = pi->Port;
217 
218 // Set the callback object static areas now!
219 //
221 
222 // Pick up exported paths from the command line
223 //
224  for (i = 1; i < pi->argc; i++) xexpdo(pi->argv[i]);
225 
226 // Pre-initialize some i/o values. Note that we now set maximum readv element
227 // transfer size to the buffer size (before it was a reasonable 256K).
228 //
229  n = (pi->theEnv ? pi->theEnv->GetInt("MaxBuffSize") : 0);
230  maxTransz = maxBuffsz = (n ? n : BPool->MaxSize());
231  maxReadv_ior = maxTransz-(int)sizeof(readahead_list);
232 
233 // Export the readv_ior_max and readv_iov_max values
234 //
235  {char buff[256];
236  snprintf(buff, sizeof(buff), "%d,%d", maxReadv_ior, XrdProto::maxRvecsz);
237  XrdOucEnv::Export("XRD_READV_LIMITS", buff);
238  }
239 
240  memset(Route, 0, sizeof(Route));
241 
242 // Now process and configuration parameters
243 //
244  rdf = (parms && *parms ? parms : pi->ConfigFN);
245  if (rdf && Config(rdf)) return 0;
247 
248 // Initialize the packet marking framework if configured. We do that here as
249 // nothing else following this code can fail but we can so be consistent.
250 //
251  bool bad = false;
253  if (PMark)
254  {if (pi->theEnv) pi->theEnv->PutPtr("XrdNetPMark*", PMark);
255  xrootdEnv.PutPtr("XrdNetPMark*", PMark);
256  }
257  else if (bad) return 0;
258 
259 // Check if we are exporting a generic object name
260 //
261  if (XPList.Opts() & XROOTDXP_NOSLASH)
262  {eDest.Say("Config exporting ", XPList.Path(n)); n += 2;}
263  else n = 0;
264 
265 // Check if we are exporting anything
266 //
267  if (!(xp = XPList.Next()) && !n)
268  {XPList.Insert("/tmp"); n = 8;
269  eDest.Say("Config warning: only '/tmp' will be exported.");
270  } else {
271  while(xp) {eDest.Say("Config exporting ", xp->Path(i));
272  n += i+2; xp = xp->Next();
273  }
274  }
275 
276 // Export the exports
277 //
278  bP = tmp = (char *)malloc(n);
279  if (XPList.Opts() & XROOTDXP_NOSLASH)
280  {strcpy(bP, XPList.Path(i)); bP += i, *bP++ = ' ';}
281  xp = XPList.Next();
282  while(xp) {strcpy(bP, xp->Path(i)); bP += i; *bP++ = ' '; xp = xp->Next();}
283  *(bP-1) = '\0';
284  XrdOucEnv::Export("XRDEXPORTS", tmp); free(tmp);
285 
286 // Initialize the security system if this is wanted
287 //
288  if (!ConfigSecurity(xrootdEnv, pi->ConfigFN)) return 0;
289 
290 // Set up the network for self-identification and display it
291 //
292  pi->NetTCP->netIF.Port(Port);
293  pi->NetTCP->netIF.Display("Config ");
294 
295 // Establish our specific environment that will be passed along
296 //
297  xrootdEnv.PutPtr("XrdInet*", (void *)(pi->NetTCP));
298  xrootdEnv.PutPtr("XrdNetIF*", (void *)(&(pi->NetTCP->netIF)));
299  xrootdEnv.PutPtr("XrdScheduler*", Sched);
300 
301 // Copy over the xrd environment which contains plugin argv's and re-export
302 // the monitoring registration object into out own env for simplicity
303 //
304  if (pi->theEnv)
305  {xrootdEnv.PutPtr("xrdEnv*", pi->theEnv);
306  void* theMon = pi->theEnv->GetPtr("XrdMonRoll*");
307  if (theMon) xrootdEnv.PutPtr("XrdMonRoll*", theMon);
308  }
309 
310 // Initialize monitoring (it won't do anything if it wasn't enabled). This
311 // needs to be done before we load any plugins as plugins may need monitoring.
312 //
313  if (!ConfigMon(pi, xrootdEnv)) return 0;
314 
315 // Get the filesystem to be used and its features.
316 //
317  if (!ConfigFS(xrootdEnv, pi->ConfigFN)) return 0;
318  fsFeatures = osFS->Features();
320  if (pi->theEnv) pi->theEnv->PutPtr("XrdSfsFileSystem*", osFS);
321 
322 // Check if the file system includes a custom prepare handler as this will
323 // affect how we handle prepare requests.
324 //
325  if (fsFeatures & XrdSfs::hasPRP2 || xrootdEnv.Get("XRD_PrepHandler"))
326  PrepareAlt = true;
327 
328 // Check if the diglib should be loaded. We only support the builtin one. In
329 // the future we will have to change this code to be like the above.
330 //
331  if (digParm)
332  {TRACE(DEBUG, "Loading dig filesystem builtin");
333  digFS = XrdDigGetFS(osFS, eDest.logger(), pi->ConfigFN, digParm);
334  if (!digFS) eDest.Emsg("Config","Unable to load digFS; "
335  "remote debugging disabled!");
336  }
337 
338 // Check if we are going to be processing checksums locally
339 //
340  if (JobCKT) {
341  XrdOucString csList(1024);
342  XrdOucErrInfo myError("Config");
343  XrdOucTList *tP = JobCKTLST;
344  int csNum = 0;
345  do {
346  if(JobLCL) {
347  // Check natively supported checksum
348  if (osFS->chksum(XrdSfsFileSystem::csSize, tP->text, 0, myError)) {
349  eDest.Emsg("Config", tP->text, "checksum is not natively supported.");
350  return 0;
351  }
352  }
353  tP->ival[1] = myError.getErrInfo();
354  if (csNum) csList += ',';
355  csList.append(csNum);
356  csList.append(':');
357  csList.append(tP->text);
358  csNum++;
359  tP = tP->next;
360  } while (tP);
361  if (csNum) XrdOucEnv::Export("XRD_CSLIST", csList.c_str());
362  }
363 
364 // Configure the redirect plugins
365 //
366  if (!RDLPath.empty())
367  {for (int i = 0; i < (int)RDLPath.size(); i++)
368  {const char* parm = (RDLParm[i].length() ? RDLParm[i].c_str() : 0);
369  if (!ConfigRedirPI(RDLPath[i].c_str(),xrootdEnv,pi->ConfigFN,parm))
370  return 0;
371  if (pi->theEnv)
372  pi->theEnv->PutPtr("XrdXrootdRedirPI*", RedirPI);
373  }
374  }
375 
376 // Initialiaze for AIO. If we are not in debug mode and aio is enabled then we
377 // turn off async I/O if tghe filesystem requests it or if this is a caching
378 // proxy and we were asked not to use aio in such a cacse.
379 //
380  if (!(asyncFlags & asDebug) && as_aioOK)
381  {if (fsFeatures & XrdSfs::hasNAIO) as_aioOK = false;
382  else if (asyncFlags & asNoCache && fsFeatures & XrdSfs::hasCACH)
383  as_aioOK = false;
384  if (!as_aioOK) eDest.Say("Config asynchronous I/O has been disabled!");
385  }
386 
387 // Compute the maximum stutter allowed during async I/O (one per 64k)
388 //
389  if (as_segsize > 65536) as_okstutter = as_segsize/65536;
390 
391 // Establish final sendfile processing mode. This may be turned off by the
392 // link or by the SFS plugin usually because it's a proxy.
393 //
394  const char *why = 0;
395  if (!as_nosf)
396  {if (fsFeatures & XrdSfs::hasNOSF) why = "file system plugin.";
397  else if (!XrdLink::sfOK) why = "OS kernel.";
398  if (why)
399  {as_nosf = true;
400  eDest.Say("Config sendfile has been disabled by ", why);
401  }
402  }
403 
404 // Create the file lock manager and initialize file handling
405 //
408 
409 // Schedule protocol object cleanup (also advise the transit protocol)
410 //
411  ProtStack.Set(pi->Sched, &XrdXrootdTrace, TRACE_MEM);
412  n = (pi->ConnMax/3 ? pi->ConnMax/3 : 30);
413  ProtStack.Set(n, 60*60);
414  XrdXrootdTransit::Init(pi->Sched, n, 60*60);
415 
416 // Initialize the request ID generation object
417 //
418  PrepID = new XrdOucReqID(pi->urAddr, (int)Port);
419 
420 // Initialize for prepare processing
421 //
423  sprintf(buff, "%%s://%s:%d/&L=%%d&U=%%s", pi->myName, pi->Port);
424  Notify = strdup(buff);
425 
426 // Set the redirect flag if we are a pure redirector
427 //
428  int tlsFlags = myRole & kXR_tlsAny;
430  if ((rdf = getenv("XRDREDIRECT"))
431  && (!strcmp(rdf, "R") || !strcmp(rdf, "M")))
432  {isRedir = *rdf;
434  if (!strcmp(rdf, "M")) myRole |=kXR_attrMeta;
435  }
438  myRole |= tlsFlags;
439 
440 // Turn off client redirects if we are neither a redirector nor a proxy server
441 //
442  if (CL_Redir && !isRedir && !isProxy)
443  {CL_Redir = false;
444  eDest.Say("Config warning: 'redirect client' ignored; "
445  "not a redirector nor a proxy server");
446  }
447 
448 // Check if we are redirecting anything
449 //
450  if ((xp = RPList.Next()))
451  {int k;
452  char buff[2048], puff[1024];
453  do {k = xp->Opts();
454  if (Route[k].Host[0] == Route[k].Host[1]
455  && Route[k].Port[0] == Route[k].Port[1]) *puff = 0;
456  else sprintf(puff, "%%%s:%d", Route[k].Host[1], Route[k].Port[1]);
457  sprintf(buff," to %s:%d%s",Route[k].Host[0],Route[k].Port[0],puff);
458  eDest.Say("Config redirect static ", xp->Path(), buff);
459  xp = xp->Next();
460  } while(xp);
461  }
462 
463  if ((xp = RQList.Next()))
464  {int k;
465  const char *cgi1, *cgi2;
466  char buff[2048], puff[1024], xCgi[RD_Num] = {0};
467  if (isRedir) {cgi1 = "+"; cgi2 = getenv("XRDCMSCLUSTERID");}
468  else {cgi1 = ""; cgi2 = pi->myName;}
469  myCNlen = snprintf(buff, sizeof(buff), "%s%s", cgi1, cgi2);
470  myCName = strdup(buff);
471  do {k = xp->Opts();
472  if (Route[k].Host[0] == Route[k].Host[1]
473  && Route[k].Port[0] == Route[k].Port[1]) *puff = 0;
474  else sprintf(puff, "%%%s:%d", Route[k].Host[1], Route[k].Port[1]);
475  sprintf(buff," to %s:%d%s",Route[k].Host[0],Route[k].Port[0],puff);
476  eDest.Say("Config redirect enoent ", xp->Path(), buff);
477  if (!xCgi[k] && cgi2)
478  {bool isdup = Route[k].Host[0] == Route[k].Host[1]
479  && Route[k].Port[0] == Route[k].Port[1];
480  for (i = 0; i < 2; i++)
481  {n = snprintf(buff,sizeof(buff), "%s?tried=%s%s",
482  Route[k].Host[i], cgi1, cgi2);
483  free(Route[k].Host[i]); Route[k].Host[i] = strdup(buff);
484  Route[k].RDSz[i] = n;
485  if (isdup) {Route[k].Host[1] = Route[k].Host[0];
486  Route[k].RDSz[1] = n; break;
487  }
488  }
489  }
490  xCgi[k] = 1;
491  xp = xp->Next();
492  } while(xp);
493  }
494 
495 // Add all jobs that we can run to the admin object
496 //
497  if (JobCKS) XrdXrootdAdmin::addJob("chksum", JobCKS);
498 
499 // Establish the path to be used for admin functions. We will loose this
500 // storage upon an error but we don't care because we'll just exit.
501 //
502  adminp = XrdOucUtils::genPath(pi->AdmPath, 0, ".xrootd");
503 
504 // Setup the admin path (used in all roles).
505 //
506  if (!(AdminSock = XrdNetSocket::Create(&eDest, adminp, "admin", pi->AdmMode))
507  || !XrdXrootdAdmin::Init(&eDest, AdminSock)) return 0;
508 
509 // Indicate whether or not we support extended attributes
510 //
511  {XrdOucEnv myEnv;
512  XrdOucErrInfo eInfo("", &myEnv);
513  char buff[128];
514  if (osFS->FAttr(0, eInfo, 0) == SFS_OK)
515  {usxMaxNsz = myEnv.GetInt("usxMaxNsz");
516  if (usxMaxNsz < 0) usxMaxNsz = 0;
517  usxMaxVsz = myEnv.GetInt("usxMaxVsz");
518  if (usxMaxVsz < 0) usxMaxVsz = 0;
519  snprintf(buff, sizeof(buff), "%d %d", usxMaxNsz, usxMaxVsz);
520  usxParms = strdup(buff);
521  } else {
522  usxMaxNsz = 0;
523  usxMaxVsz = 0;
524  usxParms = strdup("0 0");
525  }
526  }
527 
528 // Finally, check if we really need to be in bypass mode if it is set
529 //
530  if (OD_Bypass)
531  {const char *penv = getenv("XRDXROOTD_PROXY");
532  if (!penv || *penv != '=')
533  {OD_Bypass = false;
534  eDest.Say("Config warning: 'fsoverload bypass' ignored; "
535  "not a forwarding proxy.");
536  }
537  }
538 
539 // Add any additional features
540 //
545  myRole |= kXR_anongpf;
546 
547 // Finally note whether or not we have TLS enabled
548 //
549  if (tlsCtx) myRole |= kXR_haveTLS;
550 
551 // Return success
552 //
553  free(adminp);
554  return 1;
555 }
556 
557 /******************************************************************************/
558 /* C o n f i g */
559 /******************************************************************************/
560 
561 #define TS_Xeq(x,m) (!strcmp(x,var)) GoNo = m(Config)
562 #define TS_Zeq(x,m) (!strcmp(x,var)) GoNo = m(&eDest, Config)
563 
564 int XrdXrootdProtocol::Config(const char *ConfigFN)
565 {
566  XrdOucEnv myEnv;
567  XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
568  char *var;
569  int cfgFD, GoNo, NoGo = 0, ismine;
570 
571  // Open and attach the config file
572  //
573  if ((cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
574  return eDest.Emsg("Config", errno, "open config file", ConfigFN);
575  Config.Attach(cfgFD);
576 
577  // Indicate what we are about to do in the capture stream
578  //
579  static const char *cvec[] = { "*** xroot protocol config:", 0 };
580  Config.Capture(cvec);
581 
582  // Process items
583  //
584  while((var = Config.GetMyFirstWord()))
585  { if ((ismine = !strncmp("xrootd.", var, 7)) && var[7]) var += 7;
586  else if ((ismine = !strcmp("all.export", var))) var += 4;
587  else if ((ismine = !strcmp("all.seclib", var))) var += 4;
588 
589  if (ismine)
590  { if TS_Xeq("async", xasync);
591  else if TS_Xeq("bindif", xbif);
592  else if TS_Xeq("chksum", xcksum);
593  else if TS_Xeq("diglib", xdig);
594  else if TS_Xeq("export", xexp);
595  else if TS_Xeq("fslib", xfsl);
596  else if TS_Xeq("fsoverload", xfso);
597  else if TS_Xeq("gpflib", xgpf);
598  else if TS_Xeq("log", xlog);
599  else if TS_Xeq("mongstream", xmongs);
600  else if TS_Xeq("monitor", xmon);
601  else if TS_Zeq("pmark", XrdNetPMarkCfg::Parse);
602  else if TS_Xeq("prep", xprep);
603  else if TS_Xeq("redirect", xred);
604  else if TS_Xeq("redirlib", xrdl);
605  else if TS_Xeq("seclib", xsecl);
606  else if TS_Xeq("tls", xtls);
607  else if TS_Xeq("tlsreuse", xtlsr);
608  else if TS_Xeq("trace", xtrace);
609  else if TS_Xeq("limit", xlimit);
610  else {if (!strcmp(var, "pidpath"))
611  {eDest.Say("Config warning: 'xrootd.pidpath' no longer "
612  "supported; use 'all.pidpath'.");
613  } else {
614  eDest.Say("Config warning: ignoring unknown "
615  "directive '", var, "'.");
616  }
617  Config.Echo(false);
618  continue;
619  }
620  if (GoNo) {Config.Echo(); NoGo = 1;}
621  }
622  }
623 
624 // We now have to generate the correct TLS context if one was specified. Our
625 // context must be of the non-verified kind as we don't accept certs.
626 //
627  if (!NoGo && tlsCtx)
628  {tlsCtx = tlsCtx->Clone(false,true);
629  if (!tlsCtx)
630  {eDest.Say("Config failure: unable to setup TLS for protocol!");
631  NoGo = 1;
632  } else {
633  static const char *sessID = "xroots";
634  tlsCtx->SessionCache(tlsCache, sessID, 6);
635  }
636  }
637 
638 // Add our config to our environment and return
639 //
640  return NoGo;
641 }
642 
643 /******************************************************************************/
644 /* P r i v a t e F u n c t i o n s */
645 /******************************************************************************/
646 /******************************************************************************/
647 /* C h e c k T L S */
648 /******************************************************************************/
649 
650 int XrdXrootdProtocol::CheckTLS(const char *tlsProt)
651 {
652 
653 // If login specified, turn off session as it doesn't make sense together.
654 //
658 
659 // Turn off TPC TLS requirement if login or session is required to have TLS
660 // However, that flag must remain to be set in the protocol response.
661 //
664 
665 // If some authnetication protocols need TLS then we must requie that login
666 // uses TLS. For incapable clients, we leave this alone as we will skip
667 // TLS authnetication based protocols should the login phase not have TLS.
668 //
669  if (tlsProt && !(tlsCap & Req_TLSLogin))
670  {eDest.Say("Config Authentication protocol(s)", tlsProt,
671  " require TLS; login now requires TLS.");
672  myRole |= kXR_tlsLogin;
673  tlsCap |= Req_TLSLogin;
674  }
675 
676 // If there are any TLS requirements then TLS must have been configured.
677 //
678  if (myRole & kXR_tlsAny && !tlsCtx)
679  {eDest.Say("Config failure: unable to honor TLS requirement; "
680  "TLS not configured!");
681  return 0;
682  }
683 
684 // All done
685 //
686  return 1;
687 }
688 
689 /******************************************************************************/
690 /* C o n f i g F S */
691 /******************************************************************************/
692 
693 bool XrdXrootdProtocol::ConfigFS(XrdOucEnv &xEnv, const char *cfn)
694 {
695  const char *fsLoc;
696  int n;
697 
698 // Get the filesystem to be used
699 //
700  if (FSLib[0])
701  {TRACE(DEBUG, "Loading base filesystem library " <<FSLib[0]);
702  osFS = XrdXrootdloadFileSystem(&eDest, 0, FSLib[0], cfn, &xEnv);
703  fsLoc = FSLib[0];
704  } else {
705  osFS = XrdSfsGetDefaultFileSystem(0, eDest.logger(), cfn, &xEnv);
706  fsLoc = "default";
707  }
708 
709 // Make sure we have loaded something
710 //
711  if (!osFS)
712  {eDest.Emsg("Config", "Unable to load base file system using", fsLoc);
713  return false;
714  }
715  if (FSLib[0]) osFS->EnvInfo(&xEnv);
716 
717 // If there is an old style wrapper, load it now.
718 //
719  if (FSLib[1] && !ConfigFS(FSLib[1], xEnv, cfn)) return false;
720 
721 // Run through any other pushdowns
722 //
723  if ((n = FSLPath.size()))
724  for (int i = 0; i < n; i++)
725  {if (!ConfigFS(FSLPath[i].c_str(), xEnv, cfn)) return false;}
726 
727 // Inform the statistics object which filesystem to use
728 //
729  SI->setFS(osFS);
730 
731 // All done here
732 //
733  return true;
734 }
735 
736 /******************************************************************************/
737 
738 bool XrdXrootdProtocol::ConfigFS(const char *path, XrdOucEnv &xEnv,
739  const char *cfn)
740 {
741 
742 // Try to load this wrapper library
743 //
744  TRACE(DEBUG, "Loading wrapper filesystem library " <<path);
745  osFS = XrdXrootdloadFileSystem(&eDest, osFS, path, cfn, &xEnv);
746  if (!osFS)
747  {eDest.Emsg("Config", "Unable to load file system wrapper from", path);
748  return false;
749  }
750  osFS->EnvInfo(&xEnv);
751  return true;
752 }
753 
754 /******************************************************************************/
755 /* C o n f i g R e d i r P I */
756 /******************************************************************************/
757 
758 bool XrdXrootdProtocol::ConfigRedirPI(const char *path, XrdOucEnv &xEnv,
759  const char *cfn, const char *parms)
760 {
761 
762 // Try to load this wrapper library
763 //
764  TRACE(DEBUG, "Loading redirect plugin library " <<path);
765  RedirPI = XrdXrootdloadRedirLib(&eDest, RedirPI, path, parms, cfn, &xEnv);
766  return RedirPI != 0;
767 }
768 
769 /******************************************************************************/
770 /* C o n f i g S e c u r i t y */
771 /******************************************************************************/
772 
773 int XrdXrootdProtocol::ConfigSecurity(XrdOucEnv &xEnv, const char *cfn)
774 {
775  XrdSecGetProt_t secGetProt = 0;
776  char idBuff[256];
777  int n;
778 
779 // Obtain our uid and username
780 //
781  myUID = geteuid();
782  if ((n = XrdOucUtils::UidName(myUID, idBuff, sizeof(idBuff))))
783  {myUName = strdup(idBuff);
784  myUNLen = n;
785  }
786 
787 // Obtain our gid and groupname
788 //
789  myGID = getegid();
790  if ((n = XrdOucUtils::GidName(myGID, idBuff, sizeof(idBuff))))
791  {myGName = strdup(idBuff);
792  myGNLen = n;
793  }
794 
795 // TLS support is independent of security per se. Record context, if any.
796 //
797  if (tlsCtx) xEnv.PutPtr("XrdTLSContext*", (void *)tlsCtx);
798 
799 // Check if we need to load anything
800 //
801  if (!SecLib)
802  {eDest.Say("Config warning: 'xrootd.seclib' not specified;"
803  " strong authentication disabled!");
804  xEnv.PutPtr("XrdSecGetProtocol*", (void *)0);
805  xEnv.PutPtr("XrdSecProtector*" , (void *)0);
806  return 1;
807  }
808 
809 // Blad some debugging info
810 //
811  TRACE(DEBUG, "Loading security library " <<SecLib);
812 
813 // Load the security server
814 //
815  if (!(CIA = XrdSecLoadSecService(&eDest, cfn,
816  (strcmp(SecLib,"default") ? SecLib : 0),
817  &secGetProt, &DHS)))
818  {eDest.Emsg("Config", "Unable to load security system.");
819  return 0;
820  }
821 
822 // Set environmental pointers
823 //
824  xEnv.PutPtr("XrdSecGetProtocol*", (void *)secGetProt);
825  xEnv.PutPtr("XrdSecProtector*" , (void *)DHS);
826 
827 // If any protocol needs TLS then all logins must use TLS, ufortunately.
828 //
829  const char *tlsProt = CIA->protTLS();
830  if (tlsProt) return CheckTLS(tlsProt);
831  return 1;
832 }
833 
834 /******************************************************************************/
835 /* x a s y n c */
836 /******************************************************************************/
837 
838 /* Function: xasync
839 
840  Purpose: To parse directive: async [limit <aiopl>] [maxsegs <msegs>]
841  [maxtot <mtot>] [segsize <segsize>]
842  [minsize <iosz>] [maxstalls <cnt>]
843  [timeout <tos>]
844  [Debug] [force] [syncw] [off]
845  [nocache] [nosf]
846 
847  <aiopl> maximum number of async req per link. Default 8.
848  <msegs> maximum number of async ops per request. Default 8.
849  <mtot> maximum number of async ops per server. Default is 4096.
850  of maximum connection times aiopl divided by two.
851  <segsz> The aio segment size. This is the maximum size that data
852  will be read or written. The defaults to 64K but is
853  adjusted for each request to minimize latency.
854  <iosz> the minimum number of bytes that must be read or written
855  to allow async processing to occur (default is maxbsz/2
856  typically 1M).
857  <tos> second timeout for async I/O.
858  <cnt> Maximum number of client stalls before synchronous i/o is
859  used. Async mode is tried after <cnt> requests.
860  Debug Turns on async I/O for everything. This an internal
861  undocumented option used for testing purposes.
862  force Uses async i/o for all requests, even when not explicitly
863  requested (this is compatible with synchronous clients).
864  syncw Use synchronous i/o for write requests.
865  off Disables async i/o
866  nocache Disables async I/O is this is a caching proxy.
867  nosf Disables use of sendfile to send data to the client.
868 
869  Output: 0 upon success or 1 upon failure.
870 */
871 
872 int XrdXrootdProtocol::xasync(XrdOucStream &Config)
873 {
874  char *val;
875  int i, ppp;
876  int V_force=-1, V_syncw = -1, V_off = -1, V_mstall = -1, V_nosf = -1;
877  int V_limit=-1, V_msegs=-1, V_mtot=-1, V_minsz=-1, V_segsz=-1;
878  int V_minsf=-1, V_debug=-1, V_noca=-1, V_tmo=-1;
879  long long llp;
880  struct asyncopts {const char *opname; int minv; int *oploc;
881  const char *opmsg;} asopts[] =
882  {
883  {"Debug", -1, &V_debug, ""},
884  {"force", -1, &V_force, ""},
885  {"off", -1, &V_off, ""},
886  {"nocache", -1, &V_noca, ""},
887  {"nosf", -1, &V_nosf, ""},
888  {"syncw", -1, &V_syncw, ""},
889  {"limit", 0, &V_limit, "async limit"},
890  {"segsize", 4096, &V_segsz, "async segsize"},
891  {"timeout", 0, &V_tmo, "async timeout"},
892  {"maxsegs", 0, &V_msegs, "async maxsegs"},
893  {"maxstalls", 0, &V_mstall,"async maxstalls"},
894  {"maxtot", 0, &V_mtot, "async maxtot"},
895  {"minsfsz", 1, &V_minsf, "async minsfsz"},
896  {"minsize", 4096, &V_minsz, "async minsize"}};
897  int numopts = sizeof(asopts)/sizeof(struct asyncopts);
898 
899  if (!(val = Config.GetWord()))
900  {eDest.Emsg("Config", "async option not specified"); return 1;}
901 
902  while (val)
903  {for (i = 0; i < numopts; i++)
904  if (!strcmp(val, asopts[i].opname))
905  {if (asopts[i].minv >= 0 && !(val = Config.GetWord()))
906  {eDest.Emsg("Config","async",(char *)asopts[i].opname,
907  "value not specified");
908  return 1;
909  }
910  if (asopts[i].minv > 0)
911  if (XrdOuca2x::a2sz(eDest,asopts[i].opmsg, val, &llp,
912  (long long)asopts[i].minv)) return 1;
913  else *asopts[i].oploc = (int)llp;
914  else if (asopts[i].minv == 0)
915  if (XrdOuca2x::a2i(eDest,asopts[i].opmsg,val,&ppp,1))
916  return 1;
917  else *asopts[i].oploc = ppp;
918  else *asopts[i].oploc = 1;
919  break;
920  }
921  if (i >= numopts)
922  eDest.Emsg("Config", "Warning, invalid async option", val);
923  val = Config.GetWord();
924  }
925 
926 // Make sure max values are consistent
927 //
928  if (V_limit > 0 && V_mtot > 0 && V_limit > V_mtot)
929  {eDest.Emsg("Config", "async limit may not be greater than maxtot");
930  return 1;
931  }
932 
933 // Calculate the actual segment size
934 //
935  if (V_segsz > 0)
936  {i = BPool->Recalc(V_segsz);
937  if (!i) {eDest.Emsg("Config", "async segsize is too large"); return 1;}
938  if (i != V_segsz)
939  {char buff[64];
940  sprintf(buff, "%d readjusted to %d", V_segsz, i);
941  eDest.Emsg("Config", "async segsize", buff);
942  V_segsz = i;
943  }
944  }
945 
946 // Calculate actual timeout
947 //
948  if (V_tmo >= 0)
949  {i = V_tmo;
950  if (V_tmo < 1) i = 1;
951  else if (V_tmo > 360) i = 360;
952  if (i != V_tmo)
953  {char buff[64];
954  sprintf(buff, "%d readjusted to %d", V_tmo, i);
955  eDest.Emsg("Config", "async timeout", buff);
956  V_tmo = i;
957  }
958  }
959 
960 // Establish async options
961 //
962  if (V_limit > 0) as_maxperlnk = V_limit;
963  if (V_msegs > 0) as_maxperreq = V_msegs;
964  if (V_mtot > 0) as_maxpersrv = V_mtot;
965  if (V_minsz > 0) as_miniosz = V_minsz;
966  if (V_segsz > 0){as_segsize = V_segsz; as_seghalf = V_segsz/2;}
967  if (V_tmo >= 0) as_timeout = V_tmo;
968  if (V_mstall> 0) as_maxstalls = V_mstall;
969  if (V_debug > 0) asyncFlags |= asDebug;
970  if (V_force > 0) as_force = true;
971  if (V_off > 0) as_aioOK = false;
972  if (V_syncw > 0) as_syncw = true;
973  if (V_noca > 0) asyncFlags |= asNoCache;
974  if (V_nosf > 0) as_nosf = true;
975  if (V_minsf > 0) as_minsfsz = V_minsf;
976 
977  return 0;
978 }
979 
980 /******************************************************************************/
981 /* x b i f */
982 /******************************************************************************/
983 
984 /* Function: xbif
985 
986  Purpose: To parse the directive: bindif <trg>
987 
988  <trg>: <host>:<port>[%<prvhost>:<port>]] [<trg>]
989 */
990 
991 namespace XrdXrootd
992 {
993 char *bifResp[2] = {0,0};
994 int bifRLen[2] = {0,0};
995 }
996 
997 int XrdXrootdProtocol::xbif(XrdOucStream &Config)
998 {
999  static const int brSize = sizeof(XrdProto::bifReqs);
1000  using XrdXrootd::bifResp;
1001  using XrdXrootd::bifRLen;
1002 
1003  XrdOucString bSpec[2];
1004  char *bHost[2], *val, buff[512];
1005  int bPort[2], thePort;
1006 
1007 // Cleanup any previous bif specification
1008 //
1009  if (bifResp[1])
1010  {if (bifResp[1] != bifResp[0]) free(bifResp[1]);
1011  bifResp[1] = 0; bifRLen[1] = 0;
1012  }
1013  if (bifResp[0])
1014  {free(bifResp[0]);
1015  bifResp[0] = 0; bifRLen[0] = 0;
1016  }
1017 
1018 // Process all of the options
1019 //
1020  while((val = Config.GetWord()) && *val)
1021  {if (!xred_php(val, bHost, bPort, "bindif", true)) return 1;
1022  for (int i = 0; i < 2 && bHost[i] != 0; i++)
1023  {thePort = (bPort[i] ? bPort[i] : XrdXrootdPort);
1024  snprintf(buff, sizeof(buff), "%s%s:%d",
1025  (bSpec[i].length() ? "," : ""), bHost[i], thePort);
1026  bSpec[i] += buff;
1027  }
1028  }
1029 
1030 // Generate the "b" record for each type of interface
1031 //
1032  for (int i = 0; i < 2 && bSpec[i].length(); i++)
1033  {int n = brSize + bSpec[i].length() + 1;
1034  n = (n + 7) & ~7;
1035  XrdProto::bifReqs *bifRec = (XrdProto::bifReqs *)malloc(n);
1036  memset(bifRec, 0, n);
1037  bifRec->theTag = 'B';
1038  bifRec->bifILen = htons(static_cast<kXR_unt16>(n-brSize));
1039  strcpy(((char *)bifRec)+brSize, bSpec[i].c_str());
1040  bifResp[i] = (char *)bifRec;
1041  bifRLen[i] = n;
1042  }
1043 
1044 // Now complete the definition
1045 //
1046  if (bifResp[0] && bifResp[1] == 0)
1047  {bifResp[1] = bifResp[0];
1048  bifRLen[1] = bifRLen[0];
1049  }
1050 
1051 // All done
1052 //
1053  return 0;
1054 }
1055 
1056 /******************************************************************************/
1057 /* x c k s u m */
1058 /******************************************************************************/
1059 
1060 /* Function: xcksum
1061 
1062  Purpose: To parse the directive: chksum [chkcgi] [max <n>] <type> [<path>]
1063 
1064  max maximum number of simultaneous jobs
1065  chkcgi Always check for checksum type in cgo info.
1066  <type> algorithm of checksum (e.g., md5). If more than one
1067  checksum is supported then they should be listed with
1068  each separated by a space.
1069  <path> the path of the program performing the checksum
1070  If no path is given, the checksum is local.
1071 
1072  Output: 0 upon success or !0 upon failure.
1073 */
1074 
1075 int XrdXrootdProtocol::xcksum(XrdOucStream &Config)
1076 {
1077  static XrdOucProg *theProg = 0;
1078  int (*Proc)(XrdOucStream *, char **, int) = 0;
1079  XrdOucTList *tP, *algFirst = 0, *algLast = 0;
1080  char *palg, prog[2048];
1081  int jmax = 4, anum[2] = {0,0};
1082 
1083 // Get the algorithm name and the program implementing it
1084 //
1085  JobCKCGI = 0;
1086  while ((palg = Config.GetWord()) && *palg != '/')
1087  {if (!strcmp(palg,"chkcgi")) {JobCKCGI = 1; continue;}
1088  if (strcmp(palg, "max"))
1089  {XrdOucUtils::toLower(palg);
1090  XrdOucTList *xalg = new XrdOucTList(palg, anum); anum[0]++;
1091  if (algLast) algLast->next = xalg;
1092  else algFirst = xalg;
1093  algLast = xalg;
1094  continue;
1095  }
1096  if (!(palg = Config.GetWord()))
1097  {eDest.Emsg("Config", "chksum max not specified"); return 1;}
1098  if (XrdOuca2x::a2i(eDest, "chksum max", palg, &jmax, 0)) return 1;
1099  }
1100 
1101 // Verify we have an algoritm
1102 //
1103  if (!algFirst)
1104  {eDest.Emsg("Config", "chksum algorithm not specified"); return 1;}
1105  if (JobCKT) free(JobCKT);
1106  JobCKT = strdup(algFirst->text);
1107 
1108 // Handle alternate checksums
1109 //
1110  while((tP = JobCKTLST)) {JobCKTLST = tP->next; delete tP;}
1111  JobCKTLST = algFirst;
1112  if (algFirst->next) JobCKCGI = 2;
1113 
1114 // Handle program if we have one
1115 //
1116  if (palg)
1117  {int n = strlen(palg);
1118  if (n+2 >= (int)sizeof(prog))
1119  {eDest.Emsg("Config", "cksum program too long"); return 1;}
1120  strcpy(prog, palg); palg = prog+n; *palg++ = ' '; n = sizeof(prog)-n-1;
1121  if (!Config.GetRest(palg, n))
1122  {eDest.Emsg("Config", "cksum parameters too long"); return 1;}
1123  } else *prog = 0;
1124 
1125 // Check if we have a program. If not, then this will be a local checksum and
1126 // the algorithm will be verified after we load the filesystem.
1127 //
1128  if (*prog) JobLCL = 0;
1129  else { JobLCL = 1; Proc = &CheckSum; strcpy(prog, "chksum");}
1130 
1131 // Set up the program and job
1132 //
1133  if (!theProg) theProg = new XrdOucProg(0);
1134  if (theProg->Setup(prog, &eDest, Proc)) return 1;
1135  if (JobCKS) delete JobCKS;
1136  if (jmax) JobCKS = new XrdXrootdJob(Sched, theProg, "chksum", jmax);
1137  else JobCKS = 0;
1138  return 0;
1139 }
1140 
1141 /******************************************************************************/
1142 /* x d i g */
1143 /******************************************************************************/
1144 
1145 /* Function: xdig
1146 
1147  Purpose: To parse the directive: diglib * <parms>
1148 
1149  * use builtin digfs library (only one supported now).
1150  parms parameters for digfs.
1151 
1152  Output: 0 upon success or !0 upon failure.
1153 */
1154 
1155 int XrdXrootdProtocol::xdig(XrdOucStream &Config)
1156 {
1157  char parms[4096], *val;
1158 
1159 // Get the path
1160 //
1161  if (!(val = Config.GetWord()))
1162  {eDest.Emsg("Config", "diglib not specified"); return 1;}
1163 
1164 // Make sure it refers to an internal one
1165 //
1166  if (strcmp(val, "*"))
1167  {eDest.Emsg("Config", "builtin diglib not specified"); return 1;}
1168 
1169 // Grab the parameters
1170 //
1171  if (!Config.GetRest(parms, sizeof(parms)))
1172  {eDest.Emsg("Config", "diglib parameters too long"); return 1;}
1173  if (digParm) free(digParm);
1174  digParm = strdup(parms);
1175 
1176 // All done
1177 //
1178  return 0;
1179 }
1180 
1181 /******************************************************************************/
1182 /* x e x p */
1183 /******************************************************************************/
1184 
1185 /* Function: xexp
1186 
1187  Purpose: To parse the directive: export <path> [lock|nolock] [mwfiles]
1188 
1189  <path> the path to be exported.
1190 
1191  Output: 0 upon success or !0 upon failure.
1192 */
1193 
1194 int XrdXrootdProtocol::xexp(XrdOucStream &Config)
1195 {
1196  char *val, pbuff[1024];
1197  int popt = 0;
1198 
1199 // Get the path
1200 //
1201  val = Config.GetWord();
1202  if (!val || !val[0])
1203  {eDest.Emsg("Config", "export path not specified"); return 1;}
1204  strlcpy(pbuff, val, sizeof(pbuff));
1205 
1206 // Get export lock option
1207 //
1208  while((val = Config.GetWord()))
1209  { if (!strcmp( "nolock", val)) popt |= XROOTDXP_NOLK;
1210  else if (!strcmp( "lock", val)) popt &= ~XROOTDXP_NOLK;
1211  else if (!strcmp("mwfiles", val)) popt |= XROOTDXP_NOMWCHK;
1212  else {Config.RetToken(); break;}
1213  }
1214 
1215 // Add path to configuration
1216 //
1217  return xexpdo(pbuff, popt);
1218 }
1219 
1220 /******************************************************************************/
1221 
1222 int XrdXrootdProtocol::xexpdo(char *path, int popt)
1223 {
1224  char *opaque;
1225  int xopt;
1226 
1227 // Check if we are exporting a generic name
1228 //
1229  if (*path == '*')
1230  {popt |= XROOTDXP_NOSLASH | XROOTDXP_NOCGI;
1231  if (*(path+1))
1232  {if (*(path+1) == '?') popt &= ~XROOTDXP_NOCGI;
1233  else {eDest.Emsg("Config","invalid export path -",path);return 1;}
1234  }
1235  XPList.Set(popt, path);
1236  return 0;
1237  }
1238 
1239 // Make sure path start with a slash
1240 //
1241  if (rpCheck(path, &opaque))
1242  {eDest.Emsg("Config", "non-absolute export path -", path); return 1;}
1243 
1244 // Record the path
1245 //
1246  if (!(xopt = Squash(path)) || xopt != (popt|XROOTDXP_OK))
1247  XPList.Insert(path, popt);
1248  return 0;
1249 }
1250 
1251 /******************************************************************************/
1252 /* x f s l */
1253 /******************************************************************************/
1254 
1255 /* Function: xfsl
1256 
1257  Purpose: To parse the directive: fslib [throttle | [-2] <fspath2>]
1258  {default | [-2] <fspath1>}
1259  | ++ <fspath2>
1260 
1261  -2 Uses version2 of the plugin initializer.
1262  This is ignored now because it's always done.
1263  ++ Pushes a wrapper onto the library stack.
1264  throttle load libXrdThrottle.so as the head interface.
1265  <fspath2> load the named library as the head interface.
1266  default load libXrdOfs.so ro libXrdPss.so as the tail
1267  interface. This is the default.
1268  <fspath1> load the named library as the tail interface.
1269 
1270  Output: 0 upon success or !0 upon failure.
1271 */
1272 
1273 int XrdXrootdProtocol::xfsl(XrdOucStream &Config)
1274 {
1275  char *val;
1276 
1277 // Get the path
1278 //
1279  if (!(val = Config.GetWord()))
1280  {eDest.Emsg("Config", "fslib not specified"); return 1;}
1281 
1282 // First check for a psuhdown
1283 //
1284  if (!strcmp("++", val))
1285  {if (!(val = Config.GetWord()))
1286  {eDest.Emsg("Config", "fslib wrapper not specified"); return 1;}
1287  if (strcmp("throttle", val)) FSLPath.push_back((std::string)val);
1288  else FSLPath.push_back("libXrdThrottle.so");
1289  return 0;
1290  }
1291 
1292 // Clear storage pointers
1293 //
1294  if (FSLib[0]) {free(FSLib[0]); FSLib[0] = 0;}
1295  if (FSLib[1]) {free(FSLib[1]); FSLib[1] = 0;}
1296 
1297 // Check if this is "thottle"
1298 //
1299  if (!strcmp("throttle", val))
1300  {FSLib[1] = strdup("libXrdThrottle.so");
1301  if (!(val = Config.GetWord()))
1302  {eDest.Emsg("Config","fslib throttle target library not specified");
1303  return 1;
1304  }
1305  return xfsL(Config, val, 0);
1306  }
1307 
1308 // Check for default or default library, the common case
1309 //
1310  if (xfsL(Config, val, 1)) return 1;
1311  if (!FSLib[1]) return 0;
1312 
1313 // If we dont have another token, then demote the previous library
1314 //
1315  if (!(val = Config.GetWord()))
1316  {FSLib[0] = FSLib[1]; FSLib[1] = 0;
1317  return 0;
1318  }
1319 
1320 // Check for default or default library, the common case
1321 //
1322  return xfsL(Config, val, 0);
1323 }
1324 
1325 /******************************************************************************/
1326 
1327 int XrdXrootdProtocol::xfsL(XrdOucStream &Config, char *val, int lix)
1328 {
1329  char *Slash;
1330 
1331 // Check if this is a version token
1332 //
1333  if (!strcmp(val, "-2"))
1334  {if (!(val = Config.GetWord()))
1335  {eDest.Emsg("Config", "fslib not specified"); return 1;}
1336  }
1337 
1338 // We will play fast and furious with the syntax as "default" should not be
1339 // prefixed with a version number but will let that pass.
1340 //
1341  if (!strcmp("default", val)) return 0;
1342 
1343 // If this is the "standard" name tell the user that we are ignoring this lib.
1344 // Otherwise, record the path and return.
1345 //
1346  if (!(Slash = rindex(val, '/'))) Slash = val;
1347  else Slash++;
1348  if (!strcmp(Slash, "libXrdOfs.so"))
1349  eDest.Say("Config warning: 'fslib libXrdOfs.so' is actually built-in.");
1350  else FSLib[lix] = strdup(val);
1351  return 0;
1352 }
1353 
1354 /******************************************************************************/
1355 /* x f s o */
1356 /******************************************************************************/
1357 
1358 /* Function: xfso
1359 
1360  Purpose: To parse the directive: fsoverload [options]
1361 
1362  options: [[no]bypass] [redirect <host>:<port>[%<prvhost>:<port>]]
1363  [stall <sec>]
1364 
1365  bypass If path is a forwarding path, redirect client to the
1366  location specified in the path to bypass this server.
1367  The default is nobypass.
1368  redirect Redirect the request to the specified destination.
1369  stall Stall the client <sec> seconds. The default is 33.
1370 */
1371 
1372 int XrdXrootdProtocol::xfso(XrdOucStream &Config)
1373 {
1374  static const int rHLen = 264;
1375  char rHost[2][rHLen], *hP[2] = {0,0}, *val;
1376  int rPort[2], bypass = -1, stall = -1;
1377 
1378 // Process all of the options
1379 //
1380  while((val = Config.GetWord()) && *val)
1381  { if (!strcmp(val, "bypass")) bypass = 1;
1382  else if (!strcmp(val, "nobypass")) bypass = 0;
1383  else if (!strcmp(val, "redirect"))
1384  {val = Config.GetWord();
1385  if (!xred_php(val, hP, rPort, "redirect")) return 1;
1386  for (int i = 0; i < 2; i++)
1387  {if (!hP[i]) rHost[i][0] = 0;
1388  else {strlcpy(rHost[i], hP[i], rHLen);
1389  hP[i] = rHost[i];
1390  }
1391  }
1392  }
1393  else if (!strcmp(val, "stall"))
1394  {if (!(val = Config.GetWord()) || !(*val))
1395  {eDest.Emsg("Config", "stall value not specified");
1396  return 1;
1397  }
1398  if (XrdOuca2x::a2tm(eDest,"stall",val,&stall,0,32767))
1399  return 1;
1400  }
1401  else {eDest.Emsg("config","invalid fsoverload option",val); return 1;}
1402  }
1403 
1404 // Set all specified values
1405 //
1406  if (bypass >= 0) OD_Bypass = (bypass ? true : false);
1407  if (stall >= 0) OD_Stall = stall;
1408  if (hP[0])
1409  {if (Route[RD_ovld].Host[0]) free(Route[RD_ovld].Host[0]);
1410  if (Route[RD_ovld].Host[1]) free(Route[RD_ovld].Host[1]);
1411  Route[RD_ovld].Host[0] = strdup(hP[0]);
1412  Route[RD_ovld].Port[0] = rPort[0];
1413  Route[RD_ovld].RDSz[0] = strlen(hP[0]);
1414  if (hP[1])
1415  {Route[RD_ovld].Host[1] = strdup(hP[1]);
1416  Route[RD_ovld].Port[1] = rPort[1];
1417  Route[RD_ovld].RDSz[1] = strlen(hP[1]);
1418  } else {
1419  Route[RD_ovld].Host[1] = Route[RD_ovld].Host[0];
1420  Route[RD_ovld].Port[1] = Route[RD_ovld].Port[0];
1421  Route[RD_ovld].RDSz[1] = Route[RD_ovld].RDSz[0];
1422  }
1423  OD_Redir = true;
1424  } else OD_Redir = false;
1425 
1426  return 0;
1427 }
1428 
1429 /******************************************************************************/
1430 /* x g p f */
1431 /******************************************************************************/
1432 
1433 /* Function: xgpf
1434 
1435  Purpose: To parse the directive: gpflib <path> <parms>
1436 
1437  <path> library path to use or default to use the builtin one.
1438  parms optional parameters.
1439 
1440  Output: 0 upon success or !0 upon failure.
1441 */
1442 
1443 int XrdXrootdProtocol::xgpf(XrdOucStream &Config)
1444 {
1445  char parms[4096], *val;
1446 
1447 // Remove any previous parameters
1448 //
1449  if (gpfLib) {free(gpfLib); gpfLib = 0;}
1450  if (gpfParm) {free(gpfParm); gpfParm = 0;}
1451 
1452 // Get the path
1453 //
1454  if (!(val = Config.GetWord()))
1455  {eDest.Emsg("Config", "gpflib not specified"); return 1;}
1456 
1457 // If this refers to out default, then keep the library pointer nil
1458 //
1459  if (strcmp(val, "default")) gpfLib = strdup(val);
1460 
1461 // Grab the parameters
1462 //
1463  if (!Config.GetRest(parms, sizeof(parms)))
1464  {eDest.Emsg("Config", "gpflib parameters too long"); return 1;}
1465  gpfParm = strdup(parms);
1466 
1467 // All done
1468 //
1469  return 0;
1470 }
1471 
1472 /******************************************************************************/
1473 /* x l o g */
1474 /******************************************************************************/
1475 
1476 /* Function: xlog
1477 
1478  Purpose: To parse the directive: log <events>
1479 
1480  <events> the blank separated list of events to log.
1481 
1482  Output: 0 upon success or 1 upon failure.
1483 */
1484 
1485 int XrdXrootdProtocol::xlog(XrdOucStream &Config)
1486 {
1487  char *val;
1488  static struct logopts {const char *opname; int opval;} lgopts[] =
1489  {
1490  {"all", -1},
1491  {"disc", SYS_LOG_02},
1492  {"login", SYS_LOG_01}
1493  };
1494  int i, neg, lgval = -1, numopts = sizeof(lgopts)/sizeof(struct logopts);
1495 
1496  if (!(val = Config.GetWord()))
1497  {eDest.Emsg("config", "log option not specified"); return 1;}
1498  while (val)
1499  {if ((neg = (val[0] == '-' && val[1]))) val++;
1500  for (i = 0; i < numopts; i++)
1501  {if (!strcmp(val, lgopts[i].opname))
1502  {if (neg) lgval &= ~lgopts[i].opval;
1503  else lgval |= lgopts[i].opval;
1504  break;
1505  }
1506  }
1507  if (i >= numopts) eDest.Emsg("config","invalid log option",val);
1508  val = Config.GetWord();
1509  }
1510  eDest.setMsgMask(lgval);
1511  return 0;
1512 }
1513 
1514 /******************************************************************************/
1515 /* x p r e p */
1516 /******************************************************************************/
1517 
1518 /* Function: xprep
1519 
1520  Purpose: To parse the directive: prep [keep <sec>] [scrub <sec>]
1521  [logdir <path>]
1522  keep <sec> time (seconds, M, H) to keep logdir entries.
1523  scrub <sec> time (seconds, M, H) between logdir scrubs.
1524  logdir <path> the absolute path to the prepare log directory.
1525 
1526  Output: 0 upon success or !0 upon failure. Ignored by master.
1527 */
1528 int XrdXrootdProtocol::xprep(XrdOucStream &Config)
1529 { int rc, keep = 0, scrub=0;
1530  char *ldir=0,*val,buff[1024];
1531 
1532  if (!(val = Config.GetWord()))
1533  {eDest.Emsg("Config", "prep options not specified"); return 1;}
1534 
1535  do { if (!strcmp("keep", val))
1536  {if (!(val = Config.GetWord()))
1537  {eDest.Emsg("Config", "prep keep value not specified");
1538  return 1;
1539  }
1540  if (XrdOuca2x::a2tm(eDest,"prep keep int",val,&keep,1)) return 1;
1541  }
1542  else if (!strcmp("scrub", val))
1543  {if (!(val = Config.GetWord()))
1544  {eDest.Emsg("Config", "prep scrub value not specified");
1545  return 1;
1546  }
1547  if (XrdOuca2x::a2tm(eDest,"prep scrub",val,&scrub,0)) return 1;
1548  }
1549  else if (!strcmp("logdir", val))
1550  {if (!(ldir = Config.GetWord()))
1551  {eDest.Emsg("Config", "prep logdir value not specified");
1552  return 1;
1553  }
1554  }
1555  else eDest.Emsg("Config", "Warning, invalid prep option", val);
1556  } while((val = Config.GetWord()));
1557 
1558 // Set the values
1559 //
1560  if (scrub || keep) XrdXrootdPrepare::setParms(scrub, keep);
1561  if (ldir)
1562  if ((rc = XrdOucUtils::genPath(buff, sizeof(buff), ldir, myInst)) < 0
1563  || (rc = XrdOucUtils::makePath(buff, XrdOucUtils::pathMode)) < 0
1564  || (rc = XrdXrootdPrepare::setParms(buff)) < 0)
1565  {eDest.Emsg("Config", rc, "process logdir", ldir);
1566  return 1;
1567  }
1568  return 0;
1569 }
1570 
1571 /******************************************************************************/
1572 /* x r d l */
1573 /******************************************************************************/
1574 
1575 /* Function: xrdl
1576 
1577  Purpose: To parse the directive: redirlib [++] [<opts>] <libpath> [<parm>]
1578 
1579  ++ Pushes a wrapper onto the library stack.
1580  <opts> Options:
1581  +iphold <time>
1582  <libpath> load the named library as the head interface.
1583  <parms> optional parameters
1584 
1585  Output: 0 upon success or !0 upon failure.
1586 */
1587 
1588 int XrdXrootdProtocol::xrdl(XrdOucStream &Config)
1589 {
1590  char *val;
1591  char pbuff[4096];
1592 
1593 // Get the path
1594 //
1595  if (!(val = Config.GetWord()))
1596  {eDest.Emsg("Config", "redirlib path not specified"); return 1;}
1597 
1598 // First check for a psuhdown
1599 //
1600  if (!strcmp("++", val))
1601  {if (!(val = Config.GetWord()))
1602  {eDest.Emsg("Config", "redrilib wrapper not specified"); return 1;}
1603  if (RDLPath.empty())
1604  {eDest.Emsg("Config", "base redrilib not specified"); return 1;}
1605  if (*val == '+' && !(val = xrdlopt(Config, val))) return 1;
1606  RDLPath.push_back((std::string)val);
1607  if (!Config.GetRest(pbuff, sizeof(pbuff)))
1608  {eDest.Emsg("Config", "redirlib parameters too long"); return 1;}
1609  RDLParm.push_back((std::string)pbuff);
1610  return 0;
1611  } else if (*val == '+' && !(val = xrdlopt(Config, val))) return 1;
1612 
1613 // This is either a base library specification or a replacement
1614 //
1615  if (RDLPath.empty()) RDLPath.push_back((std::string)val);
1616  else RDLPath[0] = val;
1617 
1618 // Get the optional parameters
1619 //
1620  if (!Config.GetRest(pbuff, sizeof(pbuff)))
1621  {eDest.Emsg("Config", "redirlib parameters too long"); return 1;}
1622  if (RDLParm.empty()) RDLParm.push_back((std::string)pbuff);
1623  else RDLParm[0] = pbuff;
1624 
1625 // All done
1626 //
1627  return 0;
1628 }
1629 
1630 /******************************************************************************/
1631 /* x r d r o p t */
1632 /******************************************************************************/
1633 
1634 char* XrdXrootdProtocol::xrdlopt(XrdOucStream &Config, char* val)
1635 {
1636  int num;
1637 
1638 // Check for valid options
1639 //
1640 do{if (!strcmp(val, "+iphold"))
1641  {if (!(val = Config.GetWord()))
1642  {eDest.Emsg("Config", "+iphold value not specified"); return 0;}
1643  if (XrdOuca2x::a2tm(eDest,"redirlib iphold",val,&num,0)) return 0;
1644  redirIPHold = num;
1645  }
1646  } while((val = Config.GetWord()) && *val == '+');
1647 
1648 // All done
1649 //
1650  return val;
1651 }
1652 
1653 /******************************************************************************/
1654 /* x r e d */
1655 /******************************************************************************/
1656 
1657 /* Function: xred
1658 
1659  Purpose: To parse the directive: redirect <host>:<port>[%<prvhost>:<port>]
1660  {<funcs>|[?]<path>} |
1661  client <domlist>
1662 
1663  <funcs> are one or more of the following functions that will
1664  be immediately redirected to <host>:<port>. Each function
1665  may be prefixed by a minus sign to disable redirection.
1666 
1667  chmod dirlist locate mkdir mv prepare rm rmdir stat
1668 
1669  <paths> redirects the client when an attempt is made to open
1670  one of absolute <paths>. Up to 4 different redirect
1671  combinations may be specified. When prefixed by "?"
1672  then the redirect applies to any operation on the path
1673  that results in an ENOENT error.
1674 
1675  <domlist> {private | local | .<domain>} [<domlist>]
1676 
1677  Output: 0 upon success or !0 upon failure.
1678 */
1679 
1680 int XrdXrootdProtocol::xred(XrdOucStream &Config)
1681 {
1682  static struct rediropts {const char *opname; RD_func opval;} rdopts[] =
1683  {
1684  {"chmod", RD_chmod},
1685  {"chksum", RD_chksum},
1686  {"dirlist", RD_dirlist},
1687  {"locate", RD_locate},
1688  {"mkdir", RD_mkdir},
1689  {"mv", RD_mv},
1690  {"openw", RD_openw},
1691  {"prepare", RD_prepare},
1692  {"prepstage",RD_prepstg},
1693  {"rm", RD_rm},
1694  {"rmdir", RD_rmdir},
1695  {"stat", RD_stat},
1696  {"trunc", RD_trunc}
1697  };
1698  static const int rHLen = 264;
1699  char rHost[2][rHLen], *hP[2], *val;
1700  int i, k, neg, numopts = sizeof(rdopts)/sizeof(struct rediropts);
1701  int rPort[2], isQ = 0;
1702 
1703 // Get the host and port
1704 //
1705  val = Config.GetWord();
1706  if (!xred_php(val, hP, rPort, "redirect")) return 1;
1707 
1708 // Copy out he values as the target variable will be lost
1709 //
1710  for (i = 0; i < 2; i++)
1711  {if (!hP[i]) rHost[i][0] = 0;
1712  else {strlcpy(rHost[i], hP[i], rHLen);
1713  hP[i] = rHost[i];
1714  }
1715  }
1716 
1717 // Set all redirect target functions
1718 //
1719  if (!(val = Config.GetWord()))
1720  {eDest.Emsg("config", "redirect option not specified"); return 1;}
1721 
1722 // Handle the client option
1723 //
1724  if (!strcmp("client", val)) return xred_clnt(Config, hP, rPort);
1725 
1726  if (*val == '/' || (isQ = ((*val == '?') || !strcmp(val,"enoent"))))
1727  {if (isQ)
1728  {RQLxist = 1;
1729  if (!(val = Config.GetWord()))
1730  {eDest.Emsg("Config", "redirect path not specified.");
1731  return 1;
1732  }
1733  if (*val != '/')
1734  {eDest.Emsg("Config", "non-absolute redirect path -", val);
1735  return 1;
1736  }
1737  }
1738  for (k = static_cast<int>(RD_open1); k < RD_Num; k++)
1739  if (xred_xok(k, hP, rPort)) break;
1740  if (k >= RD_Num)
1741  {eDest.Emsg("Config", "too many different path redirects"); return 1;}
1742  xred_set(RD_func(k), hP, rPort);
1743  do {if (isQ) RQList.Insert(val, k, 0);
1744  else RPList.Insert(val, k, 0);
1745  if ((val = Config.GetWord()) && *val != '/')
1746  {eDest.Emsg("Config", "non-absolute redirect path -", val);
1747  return 1;
1748  }
1749  } while(val);
1750  return 0;
1751  }
1752 
1753  while (val)
1754  {if (!strcmp(val, "all"))
1755  {for (i = 0; i < numopts; i++)
1756  xred_set(rdopts[i].opval, hP, rPort);
1757  }
1758  else {if ((neg = (val[0] == '-' && val[1]))) val++;
1759  for (i = 0; i < numopts; i++)
1760  {if (!strcmp(val, rdopts[i].opname))
1761  {if (neg) xred_set(rdopts[i].opval, 0, 0);
1762  else xred_set(rdopts[i].opval, hP, rPort);
1763  break;
1764  }
1765  }
1766  if (i >= numopts)
1767  eDest.Emsg("config", "invalid redirect option", val);
1768  }
1769  val = Config.GetWord();
1770  }
1771  return 0;
1772 }
1773 
1774 /******************************************************************************/
1775 
1776 int XrdXrootdProtocol::xred_clnt(XrdOucStream &Config,char *hP[2],int rPort[2])
1777 {
1778  static const int maxDom = sizeof(RouteClient.Domain)/sizeof(char*);
1779  char *val;
1780 
1781 // Reset values
1782 //
1783  if (CL_Redir)
1784  {for (int i = 0; i < RouteClient.DomCnt; i++)
1785  {if (RouteClient.Domain[i]) free(RouteClient.Domain[i]);}
1786  }
1787  for (int i = 0; i < maxDom; i++) RouteClient.Domain[i] = 0;
1788  RouteClient.DomCnt = 0;
1789  RouteClient.pvtIP = false;
1790  RouteClient.lclDom = false;
1791  CL_Redir = true;
1792 
1793 // Process arguments
1794 //
1795  if (!(val = Config.GetWord()))
1796  {eDest.Emsg("Config", "redirect client argument not specified.");
1797  return 1;
1798  }
1799 
1800  while(val)
1801  { if (!strcmp("private", val)) RouteClient.pvtIP = true;
1802  else if (!strcmp("local", val)) RouteClient.lclDom = true;
1803  else if (*val == '.')
1804  {if (RouteClient.DomCnt >= maxDom)
1805  {eDest.Emsg("Config",
1806  "Too many redirect client domains specified.");
1807  return 1;
1808  }
1809  RouteClient.Domain[RouteClient.DomCnt++] = strdup(val);
1810  }
1811  else {eDest.Emsg("Config", "Invalid redirect client domain -", val);
1812  return 1;
1813  }
1814  val = Config.GetWord();
1815  }
1816 
1817 // Set the host parameters
1818 //
1819  xred_set(RD_client, hP, rPort);
1820  return 0;
1821 }
1822 
1823 /******************************************************************************/
1824 
1825 bool XrdXrootdProtocol::xred_php(char *val, char *hP[2], int rPort[2],
1826  const char *what, bool optport)
1827 {
1828  XrdNetAddr testAddr;
1829  char *pp;
1830 
1831 // Make sure we have a value
1832 //
1833  if (!val || !(*val))
1834  {eDest.Emsg("config", what, "argument not specified"); return false;}
1835 
1836 // Check if we have two hosts here
1837 //
1838  hP[0] = val;
1839  if (!(pp = index(val, '%'))) hP[1] = 0;
1840  else {hP[1] = pp+1; *pp = 0;}
1841 
1842 // Verify corectness here
1843 //
1844  if (!(*val) || (hP[1] && !*hP[1]))
1845  {eDest.Emsg("Config", "malformed", what, "host specification");
1846  return false;
1847  }
1848 
1849 // Process the hosts
1850 //
1851  for (int i = 0; i < 2; i++)
1852  {if (!(val = hP[i])) break;
1853  if (!val || !val[0] || val[0] == ':')
1854  {eDest.Emsg("Config", what, "host not specified"); return false;}
1855  if ((pp = rindex(val, ':')))
1856  {if ((rPort[i] = XrdOuca2x::a2p(eDest, "tcp", pp+1, false)) <= 0)
1857  return false;
1858  *pp = '\0';
1859  } else {
1860  if (optport) rPort[i] = 0;
1861  else {eDest.Emsg("Config", what, "port not specified");
1862  return false;
1863  }
1864  }
1865  const char *eText = testAddr.Set(val, 0);
1866  if (eText)
1867  {if (XrdNetAddrInfo::isHostName(val) && !strncmp(eText,"Dynamic",7))
1868  eDest.Say("Config warning: ", eText, " as ", val);
1869  else {eDest.Say("Config failure: ", what, " target ", val,
1870  " is invalid; ", eText);
1871  return false;
1872  }
1873  }
1874  }
1875 
1876 // All done
1877 //
1878  return true;
1879 }
1880 
1881 void XrdXrootdProtocol::xred_set(RD_func func, char *rHost[2], int rPort[2])
1882 {
1883 
1884 // Reset static redirection
1885 //
1886  if (Route[func].Host[0]) free(Route[func].Host[0]);
1887  if (Route[func].Host[0] != Route[func].Host[1]) free(Route[func].Host[1]);
1888 
1889  if (rHost)
1890  {Route[func].Host[0] = strdup(rHost[0]);
1891  Route[func].Port[0] = rPort[0];
1892  } else {
1893  Route[func].Host[0] = Route[func].Host[1] = 0;
1894  Route[func].Port[0] = Route[func].Port[1] = 0;
1895  return;
1896  }
1897 
1898  if (!rHost[1])
1899  {Route[func].Host[1] = Route[func].Host[0];
1900  Route[func].Port[1] = Route[func].Port[0];
1901  } else {
1902  Route[func].Host[1] = strdup(rHost[1]);
1903  Route[func].Port[1] = rPort[1];
1904  }
1905 }
1906 
1907 bool XrdXrootdProtocol::xred_xok(int func, char *rHost[2], int rPort[2])
1908 {
1909  if (!Route[func].Host[0]) return true;
1910 
1911  if (strcmp(Route[func].Host[0], rHost[0])
1912  || Route[func].Port[0] != rPort[0]) return false;
1913 
1914  if (!rHost[1]) return Route[func].Host[0] == Route[func].Host[1];
1915 
1916  if (strcmp(Route[func].Host[1], rHost[1])
1917  || Route[func].Port[1] != rPort[1]) return false;
1918 
1919  return true;
1920 }
1921 
1922 /******************************************************************************/
1923 /* x s e c l */
1924 /******************************************************************************/
1925 
1926 /* Function: xsecl
1927 
1928  Purpose: To parse the directive: seclib {default | <path>}
1929 
1930  <path> the path of the security library to be used.
1931  "default" uses the default security library.
1932 
1933  Output: 0 upon success or !0 upon failure.
1934 */
1935 
1936 int XrdXrootdProtocol::xsecl(XrdOucStream &Config)
1937 {
1938  char *val;
1939 
1940 // Get the path
1941 //
1942  val = Config.GetWord();
1943  if (!val || !val[0])
1944  {eDest.Emsg("Config", "seclib argument not specified"); return 1;}
1945 
1946 // Record the path
1947 //
1948  if (SecLib) free(SecLib);
1949  SecLib = strdup(val);
1950  return 0;
1951 }
1952 
1953 /******************************************************************************/
1954 /* x t l s */
1955 /******************************************************************************/
1956 
1957 /* Function: xtls
1958 
1959 topPurpose: To parse the directive: tls [capable] <reqs>
1960 
1961  capable Enforce TLS requirements only for TLS capable clients.
1962  Otherwise, TLS is enforced for all clients.
1963  <reqs> are one or more of the following tls requirements. Each
1964  may be prefixed by a minus sign to disable it. Note
1965  this directive is cummalitive.
1966 
1967  all Requires all of the below.
1968  data All bound sockets must use TLS. When specified,
1969  session is implied unless login is specified.
1970  gpfile getile and putfile requests must use TLS
1971  login Logins and all subsequent requests must use TLS
1972  none Turns all requirements off (default).
1973  off Synonym for none.
1974  session All requests after login must use TLS
1975  tpc Third party copy requests must use TLS
1976 
1977  Output: 0 upon success or !0 upon failure.
1978 */
1979 
1980 int XrdXrootdProtocol::xtls(XrdOucStream &Config)
1981 {
1982  static const int Req_TLSAll = Req_TLSData|Req_TLSLogin|Req_TLSTPC;
1983  static struct enforceopts {const char *opname; int opval; int enval;}
1984  enfopts[] =
1985  {
1986  {"all", kXR_tlsAny, Req_TLSAll},
1987  {"data", kXR_tlsData, Req_TLSData},
1988  {"gpfile", kXR_tlsGPF, Req_TLSGPFile},
1989  {"login", kXR_tlsLogin, Req_TLSLogin},
1990  {"session", kXR_tlsSess, Req_TLSSess},
1991  {"tpc", kXR_tlsTPC, Req_TLSTPC}
1992  };
1993  char *val;
1994  int i, numopts = sizeof(enfopts)/sizeof(struct enforceopts);
1995  bool neg, forall = true;
1996 
1997  if (!(val = Config.GetWord()))
1998  {eDest.Emsg("config", "tls parameter not specified"); return 1;}
1999 
2000  if (!strcmp("capable", val))
2001  {forall = false;
2002  if (!(val = Config.GetWord()))
2003  {eDest.Emsg("config", "tls requirement not specified"); return 1;}
2004  }
2005 
2006  while (val)
2007  {if (!strcmp(val, "off") || !strcmp(val, "none"))
2008  {myRole &= ~kXR_tlsAny;
2009  if (forall) tlsCap = tlsNot = 0;
2010  else tlsCap = 0;
2011  } else {
2012  if ((neg = (val[0] == '-' && val[1]))) val++;
2013  for (i = 0; i < numopts; i++)
2014  {if (!strcmp(val, enfopts[i].opname))
2015  {if (neg) myRole &= ~enfopts[i].opval;
2016  else myRole |= enfopts[i].opval;
2017  if (neg) tlsCap &= ~enfopts[i].enval;
2018  else tlsCap |= enfopts[i].enval;
2019  if (forall)
2020  {if (neg) tlsNot &= ~enfopts[i].enval;
2021  else tlsNot |= enfopts[i].enval;
2022  }
2023  break;
2024  }
2025  }
2026  if (i >= numopts)
2027  {eDest.Emsg("config", "Invalid tls requirement -", val);
2028  return 1;
2029  }
2030  }
2031  val = Config.GetWord();
2032  }
2033 
2034 // If data needs TLS but the session does not, then force session TLS
2035 //
2036  if ((myRole & kXR_tlsData) && !(myRole & (kXR_tlsLogin | kXR_tlsSess)))
2037  myRole |= kXR_tlsSess;
2038  if ((tlsCap & kXR_tlsData) && !(tlsCap & (Req_TLSLogin | Req_TLSSess)))
2039  tlsCap |= Req_TLSSess;
2040  if ((tlsNot & kXR_tlsData) && !(tlsNot & (Req_TLSLogin | Req_TLSSess)))
2041  tlsNot |= Req_TLSSess;
2042 
2043 // Do final resolution on the settins
2044 //
2045  return (CheckTLS(0) ? 0 : 1);
2046 }
2047 
2048 /******************************************************************************/
2049 /* x t l s r */
2050 /******************************************************************************/
2051 
2052 /* Function: xtlsr
2053 
2054  Purpose: To parse the directive: tlsreuse off | on [flush <ft>[h|m|s]]
2055 
2056  off turns off the TLS session reuse cache.
2057  on turns on the TLS session reuse cache.
2058  <ft> sets the cache flush frequency. the default is set
2059  by the TLS libraries and is typically connection count.
2060 
2061  Output: 0 upon success or !0 upon failure.
2062 */
2063 
2064 int XrdXrootdProtocol::xtlsr(XrdOucStream &Config)
2065 {
2066  char *val;
2067  int num;
2068 
2069 // Get the argument
2070 //
2071  val = Config.GetWord();
2072  if (!val || !val[0])
2073  {eDest.Emsg("Config", "tlsreuse argument not specified"); return 1;}
2074 
2075 // If it's off, we set it off
2076 //
2077  if (!strcmp(val, "off"))
2079  return 0;
2080  }
2081 
2082 // If it's on we may need more to do
2083 //
2084  if (!strcmp(val, "on"))
2085  {if (!tlsCtx) {eDest.Emsg("Config warning:", "Ignoring "
2086  "'tlsreuse on'; TLS not configured!");
2087  return 0;
2088  }
2090  if (!(val = Config.GetWord())) return 0;
2091  if (!strcmp(val, "flush" ))
2092  {if (!(val = Config.GetWord()))
2093  {eDest.Emsg("Config", "tlsreuse flush value not specified");
2094  return 1;
2095  }
2096  if (XrdOuca2x::a2tm(eDest,"tlsreuse flush",val,&num,1)) return 1;
2097  if (num < 60) num = 60;
2098  else if (num > XrdTlsContext::scFMax)
2099  num = XrdTlsContext::scFMax;
2100  tlsCache |= num;
2101  }
2102  }
2103 
2104 // We have a bad keyword
2105 //
2106  eDest.Emsg("config", "Invalid tlsreuse option -", val);
2107  return 1;
2108 }
2109 
2110 /******************************************************************************/
2111 /* x t r a c e */
2112 /******************************************************************************/
2113 
2114 /* Function: xtrace
2115 
2116  Purpose: To parse the directive: trace <events>
2117 
2118  <events> the blank separated list of events to trace. Trace
2119  directives are cummalative.
2120 
2121  Output: 0 upon success or 1 upon failure.
2122 */
2123 
2124 int XrdXrootdProtocol::xtrace(XrdOucStream &Config)
2125 {
2126  char *val;
2127  static struct traceopts {const char *opname; int opval;} tropts[] =
2128  {
2129  {"all", TRACE_ALL},
2130  {"auth", TRACE_AUTH},
2131  {"debug", TRACE_DEBUG},
2132  {"emsg", TRACE_EMSG},
2133  {"fs", TRACE_FS},
2134  {"fsaio", TRACE_FSAIO},
2135  {"fsio", TRACE_FSIO},
2136  {"login", TRACE_LOGIN},
2137  {"mem", TRACE_MEM},
2138  {"pgcserr", TRACE_PGCS},
2139  {"redirect", TRACE_REDIR},
2140  {"request", TRACE_REQ},
2141  {"response", TRACE_RSP},
2142  {"stall", TRACE_STALL}
2143  };
2144  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
2145 
2146  if (!(val = Config.GetWord()))
2147  {eDest.Emsg("config", "trace option not specified"); return 1;}
2148  while (val)
2149  {if (!strcmp(val, "off")) trval = 0;
2150  else {if ((neg = (val[0] == '-' && val[1]))) val++;
2151  for (i = 0; i < numopts; i++)
2152  {if (!strcmp(val, tropts[i].opname))
2153  {if (neg) trval &= ~tropts[i].opval;
2154  else trval |= tropts[i].opval;
2155  break;
2156  }
2157  }
2158  if (i >= numopts)
2159  eDest.Emsg("config", "invalid trace option", val);
2160  }
2161  val = Config.GetWord();
2162  }
2163  XrdXrootdTrace.What = trval;
2164  return 0;
2165 }
2166 
2167 /******************************************************************************/
2168 /* x l i m i t */
2169 /******************************************************************************/
2170 
2171 /* Function: xlimit
2172 
2173  Purpose: To parse the directive: limit [prepare <count>] [noerror]
2174 
2175  prepare <count> The maximum number of prepares that are allowed
2176  during the course of a single connection
2177 
2178  noerror When possible, do not issue an error when a limit
2179  is hit.
2180 
2181  Output: 0 upon success or 1 upon failure.
2182 */
2183 int XrdXrootdProtocol::xlimit(XrdOucStream &Config)
2184 {
2185  int plimit = -1;
2186  const char *word;
2187 
2188 // Look for various limits set
2189 //
2190  while ( (word = Config.GetWord()) ) {
2191  if (!strcmp(word, "prepare")) {
2192  if (!(word = Config.GetWord()))
2193  {
2194  eDest.Emsg("Config", "'limit prepare' value not specified");
2195  return 1;
2196  }
2197  if (XrdOuca2x::a2i(eDest, "limit prepare", word, &plimit, 0)) { return 1; }
2198  } else if (!strcmp(word, "noerror")) {
2199  LimitError = false;
2200  }
2201  }
2202  if (plimit >= 0) {PrepareLimit = plimit;}
2203  return 0;
2204 }
#define kXR_isManager
Definition: XProtocol.hh:1198
#define kXR_tlsLogin
Definition: XProtocol.hh:1226
#define kXR_suppgrw
Definition: XProtocol.hh:1216
#define kXR_attrMeta
Definition: XProtocol.hh:1201
#define kXR_haveTLS
Definition: XProtocol.hh:1221
#define kXR_anongpf
Definition: XProtocol.hh:1214
#define kXR_tlsAny
Definition: XProtocol.hh:1223
#define kXR_tlsTPC
Definition: XProtocol.hh:1228
#define kXR_isServer
Definition: XProtocol.hh:1199
#define kXR_attrCache
Definition: XProtocol.hh:1200
#define kXR_attrProxy
Definition: XProtocol.hh:1202
#define kXR_LBalServer
Definition: XProtocol.hh:1193
#define kXR_tlsGPF
Definition: XProtocol.hh:1225
#define kXR_supposc
Definition: XProtocol.hh:1217
#define kXR_tlsSess
Definition: XProtocol.hh:1227
#define kXR_DataServer
Definition: XProtocol.hh:1192
#define kXR_supgpf
Definition: XProtocol.hh:1215
#define kXR_tlsData
Definition: XProtocol.hh:1224
unsigned short kXR_unt16
Definition: XPtypes.hh:67
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
XrdSfsFileSystem * XrdDigGetFS(XrdSfsFileSystem *native_fs, XrdSysLogger *lp, const char *cFN, const char *parms)
Definition: XrdDigFS.cc:105
#define TRACE_AUTH
Definition: XrdHttpTrace.hh:48
#define TRACE_REQ
Definition: XrdHttpTrace.hh:51
#define TRACE_RSP
Definition: XrdHttpTrace.hh:53
#define TRACE_REDIR
Definition: XrdHttpTrace.hh:52
#define open
Definition: XrdPosix.hh:78
XrdSecProtocol *(* XrdSecGetProt_t)(const char *hostname, XrdNetAddrInfo &endPoint, XrdSecParameters &sectoken, XrdOucErrInfo *einfo)
Typedef to simplify the encoding of methods returning XrdSecProtocol.
XrdSecService * XrdSecLoadSecService(XrdSysError *eDest, const char *cfn, const char *seclib, XrdSecGetProt_t *getP, XrdSecProtector **proP)
#define SFS_OK
const int SYS_LOG_02
Definition: XrdSysError.hh:101
const int SYS_LOG_01
Definition: XrdSysError.hh:100
if(Avsz)
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE_DEBUG
Definition: XrdTrace.hh:36
#define TRACE_MEM
Definition: XrdTrace.hh:38
#define TRACE(act, x)
Definition: XrdTrace.hh:63
#define TRACE_ALL
Definition: XrdTrace.hh:35
const char * XrdXrootdInstance
XrdSysTrace XrdXrootdTrace
XrdSfsFileSystem * XrdSfsGetDefaultFileSystem(XrdSfsFileSystem *nativeFS, XrdSysLogger *Logger, const char *configFn, XrdOucEnv *EnvInfo)
Definition: XrdOfsFS.cc:49
XrdXrootdPrepare * XrdXrootdPrepQ
XrdXrootdRedirPI * XrdXrootdloadRedirLib(XrdSysError *, XrdXrootdRedirPI *, const char *, const char *, const char *, XrdOucEnv *)
#define TS_Zeq(x, m)
XrdOucString * XrdXrootdCF
#define TS_Xeq(x, m)
XrdSfsFileSystem * XrdXrootdloadFileSystem(XrdSysError *, XrdSfsFileSystem *, const char *, const char *, XrdOucEnv *)
int XrdXrootdPort
#define TRACE_FS
#define TRACE_FSAIO
#define TRACE_FSIO
#define TRACE_PGCS
#define TRACE_LOGIN
#define TRACE_EMSG
#define TRACE_STALL
#define XROOTDXP_OK
#define XROOTDXP_NOLK
#define XROOTDXP_NOSLASH
#define XROOTDXP_NOMWCHK
#define XROOTDXP_NOCGI
int Recalc(int bsz)
Definition: XrdBuffer.cc:195
static XrdNetIF netIF
Definition: XrdInet.hh:68
static bool isHostName(const char *name)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
void Display(const char *pfx="=====> ")
Definition: XrdNetIF.cc:142
int Port()
Definition: XrdNetIF.hh:322
static int Parse(XrdSysError *eLog, XrdOucStream &Config)
static XrdNetPMark * Config(XrdSysError *eLog, XrdScheduler *sched, XrdSysTrace *trc, bool &fatal)
static XrdNetSocket * Create(XrdSysError *Say, const char *path, const char *fn, mode_t mode, int isudp=0)
void Set(int inQMax, time_t agemax=1800)
Definition: XrdObject.icc:90
long GetInt(const char *varname)
Definition: XrdOucEnv.cc:253
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:281
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
void PutPtr(const char *varname, void *value)
Definition: XrdOucEnv.cc:316
int Setup(const char *prog, XrdSysError *errP=0, int(*Proc)(XrdOucStream *, char **, int)=0)
Definition: XrdOucProg.cc:296
const char * c_str() const
int length() const
void append(const int i)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static const mode_t pathMode
Definition: XrdOucUtils.hh:48
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:505
static int GidName(gid_t gID, char *gName, int gNsz, time_t keepT=0)
Definition: XrdOucUtils.cc:635
static int UidName(uid_t uID, char *uName, int uNsz, time_t keepT=0)
static int makePath(char *path, mode_t mode, bool reset=false)
static void toLower(char *str)
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
const char * myName
Definition: XrdProtocol.hh:82
XrdBuffManager * BPool
Definition: XrdProtocol.hh:63
XrdScheduler * Sched
Definition: XrdProtocol.hh:64
XrdTlsContext * tlsCtx
Definition: XrdProtocol.hh:99
const char * AdmPath
Definition: XrdProtocol.hh:76
XrdSysError * eDest
Definition: XrdProtocol.hh:61
XrdOucString * totalCF
Definition: XrdProtocol.hh:100
XrdOucEnv * theEnv
Definition: XrdProtocol.hh:66
const char * myInst
Definition: XrdProtocol.hh:81
XrdStats * Stats
Definition: XrdProtocol.hh:65
virtual const char * protTLS()=0
virtual void EnvInfo(XrdOucEnv *envP)
virtual int chksum(csFunc Func, const char *csName, const char *path, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0, const char *opaque=0)
virtual int FAttr(XrdSfsFACtl *faReq, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
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:162
void setMsgMask(int mask)
Definition: XrdSysError.hh:188
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:175
void SetLogger(XrdSysLogger *logp)
Definition: XrdSysTrace.cc:65
XrdTlsContext * Clone(bool full=true, bool startCRLRefresh=false)
int SessionCache(int opts=scNone, const char *id=0, int idlen=0)
static const int scNone
Do not change any option settings.
static const int scOff
Turn off cache.
static const int scFMax
static const int scSrvr
Turn on cache server mode (default)
static int Init(XrdSysError *erp, XrdNetSocket *asock)
static void addJob(const char *jname, XrdXrootdJob *jp)
static void setVals(XrdSysError *erp, XrdXrootdStats *SIp, XrdScheduler *schp, int port)
static void Init(XrdXrootdFileLock *lp, XrdSysError *erP, bool sfok)
static int setParms(int stime, int skeep)
static XrdXrootdStats * SI
static const char * myInst
static XrdSfsFileSystem * digFS
static XrdNetPMark * PMark
static short as_okstutter
static XrdXrootdXPath RPList
static XrdNetSocket * AdminSock
static const char Req_TLSGPFile
static const char Req_TLSSess
static XrdXrootdJob * JobCKS
static XrdSysError & eDest
static char * usxParms
static XrdXrootdRedirPI * RedirPI
static const char * myCName
static const char Req_TLSData
static XrdXrootdFileLock * Locker
static const char Req_TLSTPC
static XrdTlsContext * tlsCtx
static XrdXrootdXPath XPList
static XrdScheduler * Sched
static struct XrdXrootdProtocol::RC_Table RouteClient
static const char * myUName
static const char Req_TLSLogin
static int Configure(char *parms, XrdProtocol_Config *pi)
static XrdOucTList * JobCKTLST
static XrdXrootdXPath RQList
static XrdSecProtector * DHS
static XrdBuffManager * BPool
static XrdSecService * CIA
static const char * myGName
static uint64_t fsFeatures
static XrdOucReqID * PrepID
static struct XrdXrootdProtocol::RD_Table Route[RD_Num]
static XrdSfsFileSystem * osFS
void setFS(XrdSfsFileSystem *fsp)
static void Init(XrdScheduler *schedP, int qMax, int qTTL)
Perform one-time initialization.
void Insert(const char *pd, int popt=0, int flags=XROOTDXP_OK)
XrdXrootdXPath * Next()
void Set(int opts, const char *pathdata=0)
XrdCmsConfig Config
XrdSysLogger Logger
Definition: XrdGlobals.cc:47
struct ServerResponseBifs_Protocol bifReqs
Definition: XProtocol.hh:1162
static const int maxRvecsz
Definition: XProtocol.hh:722
static const uint64_t hasPGRW
Feature: pgRead and pgWrite.
Definition: XrdSfsFlags.hh:56
static const uint64_t hasPRP2
Feature: Prepare Handler Version 2 (different calling conventions)
Definition: XrdSfsFlags.hh:62
static const uint64_t hasGPFA
Feature: gpFile anonymous.
Definition: XrdSfsFlags.hh:53
static const uint64_t hasCACH
Feature: Implements a data cache.
Definition: XrdSfsFlags.hh:74
static const uint64_t hasNOSF
Feature: Supports no sendfile.
Definition: XrdSfsFlags.hh:71
static const uint64_t hasPOSC
Feature: Persist On Successful Close.
Definition: XrdSfsFlags.hh:59
static const uint64_t hasGPF
Feature: gpFile.
Definition: XrdSfsFlags.hh:50
static const uint64_t hasNAIO
Feature: Supports no async I/O.
Definition: XrdSfsFlags.hh:77
static const uint64_t hasPRXY
Feature: Proxy Server.
Definition: XrdSfsFlags.hh:65
XrdXrootdStats * SI
XrdScheduler * Sched
char * bifResp[2]
XrdBuffManager * BPool