windows-misc-20070619
[openafs.git] / src / WINNT / afsd / lanahelper.cpp
index d704ada..8610b1d 100644 (file)
@@ -35,6 +35,7 @@ SOFTWARE.
 #include <malloc.h>
 #include <stdio.h>
 #include <lanahelper.h>
+#include <WINNT\afsreg.h>
 
 #define NOLOGGING
 #ifndef NOLOGGING
@@ -55,11 +56,13 @@ extern "C" {
 }
 #endif
 
-static const char *szAFSConfigKeyName = "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
 static const char *szNetbiosNameValue = "NetbiosName";
 static const char *szIsGatewayValue = "IsGateway";
 static const char *szLanAdapterValue = "LanAdapter";
+#ifdef USE_FINDLANABYNAME
 static const char *szNoFindLanaByName = "NoFindLanaByName";
+#endif
+static const char *szForceLanaLoopback = "ForceLanaLoopback";
 
 // Use the IShellFolder API to get the connection name for the given Guid.
 static HRESULT lana_ShellGetNameFromGuidW(WCHAR *wGuid, WCHAR *wName, int NameSize)
@@ -312,9 +315,9 @@ extern "C" LANAINFO * lana_FindLanaByName(const char *LanaName)
         if ((lanamap[i].flags & 1) == 0)
             continue;
 
-               // check for an IPv4 binding
-               if(!strstr(pBind,"_Tcpip_"))
-                       continue;
+        // check for an IPv4 binding
+        if(!strstr(pBind,"_Tcpip_"))
+            continue;
 
         // Find the beginning of the GUID.
         guid = strchr(pBind, '{');
