Browse Source

HPCC-8669 - Extend NAS mapping options

Allow a range as opposed to a subnet/mask to be defined for a
filter and allow a source range to apply also.

Signed-off-by: Jake Smith <jake.smith@lexisnexis.com>
Jake Smith 12 years ago
parent
commit
858fa0743a

+ 9 - 9
common/environment/dalienv.cpp

@@ -464,29 +464,29 @@ IPropertyTree *envGetNASConfiguration()
     return createPTreeFromIPT(conn->queryRoot());
 }
 
-IPropertyTree *envGetInstallNASHooks()
+IPropertyTree *envGetInstallNASHooks(SocketEndpoint *myEp)
 {
     Owned<IPropertyTree> nasPTree = envGetNASConfiguration();
-    return envGetInstallNASHooks(nasPTree);
+    return envGetInstallNASHooks(nasPTree, myEp);
 }
 
-IPropertyTree *envGetInstallNASHooks(IPropertyTree *nasPTree)
+IPropertyTree *envGetInstallNASHooks(IPropertyTree *nasPTree, SocketEndpoint *myEp)
 {
     IDaFileSrvHook *daFileSrvHook = queryDaFileSrvHook();
     if (!daFileSrvHook) // probably always installed
         return NULL;
-    daFileSrvHook->clearSubNetFilters();
+    daFileSrvHook->clearFilters();
     if (!nasPTree)
         return NULL;
-    return daFileSrvHook->addMySubnetFilters(nasPTree);
+    return daFileSrvHook->addMyFilters(nasPTree, myEp);
 }
 
-void envInstallNASHooks()
+void envInstallNASHooks(SocketEndpoint *myEp)
 {
-    Owned<IPropertyTree> installedFilters = envGetInstallNASHooks();
+    Owned<IPropertyTree> installedFilters = envGetInstallNASHooks(myEp);
 }
 
-void envInstallNASHooks(IPropertyTree *nasPTree)
+void envInstallNASHooks(IPropertyTree *nasPTree, SocketEndpoint *myEp)
 {
-    Owned<IPropertyTree> installedFilters = envGetInstallNASHooks(nasPTree);
+    Owned<IPropertyTree> installedFilters = envGetInstallNASHooks(nasPTree, myEp);
 }

+ 5 - 4
common/environment/dalienv.hpp

