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