@@ -381,7 +384,7 @@ extern "C" lana_number_t lana_FindLoopback(void)
         return LANA_INVALID;
     }
     for (i = 0; i < lana_list.length; i++) {
-       if (lana_IsLoopback(lana_list.lana[i])) {
+       if (lana_IsLoopback(lana_list.lana[i],TRUE)) {
            // Found one, return it.
 #ifndef NOLOGGING
            afsi_log("lana_FindLoopback: Found LAN adapter %d",
@@ -394,10 +397,40 @@ extern "C" lana_number_t lana_FindLoopback(void)
     return LANA_INVALID;
 }
 
+/* Returns TRUE if all adapters are loopback adapters */
+extern "C" BOOL lana_OnlyLoopback(void)
+{
+    NCB ncb;
+    LANA_ENUM lana_list;
+    int status;
+    int i;
+
+    memset(&ncb, 0, sizeof(ncb));
+    ncb.ncb_command = NCBENUM;
+    ncb.ncb_buffer = (UCHAR *) &lana_list;
+    ncb.ncb_length = sizeof(lana_list);
+    status = Netbios(&ncb);
+    if (status != 0) {
+#ifndef NOLOGGING
+        afsi_log("Netbios NCBENUM failed: status %ld", status);
+#endif
+        return FALSE;
+    }
+    for (i = 0; i < lana_list.length; i++) {
+       if (!lana_IsLoopback(lana_list.lana[i],FALSE)) {
+           // Found one non-Loopback adapter
+           return FALSE;
+       }
+    }
+    // All adapters are loopback
+    return TRUE;
+}
+
 // Is the given lana a Windows Loopback Adapter?
 // TODO: implement a better check for loopback
 // TODO: also check for proper bindings (IPv4)
-extern "C" BOOL lana_IsLoopback(lana_number_t lana)
+// For VMWare we only check the first five octets since the last one may vary
+extern "C" BOOL lana_IsLoopback(lana_number_t lana, BOOL reset)
 {
     NCB ncb;
     struct {
@@ -405,23 +438,42 @@ extern "C" BOOL lana_IsLoopback(lana_number_t lana)
         NAME_BUFFER names[MAX_LANA+1];
     } astat;
     unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
+    unsigned char kVista_WLA_MAC[6] = { 0x7F, 0x00, 0x00, 0x01, 0x4f, 0x50 };
+#ifdef USE_VMWARE
+    unsigned char kVMWare_MAC[5] = { 0x00, 0x50, 0x56, 0xC0, 0x00 };
+#endif
     int status;
+    HKEY hkConfig;
+    LONG rv;
+    int regLana = -1;
+    DWORD dummyLen;
 
-    // Reset the adapter: in Win32, this is required for every process, and
-    // acts as an init call, not as a real hardware reset.
-    memset(&ncb, 0, sizeof(ncb));
-    ncb.ncb_command = NCBRESET;
-    ncb.ncb_callname[0] = 100;
-    ncb.ncb_callname[2] = 100;
-    ncb.ncb_lana_num = lana;
-    status = Netbios(&ncb);
-    if (status == 0)
-        status = ncb.ncb_retcode;
-    if (status != 0) {
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,AFSREG_CLT_SVC_PARAM_SUBKEY,0,KEY_READ,&hkConfig);
+    if (rv == ERROR_SUCCESS) {
+        rv = RegQueryValueEx(hkConfig, szForceLanaLoopback, NULL, NULL, (LPBYTE) &regLana, &dummyLen);
+        RegCloseKey(hkConfig);
+
+        if (regLana == lana)
+            return TRUE;
+    }
+
+    if (reset) {
+       // Reset the adapter: in Win32, this is required for every process, and
+       // acts as an init call, not as a real hardware reset.
+       memset(&ncb, 0, sizeof(ncb));
+       ncb.ncb_command = NCBRESET;
+       ncb.ncb_callname[0] = 100;
+       ncb.ncb_callname[2] = 100;
+       ncb.ncb_lana_num = lana;
+       status = Netbios(&ncb);
+       if (status == 0)
+           status = ncb.ncb_retcode;
+       if (status != 0) {
 #ifndef NOLOGGING
-       afsi_log("NCBRESET failed: lana %u, status %ld", lana, status);
+           afsi_log("NCBRESET failed: lana %u, status %ld", lana, status);
 #endif
-        return FALSE;
+           return FALSE;
+       }
     }
 
     // Use the NCBASTAT command to get the adapter address.
@@ -440,7 +492,12 @@ extern "C" BOOL lana_IsLoopback(lana_number_t lana)
 #endif
         return FALSE;
     }
-    return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0);
+    return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0 ||
+           memcmp(astat.status.adapter_address, kVista_WLA_MAC, 6) == 0 
+#ifdef USE_VMWARE
+             || memcmp(astat.status.adapter_address, kVMWare_MAC, 5) == 0
+#endif
+             );
 }
 
 // Get the netbios named used/to-be-used by the AFS SMB server.
@@ -467,141 +524,158 @@ extern "C" BOOL lana_IsLoopback(lana_number_t lana)
 // buffer is assumed to hold at least MAX_NB_NAME_LENGTH bytes.
 //
 // flags :