@@ -52,10 +52,11 @@ extern ENVIRONMENT_API bool getRemoteRunInfo(const char * keyName, const char *
 extern ENVIRONMENT_API bool envGetConfigurationDirectory(const char *category, const char *component,const char *instance, StringBuffer &dirout);
 
 extern ENVIRONMENT_API IPropertyTree *envGetNASConfiguration(); // return NAS config from environment
-extern ENVIRONMENT_API void envInstallNASHooks(); // gets NAS config and sets up NAS hooks from it
-extern ENVIRONMENT_API void envInstallNASHooks(IPropertyTree *nasPTree); // Sets NAS hooks from user-supplied info
+// These methods filter the NAS hooks based on the callers IP, unless 'myEp' is supplied.
+extern ENVIRONMENT_API void envInstallNASHooks(SocketEndpoint *myEp=NULL); // gets NAS config and sets up NAS hooks from it
+extern ENVIRONMENT_API void envInstallNASHooks(IPropertyTree *nasPTree, SocketEndpoint *myEp=NULL); // Sets NAS hooks from user-supplied info
 // like envInstallNASHooks but also returns which filters were installed
-extern ENVIRONMENT_API IPropertyTree *envGetInstallNASHooks();
-extern ENVIRONMENT_API IPropertyTree *envGetInstallNASHooks(IPropertyTree *nasPTree);
+extern ENVIRONMENT_API IPropertyTree *envGetInstallNASHooks(SocketEndpoint *myEp=NULL);
+extern ENVIRONMENT_API IPropertyTree *envGetInstallNASHooks(IPropertyTree *nasPTree, SocketEndpoint *myEp=NULL);
 
 #endif

+ 141 - 41
common/remote/rmtfile.cpp

@@ -61,31 +61,36 @@ void setLocalMountRedirect(const IpAddress &ip,const char *dir,const char *mount
 
 
 
-
 class CDaliServixFilter : public CInterface
 {
-    IpSubNet ipSubNet;
-    StringAttr dir;
-    bool trace;
-public:
-    CDaliServixFilter(IPropertyTree &filter)
+protected:
+    StringAttr dir, sourceRangeText;
+    SocketEndpointArray sourceRangeIps;
+    bool sourceRangeHasPorts, trace;
+
+    bool checkForPorts(SocketEndpointArray &ips)
     {
-        const char *subnet = filter.queryProp("@subnet");
-        const char *mask = filter.queryProp("@mask");
-        if (!ipSubNet.set(subnet, mask))
-            throw MakeStringException(0, "Invalid sub net definition: %s, %s", subnet, mask);
-        dir.set(filter.queryProp("@directory"));
-        trace = filter.getPropBool("@trace");
+        ForEachItemIn(i, ips)
+        {
+           if (ips.item(i).port)
+               return true;
+        }
+        return false;
     }
-    CDaliServixFilter(const char *subnet, const char *mask, const char *_dir, bool _trace) : dir(_dir), trace(_trace)
+public:
+    CDaliServixFilter(const char *_dir, const char *sourceRange, bool _trace) : dir(_dir), trace(_trace)
     {
-        if (!ipSubNet.set(subnet, mask))
-            throw MakeStringException(0, "Invalid sub net definition: %s, %s", subnet, mask);
+        if (sourceRange)
+        {
+            sourceRangeText.set(sourceRange);
+            sourceRangeIps.fromText(sourceRange, 0);
+            sourceRangeHasPorts = checkForPorts(sourceRangeIps);
+        }
+        else
+            sourceRangeHasPorts = false;
     }
     bool queryTrace() const { return trace; }
     const char *queryDirectory() const { return dir; }
-    const IpSubNet &querySubNet() const { return ipSubNet; }
-    bool testIp(const IpAddress &ip) const { return ipSubNet.test(ip); }
     bool testPath(const char *path) const
     {
         if (!dir) // if no dir in filter, match any
@@ -93,24 +98,109 @@ public:
         else
             return startsWith(path, dir.get());
     }
+    bool applyFilter(const SocketEndpoint &ep) const
+    {
+        if (sourceRangeText.length())
+        {
+            SocketEndpoint _ep = ep;
+            if (!sourceRangeHasPorts) // if source range doesn't have ports, only check ip
+                _ep.port = 0;
+            return NotFound != sourceRangeIps.find(_ep);
+        }
+        // NB: If no source range, use target range to decide if filter should apply
+        return testEp(ep);
+    }
+    virtual bool testEp(const SocketEndpoint &ep) const = 0;
+    virtual StringBuffer &getInfo(StringBuffer &info)
+    {
+        if (dir.length())
+            info.append(", dir=").append(dir.get());
+        if (sourceRangeText.get())
+            info.append(", sourcerange=").append(sourceRangeText.get());
+        info.append(", trace=(").append(trace ? "true" : "false").append(")");
+        return info;
+    }
 };
 
+class CDaliServixSubnetFilter : public CDaliServixFilter
+{
+    IpSubNet ipSubNet;
+public:
+    CDaliServixSubnetFilter(const char *subnet, const char *mask, const char *dir, const char *sourceRange, bool trace) :
+        CDaliServixFilter(dir, sourceRange, trace)
+    {
+        if (!ipSubNet.set(subnet, mask))
+            throw MakeStringException(0, "Invalid sub net definition: %s, %s", subnet, mask);
+    }
+    virtual bool testEp(const SocketEndpoint &ep) const
+    {
+        return ipSubNet.test(ep);
+    }
+    virtual StringBuffer &getInfo(StringBuffer &info)
+    {
+        info.append("subnet=");
+        ipSubNet.getNetText(info);
+        info.append(", mask=");
+        ipSubNet.getMaskText(info);
+        CDaliServixFilter::getInfo(info);
+        return info;
+    }
+};
+
+class CDaliServixRangeFilter : public CDaliServixFilter
+{
+    StringAttr rangeText;
+    SocketEndpointArray rangeIps;
+    bool rangeIpsHavePorts;
+public:
+    CDaliServixRangeFilter(const char *_range, const char *dir, const char *sourceRange, bool trace)
+        : CDaliServixFilter(dir, sourceRange, trace)
+    {
+        rangeText.set(_range);
+        rangeIps.fromText(_range, 0);
+        rangeIpsHavePorts = checkForPorts(rangeIps);
+    }
+    virtual bool testEp(const SocketEndpoint &ep) const
+    {
+        SocketEndpoint _ep = ep;
+        if (!rangeIpsHavePorts) // if range doesn't have ports, only check ip
+            _ep.port = 0;
+        return NotFound != rangeIps.find(_ep);
+    }
+    virtual StringBuffer &getInfo(StringBuffer &info)
+    {
+        info.append("range=").append(rangeText.get());
+        CDaliServixFilter::getInfo(info);
+        return info;
+    }
+};
+
+CDaliServixFilter *createDaliServixFilter(IPropertyTree &filterProps)
+{
+    CDaliServixFilter *filter = NULL;
+    const char *dir = filterProps.queryProp("@directory");
+    const char *sourceRange = filterProps.queryProp("@sourcerange");
+    bool trace = filterProps.queryProp("@trace");
+    if (filterProps.hasProp("@subnet"))
+        filter = new CDaliServixSubnetFilter(filterProps.queryProp("@subnet"), filterProps.queryProp("@mask"), dir, sourceRange, trace);
+    else if (filterProps.hasProp("@range"))
+        filter = new CDaliServixRangeFilter(filterProps.queryProp("@range"), dir, sourceRange, trace);
+    else
+        throw MakeStringException(0, "Unknown DaliServix filter definition");
+    return filter;
+}
+
 class CDaliServixIntercept: public CInterface, implements IDaFileSrvHook
 {
     CIArrayOf<CDaliServixFilter> filters;
 
-    void addSubnetFilter(CDaliServixFilter *filter)
+    void addFilter(CDaliServixFilter *filter)
     {
-        const IpSubNet &ipSubNet = filter->querySubNet();
-        StringBuffer msg("DaFileSrvHook: adding translateToLocal(subnet=");
-        ipSubNet.getNetText(msg);
-        msg.append(", mask=");
-        ipSubNet.getMaskText(msg);
-        if (filter->queryDirectory())
-            msg.append(", dir=").append(filter->queryDirectory());
-        msg.append(", trace=").append(filter->queryTrace() ? "true" : "false").append(")");
-        PROGLOG("%s", msg.str());
         filters.append(*filter);
+        StringBuffer msg("DaFileSrvHook: adding translateToLocal [");
+        filter->getInfo(msg);
+        msg.append("]");
+        PROGLOG("%s", msg.str());
     }
 public:
     IMPLEMENT_IINTERFACE;
@@ -128,7 +218,7 @@ public:
                 ForEachItemIn(sn, filters)
                 {
                     CDaliServixFilter &filter = filters.item(sn);
-                    if (filter.testIp(ep))
+                    if (filter.testEp(ep))
                     {
                         StringBuffer lPath;
                         filename.getLocalPath(lPath);
@@ -159,12 +249,17 @@ public:
         }
         return NULL;
     }
-    virtual void addSubnetFilter(const char *subnet, const char *mask, const char *dir, bool trace)
+    virtual void addSubnetFilter(const char *subnet, const char *mask, const char *dir, const char *sourceRange, bool trace)
+    {
+        Owned<CDaliServixFilter> filter = new CDaliServixSubnetFilter(subnet, mask, dir, sourceRange, trace);
+        addFilter(filter.getClear());
+    }
+    virtual void addRangeFilter(const char *range, const char *dir, const char *sourceRange, bool trace)
     {
-        Owned<CDaliServixFilter> filter = new CDaliServixFilter(subnet, mask, dir, trace);
-        addSubnetFilter(filter.getClear());
+        Owned<CDaliServixFilter> filter = new CDaliServixRangeFilter(range, dir, sourceRange, trace);
+        addFilter(filter.getClear());
     }
-    virtual IPropertyTree *addSubnetFilters(IPropertyTree *config, const IpAddress *myIp)
+    virtual IPropertyTree *addFilters(IPropertyTree *config, const SocketEndpoint *myEp)
     {
         if (!config)
             return NULL;
@@ -172,11 +267,11 @@ public:
         Owned<IPropertyTreeIterator> iter = config->getElements("Filter");
         ForEach(*iter)
         {
-            Owned<CDaliServixFilter> filter = new CDaliServixFilter(iter->query());
-            // Only add filters where myIP is within subnet
-            if (!myIp || filter->testIp(*myIp))
+            Owned<CDaliServixFilter> filter = createDaliServixFilter(iter->query());
+            // Only add filters where myIP matches filter criteria
+            if (!myEp || filter->applyFilter(*myEp))
             {
-                addSubnetFilter(filter.getClear());
+                addFilter(filter.getClear());
                 if (!result)
                     result.setown(createPTree());
                 result->addPropTree("Filter", LINK(&iter->query()));
@@ -184,13 +279,18 @@ public:
         }
         return result.getClear();
     }
-    virtual IPropertyTree *addMySubnetFilters(IPropertyTree *config)
+    virtual IPropertyTree *addMyFilters(IPropertyTree *config, SocketEndpoint *myEp)
     {
-        IpAddress ip;
-        GetHostIp(ip);
-        return addSubnetFilters(config, &ip);
+        if (myEp)
+            return addFilters(config, myEp);
+        else
+        {
+            SocketEndpoint ep;
+            GetHostIp(ep);
+            return addFilters(config, &ep);
+        }
     }
-    virtual void clearSubNetFilters()
+    virtual void clearFilters()
     {
         filters.kill();
     }

+ 5 - 4
common/remote/rmtfile.hpp

@@ -39,10 +39,11 @@ extern REMOTE_API void filenameToUrl(StringBuffer & out, const char * filename);
 
 interface IDaFileSrvHook : extends IRemoteFileCreateHook
 {
-    virtual void addSubnetFilter(const char *subnet, const char *mask, const char *dir, bool trace) = 0;
-    virtual IPropertyTree *addSubnetFilters(IPropertyTree *filters, const IpAddress *ipAddress) = 0;
-    virtual IPropertyTree *addMySubnetFilters(IPropertyTree *filters) = 0;
-    virtual void clearSubNetFilters() = 0;
+    virtual void addSubnetFilter(const char *subnet, const char *mask, const char *dir, const char *sourceRange, bool trace) = 0;
+    virtual void addRangeFilter(const char *range, const char *dir, const char *sourceRange, bool trace) = 0;
+    virtual IPropertyTree *addFilters(IPropertyTree *filters, const SocketEndpoint *ipAddress) = 0;
+    virtual IPropertyTree *addMyFilters(IPropertyTree *filters, SocketEndpoint *myEp=NULL) = 0;
+    virtual void clearFilters() = 0;
 };
 extern REMOTE_API IDaFileSrvHook *queryDaFileSrvHook();
 extern REMOTE_API unsigned short getDaliServixPort();  // assumed just the one for now

+ 4 - 3
thorlcr/master/thmastermain.cpp

@@ -609,9 +609,10 @@ int main( int argc, char *argv[]  )
 
         if (globals->getPropBool("@useNASTranslation", true))
         {
-            Owned<IPropertyTree> filteredNasConfig = envGetInstallNASHooks();
-            if (filteredNasConfig)
-                globals->setPropTree("NAS", filteredNasConfig.getClear()); // for use by slaves
+            Owned<IPropertyTree> nasConfig = envGetNASConfiguration();
+            if (nasConfig)
+                globals->setPropTree("NAS", nasConfig.getClear()); // for use by slaves
+            Owned<IPropertyTree> masterNasFilters = envGetInstallNASHooks(nasConfig, &thorEp);
         }
         
         HardwareInfo hdwInfo;

+ 2 - 1
thorlcr/slave/thslavemain.cpp

@@ -307,12 +307,13 @@ int main( int argc, char *argv[]  )
         markNodeCentral(masterEp);
         if (RegisterSelf(masterEp))
         {
+            MilliSleep(20000);
             if (globals->getPropBool("Debug/@slaveDaliClient"))
                 enableThorSlaveAsDaliClient();
 
             IDaFileSrvHook *daFileSrvHook = queryDaFileSrvHook();
             if (daFileSrvHook) // probably always installed
-                daFileSrvHook->addSubnetFilters(globals->queryPropTree("NAS"), NULL);
+                daFileSrvHook->addFilters(globals->queryPropTree("NAS"), &slfEp);
 
             StringBuffer thorPath;
             globals->getProp("@thorPath", thorPath);