Loading...
Searching...
No Matches
XrdCmsRedirLocal.cc
Go to the documentation of this file.
//------------------------------------------------------------------------------
// Copyright (c) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
// Author: Paul-Niklas Kramp <p.n.kramp@gsi.de>
// Jan Knedlik <j.knedlik@gsi.de>
//------------------------------------------------------------------------------
// XRootD is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// XRootD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include <XrdCms/XrdCmsRedirLocal.hh>
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
extern "C" XrdCmsClient *XrdCmsGetClient(XrdSysLogger *Logger, int opMode,
int myPort, XrdOss *theSS) {
XrdCmsRedirLocal *plugin = new XrdCmsRedirLocal(Logger, opMode, myPort, theSS);
return plugin;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
XrdCmsRedirLocal::XrdCmsRedirLocal(XrdSysLogger *Logger, int opMode, int myPort,
XrdOss *theSS) : XrdCmsClient(amLocal),
nativeCmsFinder(new XrdCmsFinderRMT(Logger, opMode, myPort)),
readOnlyredirect(true),
httpRedirect(false),
Say(0,"cms_") {
Say.logger(Logger);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
XrdCmsRedirLocal::~XrdCmsRedirLocal() { delete nativeCmsFinder; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int XrdCmsRedirLocal::Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo) {
loadConfig(cfn);
if(localroot.empty())
{
Say.Emsg("RedirLocal", "oss.localroot (replaced by xrdcmsredirlocal for localredirect) " \
"and xrdcmsredirlocal.localroot are undefined, define xrdcmsredirlocal.localroot");
return 0;
}
if(localroot[0] != '/')
{
Say.Emsg("RedirLocal", "oss.localroot or xrdcmsredirlocal.localroot needs to be an absolute path");
return 0;
}
if (nativeCmsFinder)
return nativeCmsFinder->Configure(cfn, Parms, EnvInfo);
return 0; // means false
}
void XrdCmsRedirLocal::loadConfig(const char *filename) {
XrdOucStream Config;
int cfgFD;
char *word;
if ((cfgFD = open(filename, O_RDONLY, 0)) < 0) {
return;
}
Config.Attach(cfgFD);
while ((word = Config.GetFirstWord(true))) { //get word in lower case
// search for readonlyredirect,
// which only allows read calls to be redirected to local
if (strcmp(word, "xrdcmsredirlocal.readonlyredirect") == 0){
readOnlyredirect = std::string(Config.GetWord(true)).find("true") != std::string::npos;
}
// search for httpredirect,
// which allows http(s) calls to be redirected to local
else if (strcmp(word, "xrdcmsredirlocal.httpredirect") == 0){
httpRedirect = std::string(Config.GetWord(true)).find("true") != std::string::npos;
}
// search for newer localroot, overwrite given oss.localroot if defined,
// which manually sets localroot to prepend
else if (strcmp(word, "xrdcmsredirlocal.localroot") == 0){
localroot = std::string(Config.GetWord(false));
}
// search for oss.localroot,
// which manually sets localroot to prepend
else if (strcmp(word, "oss.localroot") == 0 && localroot.empty()){
localroot = std::string(Config.GetWord(false));
}
}
Config.Close();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int XrdCmsRedirLocal::Locate(XrdOucErrInfo &Resp, const char *path, int flags,
XrdOucEnv *EnvInfo) {
int rcode = 0;
if (nativeCmsFinder) {
// check if path contains localroot to know if potential redirection loop
// is happening. If yes, remove localroot from path, then rerun default
// locate with regular path and return to client
// localroot must be larger than 1 to avoid always being triggered by "/"
if (localroot.size() > 1 && strncmp(path, localroot.c_str(), localroot.size()) == 0)
{
// now check if localhost was tried before, to make sure we're handling
// the redirection loop
int param = 0; // need it to get Env
//EnvInfo->Env(param) gets already tried hosts
if(strstr(EnvInfo->Env(param), "tried=localhost") != nullptr)
{
std::string newPath(path);
// remove localroot
newPath = "//" + newPath.substr(localroot.size());
// get regular target host
rcode = nativeCmsFinder->Locate(Resp, newPath.c_str(), flags, EnvInfo);
// set new error message to full url:port//newPath
const std::string errText { std::string(Resp.getErrText()) + ':' + std::to_string(Resp.getErrInfo()) + newPath};
Resp.setErrInfo(0, errText.c_str());
// now have normal redirection to dataserver at url:port
return rcode;
}
}
std::string dialect = EnvInfo->secEnv()->addrInfo->Dialect();
// get regular target host
rcode = nativeCmsFinder->Locate(Resp, path, flags, EnvInfo);
// check if http redirect to local filesystem is allowed
if (strncmp(dialect.c_str(), "http", 4) == 0 && !httpRedirect)
return rcode;
// define target host from locate result
XrdNetAddr target(-1); // port is necessary, but can be any
target.Set(Resp.getErrText());
// does the target host have a private IP?
if (!target.isPrivate())
return rcode;
// does the client host have a private IP?
if (!EnvInfo->secEnv()->addrInfo->isPrivate())
return rcode;
// as we can't rely on the flags from http clients, we do not perform the below
if (strncmp(dialect.c_str(), "http", 4) != 0)
{
// get client url redirect capability
int urlRedirSupport = Resp.getUCap();
urlRedirSupport &= XrdOucEI::uUrlOK;
if (!urlRedirSupport)
return rcode;
// get client localredirect capability
int clientLRedirSupport = Resp.getUCap();
clientLRedirSupport &= XrdOucEI::uLclF;
if (!clientLRedirSupport)
return rcode;
}
// http gets SFS_O_STAT flag when opening to read, instead of SFS_O_RDONLY
// in case of http dialect and stat, we do not perform the checks below
if (!(strncmp(dialect.c_str(), "http", 4) == 0 && flags == 0x20000000))
{
// only allow simple (but most prominent) operations to avoid complications
// RDONLY, WRONLY, RDWR, CREAT, TRUNC are allowed
if (flags > 0x202)
return rcode;
// always use native function if readOnlyredirect is configured and a
// non readonly flag is passed
if (readOnlyredirect && !(flags == SFS_O_RDONLY))
return rcode;
}
// passed all checks, now to actual business
// prepend manually configured localroot
std::string ppath = "file://" + localroot + path;
if (strncmp(dialect.c_str(), "http", 4) == 0)
{
// set info which will be sent to client
// eliminate the resource name so it is not doubled in XrdHttpReq::Redir.
Resp.setErrInfo(-1, ppath.substr(0, ppath.find(path)).c_str());
}
else{
// set info which will be sent to client
Resp.setErrInfo(-1, ppath.c_str());
}
return SFS_REDIRECT;
}
return rcode;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int XrdCmsRedirLocal::Space(XrdOucErrInfo &Resp, const char *path,
XrdOucEnv *EnvInfo) {
if (nativeCmsFinder)
return nativeCmsFinder->Space(Resp, path, EnvInfo);
return 0;
}
XrdVERSIONINFO(XrdCmsGetClient, XrdCmsRedirLocal);
XrdVERSIONINFO
XrdVERSIONINFO(XrdCmsGetClient, XrdCmsRedirLocal)
XrdCmsGetClient
XrdCmsClient * XrdCmsGetClient(XrdSysLogger *Logger, int opMode, int myPort, XrdOss *theSS)
Necessary implementation for XRootD to get the Plug-in.
Definition XrdCmsRedirLocal.cc:25
XrdCmsRedirLocal.hh
Logger
static XrdSysLogger Logger
Definition XrdCryptoAux.cc:37
open
#define open
Definition XrdPosix.hh:76
SFS_REDIRECT
#define SFS_REDIRECT
Definition XrdSfsInterface.hh:110
SFS_O_RDONLY
#define SFS_O_RDONLY
Definition XrdSfsInterface.hh:50
XrdCmsClient
Definition XrdCmsClient.hh:116
XrdCmsClient::XrdCmsClient
XrdCmsClient(Persona acting)
Definition XrdCmsClient.hh:357
XrdCmsClient::amLocal
@ amLocal
Not affiliated with a cluster.
Definition XrdCmsClient.hh:352
XrdCmsFinderRMT
Definition XrdCmsFinder.hh:54
XrdCmsRedirLocal
Definition XrdCmsRedirLocal.hh:44
XrdCmsRedirLocal::Configure
int Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo)
Configure the nativeCmsFinder.
Definition XrdCmsRedirLocal.cc:50
XrdCmsRedirLocal::~XrdCmsRedirLocal
~XrdCmsRedirLocal()
Destructor.
Definition XrdCmsRedirLocal.cc:45
XrdCmsRedirLocal::nativeCmsFinder
XrdCmsClient * nativeCmsFinder
used to forward requests to CmsFinder with regular implementation
Definition XrdCmsRedirLocal.hh:76
XrdCmsRedirLocal::loadConfig
void loadConfig(const char *filename)
Definition XrdCmsRedirLocal.cc:68
XrdCmsRedirLocal::readOnlyredirect
bool readOnlyredirect
Definition XrdCmsRedirLocal.hh:77
XrdCmsRedirLocal::Locate
int Locate(XrdOucErrInfo &Resp, const char *path, int flags, XrdOucEnv *EnvInfo)
Definition XrdCmsRedirLocal.cc:122
XrdCmsRedirLocal::httpRedirect
bool httpRedirect
Definition XrdCmsRedirLocal.hh:78
XrdCmsRedirLocal::localroot
std::string localroot
Definition XrdCmsRedirLocal.hh:79
XrdCmsRedirLocal::XrdCmsRedirLocal
XrdCmsRedirLocal(XrdSysLogger *Logger, int opMode, int myPort, XrdOss *theSS)
Constructor.
Definition XrdCmsRedirLocal.cc:34
XrdCmsRedirLocal::Say
XrdSysError Say
Definition XrdCmsRedirLocal.hh:80
XrdCmsRedirLocal::Space
int Space(XrdOucErrInfo &Resp, const char *path, XrdOucEnv *EnvInfo)
Definition XrdCmsRedirLocal.cc:219
XrdNetAddrInfo::isPrivate
bool isPrivate()
Definition XrdNetAddrInfo.cc:200
XrdNetAddrInfo::Dialect
const char * Dialect()
Definition XrdNetAddrInfo.hh:65
XrdNetAddr
Definition XrdNetAddr.hh:42
XrdNetAddr::Set
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition XrdNetAddr.cc:216
XrdOss
Definition XrdOss.hh:499
XrdOucEnv
Definition XrdOucEnv.hh:42
XrdOucEnv::Env
char * Env(int &envlen)
Definition XrdOucEnv.hh:48
XrdOucEnv::secEnv
const XrdSecEntity * secEnv() const
Definition XrdOucEnv.hh:107
XrdOucErrInfo
Definition XrdOucErrInfo.hh:101
XrdOucErrInfo::getErrText
const char * getErrText()
Definition XrdOucErrInfo.hh:262
XrdOucErrInfo::setErrInfo
int setErrInfo(int code, const char *emsg)
Definition XrdOucErrInfo.hh:147
XrdOucErrInfo::getErrInfo
int getErrInfo()
Definition XrdOucErrInfo.hh:243
XrdOucErrInfo::getUCap
int getUCap()
Definition XrdOucErrInfo.hh:389
XrdOucStream
Definition XrdOucStream.hh:47
XrdSecEntity::addrInfo
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition XrdSecEntity.hh:80
XrdSysLogger
Definition XrdSysLogger.hh:53
XrdOucEI::uUrlOK
static const int uUrlOK
ucap: Supports async responses
Definition XrdOucErrInfo.hh:61
XrdOucEI::uLclF
static const int uLclF
ucap: Client is on a private net
Definition XrdOucErrInfo.hh:68