-//        LANA_NETBIOS_NAME_IN : Use the values of *pLana and *pIsGateway as [in] parameters.
-//        LANA_NETBIOS_NAME_SUFFIX : Only return the suffix of netbios name
-//               LANA_NETBIOS_NAME_FULL : Return full netbios name
+//      LANA_NETBIOS_NAME_IN : Use the values of *pLana and *pIsGateway as [in] parameters.
+//      LANA_NETBIOS_NAME_SUFFIX : Only return the suffix of netbios name
+//      LANA_NETBIOS_NAME_FULL : Return full netbios name
 extern "C" long lana_GetUncServerNameEx(char *buffer, lana_number_t * pLana, int * pIsGateway, int flags) {
     HKEY hkConfig;
-       DWORD dummyLen;
-       LONG rv;
-       int regLana;
-       int regGateway, regNoFindLanaByName;
-       TCHAR regNbName[MAX_NB_NAME_LENGTH];
-       TCHAR nbName[MAX_NB_NAME_LENGTH];
-       TCHAR hostname[MAX_COMPUTERNAME_LENGTH+1];
-
-       rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,szAFSConfigKeyName,0,KEY_READ,&hkConfig);
-       if(rv == ERROR_SUCCESS) {
-               if(!(flags & LANA_NETBIOS_NAME_IN) || !pLana) {
-                       dummyLen = sizeof(regLana);
-                       rv = RegQueryValueEx(hkConfig, szLanAdapterValue, NULL, NULL, (LPBYTE) &regLana, &dummyLen);
-                       if(rv != ERROR_SUCCESS) regLana = -1;
-               } else
-                       regLana = *pLana;
-
-               if(!(flags & LANA_NETBIOS_NAME_IN) || !pIsGateway) {
-                       dummyLen = sizeof(regGateway);
-                       rv = RegQueryValueEx(hkConfig, szIsGatewayValue, NULL, NULL, (LPBYTE) &regGateway, &dummyLen);
-                       if(rv != ERROR_SUCCESS) regGateway = 0;
-               } else
-                       regGateway = *pIsGateway;
-
-               dummyLen = sizeof(regNoFindLanaByName);
-               rv = RegQueryValueEx(hkConfig, szNoFindLanaByName, NULL, NULL, (LPBYTE) &regNoFindLanaByName, &dummyLen);
-               if(rv != ERROR_SUCCESS) regNoFindLanaByName = 0;
-
-               // Do not care if the call fails for insufficient buffer size.  We are not interested
-               // in netbios names over 15 chars.
-               dummyLen = sizeof(regNbName);
-               rv = RegQueryValueEx(hkConfig, szNetbiosNameValue, NULL, NULL, (LPBYTE) &regNbName, &dummyLen);
-               if(rv != ERROR_SUCCESS) regNbName[0] = 0;
-               else regNbName[15] = 0;
-
-               RegCloseKey(hkConfig);
+    DWORD dummyLen;
+    LONG rv;
+    int regLana;
+    int regGateway;
+#ifdef USE_FINDLANABYNAME
+    int regNoFindLanaByName;
+#endif
+    TCHAR regNbName[MAX_NB_NAME_LENGTH] = "AFS";
+    TCHAR nbName[MAX_NB_NAME_LENGTH];
+    TCHAR hostname[MAX_COMPUTERNAME_LENGTH+1];
+
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,AFSREG_CLT_SVC_PARAM_SUBKEY,0,KEY_READ,&hkConfig);
+    if(rv == ERROR_SUCCESS) {
+       if(!(flags & LANA_NETBIOS_NAME_IN) || !pLana) {
+           dummyLen = sizeof(regLana);
+           rv = RegQueryValueEx(hkConfig, szLanAdapterValue, NULL, NULL, (LPBYTE) &regLana, &dummyLen);
+           if(rv != ERROR_SUCCESS) 
+               regLana = -1;
+       } else
+           regLana = *pLana;
+
+       if(!(flags & LANA_NETBIOS_NAME_IN) || !pIsGateway) {
+           dummyLen = sizeof(regGateway);
+           rv = RegQueryValueEx(hkConfig, szIsGatewayValue, NULL, NULL, (LPBYTE) &regGateway, &dummyLen);
+           if(rv != ERROR_SUCCESS) 
+               regGateway = 0;
+       } else
+           regGateway = *pIsGateway;
+
+#ifdef USE_FINDLANABYNAME
+       dummyLen = sizeof(regNoFindLanaByName);
+       rv = RegQueryValueEx(hkConfig, szNoFindLanaByName, NULL, NULL, (LPBYTE) &regNoFindLanaByName, &dummyLen);
+       if(rv != ERROR_SUCCESS) 
+           regNoFindLanaByName = 0;
+#endif
+
+       // Do not care if the call fails for insufficient buffer size.  We are not interested
+       // in netbios names over 15 chars.
+       dummyLen = sizeof(regNbName);
+       rv = RegQueryValueEx(hkConfig, szNetbiosNameValue, NULL, NULL, (LPBYTE) &regNbName, &dummyLen);
+       if(rv != ERROR_SUCCESS) 
+           strcpy(regNbName, "AFS");
+       else 
+           regNbName[15] = 0;
+
+       RegCloseKey(hkConfig);
+    } else {
+       if(flags & LANA_NETBIOS_NAME_IN) {
+           regLana = (pLana)? *pLana: -1;
+           regGateway = (pIsGateway)? *pIsGateway: 0;
        } else {
-               if(flags & LANA_NETBIOS_NAME_IN) {
-                       regLana = (pLana)? *pLana: -1;
-                       regGateway = (pIsGateway)? *pIsGateway: 0;
-               } else {
-                       regLana = -1;
-                       regGateway = 0;
-               }
-        regNoFindLanaByName = 0;
-               regNbName[0] = 0;
+           regLana = -1;
+           regGateway = 0;
        }
+#ifdef USE_FINDLANABYNAME 
+        regNoFindLanaByName = 0;
+#endif
+       strcpy(regNbName, "AFS");
+    }
 
     if(regLana < 0 || regLana > MAX_LANA) 
         regLana = -1;
 
-       if(regLana == -1) {
-               LANAINFO *lanaInfo = NULL;
+    if(regLana == -1) {
+       LANAINFO *lanaInfo = NULL;
         int nLana = LANA_INVALID;
 
+#ifdef USE_FINDLANABYNAME
         if (!regNoFindLanaByName)
             lanaInfo = lana_FindLanaByName("AFS");
-               if(lanaInfo != NULL) {
+#endif
+       if(lanaInfo != NULL) {
             nLana = lanaInfo[0].lana_number;
-                       free(lanaInfo);
-               } else
-                       nLana = LANA_INVALID;
-
-               if(nLana == LANA_INVALID && !regGateway) {
-                       nLana = lana_FindLoopback();
-               }
-               if(nLana != LANA_INVALID) 
-            regLana = nLana;
+           free(lanaInfo);
+       } else
+           nLana = LANA_INVALID;
+
+       if(nLana == LANA_INVALID && !regGateway) {
+           nLana = lana_FindLoopback();
        }
+       if(nLana != LANA_INVALID) 
+            regLana = nLana;
+       }       
 
-       if(regNbName[0] &&
-       (regLana >=0 && lana_IsLoopback((lana_number_t) regLana))) {
+    if(regNbName[0] &&
+       (regLana >=0 && lana_IsLoopback((lana_number_t) regLana,FALSE)))        
+    {
         strncpy(nbName,regNbName,15);
         nbName[16] = 0;
         strupr(nbName);
+    } else {
+       char * dot;
+
+       if(flags & LANA_NETBIOS_NAME_SUFFIX) {
+           strcpy(nbName,"-AFS");
        } else {
-               char * dot;
-
-               if(flags & LANA_NETBIOS_NAME_SUFFIX) {
-                       strcpy(nbName,"-AFS");
-               } else {
-                       dummyLen = sizeof(hostname);
-                       // assume we are not a cluster.
-                       rv = GetComputerName(hostname, &dummyLen);
-                       if(!SUCCEEDED(rv)) { // should not happen, but...
-                               return rv;
-                       }
-                       strncpy(nbName, hostname, 11);
-                       nbName[11] = 0;
-                       if(dot = strchr(nbName,'.'))
-                               *dot = 0;
-                       strcat(nbName,"-AFS");
-               }
+           dummyLen = sizeof(hostname);
+           // assume we are not a cluster.
+           rv = GetComputerName(hostname, &dummyLen);
+           if(!SUCCEEDED(rv)) { // should not happen, but...
+               return rv;
+           }
+           strncpy(nbName, hostname, 11);
+           nbName[11] = 0;
+           if(dot = strchr(nbName,'.'))
+               *dot = 0;
+           strcat(nbName,"-AFS");
        }
+    }
 
-       if(pLana) *pLana = regLana;
-       if(pIsGateway) *pIsGateway = regGateway;
+    if(pLana) 
+       *pLana = regLana;
+    if(pIsGateway) 
+       *pIsGateway = regGateway;
 
-       strcpy(buffer, nbName);
+    strcpy(buffer, nbName);
 
-       return ERROR_SUCCESS;
+    return ERROR_SUCCESS;
 }
 
 extern "C" void lana_GetUncServerNameDynamic(int lanaNumber, BOOL isGateway, TCHAR *name, int type) {
-       char szName[MAX_NB_NAME_LENGTH];
-       lana_number_t lana = (lana_number_t) lanaNumber;
-       int gateway = (int) isGateway;
+    char szName[MAX_NB_NAME_LENGTH];
+    lana_number_t lana = (lana_number_t) lanaNumber;
+    int gateway = (int) isGateway;
 
-       if(SUCCEEDED(lana_GetUncServerNameEx(szName, &lana, &gateway, LANA_NETBIOS_NAME_IN | type))) {
+    if(SUCCEEDED(lana_GetUncServerNameEx(szName, &lana, &gateway, LANA_NETBIOS_NAME_IN | type))) {
 #ifdef _UNICODE
-               mbswcs(name,szName,MAX_NB_NAME_LENGTH);
+       mbswcs(name,szName,MAX_NB_NAME_LENGTH);
 #else
-               strncpy(name,szName,MAX_NB_NAME_LENGTH);
+       strncpy(name,szName,MAX_NB_NAME_LENGTH);
 #endif
-       } else
-               *name = _T('\0');
+    } else
+       *name = _T('\0');
 }
 
 extern "C" void lana_GetUncServerName(TCHAR *name, int type) {
-       char szName[MAX_NB_NAME_LENGTH];
+    char szName[MAX_NB_NAME_LENGTH];
 
-       if(SUCCEEDED(lana_GetUncServerNameEx(szName,NULL,NULL,type))) {
+    if(SUCCEEDED(lana_GetUncServerNameEx(szName,NULL,NULL,type))) {
 #ifdef _UNICODE
-               mbswcs(name,szName,MAX_NB_NAME_LENGTH);
-#else
-               strncpy(name,szName,MAX_NB_NAME_LENGTH);
+       mbswcs(name,szName,MAX_NB_NAME_LENGTH);
+#else  
+       strncpy(name,szName,MAX_NB_NAME_LENGTH);
 #endif
-       } else {
-        *name = _T('\0');
-       }
+    } else {
+       *name = _T('\0');
+    }
 }
 
 extern "C" void lana_GetAfsNameString(int lanaNumber, BOOL isGateway, TCHAR* name)
@@ -613,9 +687,9 @@ extern "C" void lana_GetAfsNameString(int lanaNumber, BOOL isGateway, TCHAR* nam
 
 extern "C" void lana_GetNetbiosName(LPTSTR pszName, int type)
 {
-       HKEY hkCfg;
+    HKEY hkCfg;
     TCHAR name[MAX_NB_NAME_LENGTH];
-       DWORD dummyLen;
+    DWORD dummyLen;
 
     memset(name, 0, sizeof(name));
     if (GetVersion() >= 0x80000000) // not WindowsNT
@@ -626,12 +700,12 @@ extern "C" void lana_GetNetbiosName(LPTSTR pszName, int type)
             return;
         }
 
-               if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,szAFSConfigKeyName,0,KEY_READ,&hkCfg) == ERROR_SUCCESS) {
-                       dummyLen = sizeof(name);
-                       if(RegQueryValueEx(hkCfg,TEXT("Gateway"),NULL,NULL,(LPBYTE) name,&dummyLen) == ERROR_SUCCESS)
-                               name[0] = _T('\0');
-                       RegCloseKey(hkCfg);
-               }
+       if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,AFSREG_CLT_SVC_PARAM_SUBKEY,0,KEY_READ,&hkCfg) == ERROR_SUCCESS) {
+           dummyLen = sizeof(name);
+           if(RegQueryValueEx(hkCfg,TEXT("Gateway"),NULL,NULL,(LPBYTE) name,&dummyLen) == ERROR_SUCCESS)
+               name[0] = _T('\0');
+           RegCloseKey(hkCfg);
+       }
 
         if (_tcslen(name) == 0)
         {
@@ -639,13 +713,13 @@ extern "C" void lana_GetNetbiosName(LPTSTR pszName, int type)
             return;
         }
 
-               _tcscpy(pszName, name);
+       _tcscpy(pszName, name);
         _tcscat(pszName, TEXT("-afs"));
         return;
     }
 
     lana_GetUncServerName(name,type);
-       _tcslwr(name);
+    _tcslwr(name);
     _tcscpy(pszName, name);
     return;
 }