diff --git a/src/XrdCms/XrdCmsRedirLocal.cc b/src/XrdCms/XrdCmsRedirLocal.cc new file mode 100644 index 00000000000..346d9875fef --- /dev/null +++ b/src/XrdCms/XrdCmsRedirLocal.cc @@ -0,0 +1,162 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +// Author: Paul-Niklas Kramp +// Jan Knedlik +//------------------------------------------------------------------------------ +// 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 . +//------------------------------------------------------------------------------ + +#include + +//------------------------------------------------------------------------------ +//! Necessary implementation for XRootD to get the Plug-in +//------------------------------------------------------------------------------ +extern "C" XrdCmsClient *XrdCmsGetClient(XrdSysLogger *Logger, int opMode, + int myPort, XrdOss *theSS) { + XrdCmsRedirLocal *plugin = new XrdCmsRedirLocal(Logger, opMode, myPort, theSS); + return plugin; +} + +//------------------------------------------------------------------------------ +//! Constructor +//------------------------------------------------------------------------------ +XrdCmsRedirLocal::XrdCmsRedirLocal(XrdSysLogger *Logger, int opMode, int myPort, + XrdOss *theSS) : XrdCmsClient(amLocal) { + nativeCmsFinder = new XrdCmsFinderRMT(Logger, opMode, myPort); + this->theSS = theSS; + readOnlyredirect = false; +} +//------------------------------------------------------------------------------ +//! Destructor +//------------------------------------------------------------------------------ +XrdCmsRedirLocal::~XrdCmsRedirLocal() { delete nativeCmsFinder; } + +//------------------------------------------------------------------------------ +//! Configure the nativeCmsFinder +//------------------------------------------------------------------------------ +int XrdCmsRedirLocal::Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo) { + loadConfig(cfn); + if (nativeCmsFinder) + return nativeCmsFinder->Configure(cfn, Parms, EnvInfo); + return 0; +} + +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){ + // get next word in lower case + std::string readWord = std::string(Config.GetWord(true));//to lower case + if(readWord.find("true") != string::npos){ + readOnlyredirect = true; + } + else { + readOnlyredirect = false; + } + } + } + Config.Close(); +} + +//------------------------------------------------------------------------------ +//! Preconditions: +//! Client Protocol Version is >= 784 +//! Flag is one of: SFS_O_RDONLY, SFS_O_RDWR, SFS_O_WRONLY, SFS_O_CREAT, SFS_O_TRUNC +//! Locate the file, get Client IP and target IP. +//! 1) If both are private, redirect to local does apply. +//! set ErrInfo of param Resp and return SFS_REDIRECT. +//! 2) Not both are private, redirect to local does NOT apply. +//! return nativeCmsFinder->Locate, for normal redirection procedure +//! +//! @Param Resp: Either set manually here or passed to nativeCmsFinder->Locate +//! @Param path: The path of the file, passed to nativeCmsFinder->Locate +//! @Param flags: The open flags, passed to nativeCmsFinder->Locate +//! @Param EnvInfo: Contains the secEnv, which contains the addressInfo of the +//! Client. Checked to see if redirect to local conditions apply +//------------------------------------------------------------------------------ +int XrdCmsRedirLocal::Locate(XrdOucErrInfo &Resp, const char *path, int flags, + XrdOucEnv *EnvInfo) { + int rcode = 0; + if (nativeCmsFinder) { + // get regular target host + rcode = nativeCmsFinder->Locate(Resp, path, flags, EnvInfo); + // 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; + + // 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; + + // 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 + // build a buffer with a total acceptable buffer length, + // which must have a larger capacity than localroot and filename concatenated + int rc = 0; + int maxPathLength = 4096; + char *buff = new char[maxPathLength]; + // prepend oss.localroot + const char *ppath = theSS->Lfn2Pfn(path, buff, maxPathLength, rc); + // set info which will be sent to client + Resp.setErrInfo(-1, ppath); + delete[] buff; + return SFS_REDIRECT; + } + return rcode; +} + +//------------------------------------------------------------------------------ +//! Space +//! Calls nativeCmsFinder->Space +//------------------------------------------------------------------------------ +int XrdCmsRedirLocal::Space(XrdOucErrInfo &Resp, const char *path, + XrdOucEnv *EnvInfo) { + if (nativeCmsFinder) + return nativeCmsFinder->Space(Resp, path, EnvInfo); + return 0; +} + +XrdVERSIONINFO(XrdCmsGetClient, XrdCmsRedirLocal); diff --git a/src/XrdCms/XrdCmsRedirLocal.hh b/src/XrdCms/XrdCmsRedirLocal.hh new file mode 100644 index 00000000000..01965a7f8da --- /dev/null +++ b/src/XrdCms/XrdCmsRedirLocal.hh @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +// Author: Paul-Niklas Kramp +// Jan Knedlik +//------------------------------------------------------------------------------ +// 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 . +//------------------------------------------------------------------------------ + + +/* README: + Options for xrootd config + - Enable: + - Enable with ofs.cmslib libXrdCmsRedirectLocal.so + - allow only readonly request to be redirected to local, default is false + - XrdCmsRedirLocal.readonlyredirect true +*/ + +#ifndef XRDCMSREDIRPLUGIN_HH_ +#define XRDCMSREDIRPLUGIN_HH_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class XrdCmsRedirLocal : public XrdCmsClient { +public: + XrdCmsRedirLocal(XrdSysLogger *Logger, int opMode, int myPort, XrdOss *theSS); + ~XrdCmsRedirLocal(); + int Configure(const char *cfn, char *Parms, XrdOucEnv *EnvInfo); + void loadConfig(const char *filename); + int Locate(XrdOucErrInfo &Resp, const char *path, int flags, + XrdOucEnv *EnvInfo); + + int Space(XrdOucErrInfo &Resp, const char *path, XrdOucEnv *EnvInfo); + void Added(const char *path, int Pend = 0) { + nativeCmsFinder->Added(path, Pend); + } + int Forward(XrdOucErrInfo &Resp, const char *cmd, const char *arg1 = 0, + const char *arg2 = 0, XrdOucEnv *Env1 = 0, XrdOucEnv *Env2 = 0) { + return nativeCmsFinder->Forward(Resp, cmd, arg1, arg2, Env1, Env2); + } + int isRemote() { return nativeCmsFinder->isRemote(); } + XrdOucTList *Managers() { return nativeCmsFinder->Managers(); } + int Prepare(XrdOucErrInfo &Resp, XrdSfsPrep &pargs, XrdOucEnv *Info = 0) { + return nativeCmsFinder->Prepare(Resp, pargs, Info); + } + void Removed(const char *path) { return nativeCmsFinder->Removed(path); } + void Resume(int Perm = 1) { nativeCmsFinder->Resume(Perm); } + void Suspend(int Perm = 1) { nativeCmsFinder->Suspend(Perm); } + int Resource(int n) { return nativeCmsFinder->Resource(n); } + int Reserve(int n = 1) { return nativeCmsFinder->Reserve(n); } + int Release(int n = 1) { return nativeCmsFinder->Release(n); } + + //--------------------------------------------------------------------------- + //! used to forward requests to CmsFinder with regular implementation + //--------------------------------------------------------------------------- + XrdCmsClient *nativeCmsFinder; + XrdOss *theSS; + bool readOnlyredirect; +}; + +#endif // XRDCMSREDIRPLUGIN_HH_ diff --git a/src/XrdPlugins.cmake b/src/XrdPlugins.cmake index 1d481a2d8f0..b605e70da02 100644 --- a/src/XrdPlugins.cmake +++ b/src/XrdPlugins.cmake @@ -7,6 +7,7 @@ include( XRootDCommon ) set( LIB_XRD_BWM XrdBwm-${PLUGIN_VERSION} ) set( LIB_XRD_N2NO2P XrdN2No2p-${PLUGIN_VERSION} ) set( LIB_XRD_PSS XrdPss-${PLUGIN_VERSION} ) +set( LIB_XRD_CMSREDIRL XrdCmsRedirectLocal-${PLUGIN_VERSION} ) set( LIB_XRD_GPFS XrdOssSIgpfsT-${PLUGIN_VERSION} ) set( LIB_XRD_ZCRC32 XrdCksCalczcrc32-${PLUGIN_VERSION} ) set( LIB_XRD_THROTTLE XrdThrottle-${PLUGIN_VERSION} ) @@ -147,9 +148,26 @@ set_target_properties( INTERFACE_LINK_LIBRARIES "" LINK_INTERFACE_LIBRARIES "" ) +#------------------------------------------------------------------------------- +# The XrdCmsRedirLocal module +#------------------------------------------------------------------------------- +add_library( + ${LIB_XRD_CMSREDIRL} + MODULE + XrdCms/XrdCmsRedirLocal.cc XrdCms/XrdCmsRedirLocal.hh ) + +target_link_libraries( + ${LIB_XRD_CMSREDIRL} ) + +set_target_properties( + ${LIB_XRD_CMSREDIRL} + PROPERTIES + INTERFACE_LINK_LIBRARIES "" + LINK_INTERFACE_LIBRARIES "" ) + #------------------------------------------------------------------------------- # Install #------------------------------------------------------------------------------- install( - TARGETS ${LIB_XRD_PSS} ${LIB_XRD_BWM} ${LIB_XRD_GPFS} ${LIB_XRD_ZCRC32} ${LIB_XRD_THROTTLE} ${LIB_XRD_N2NO2P} + TARGETS ${LIB_XRD_PSS} ${LIB_XRD_BWM} ${LIB_XRD_GPFS} ${LIB_XRD_ZCRC32} ${LIB_XRD_THROTTLE} ${LIB_XRD_N2NO2P} ${LIB_XRD_CMSREDIRL} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )