Windows: Query the MTU value from the registry
authorAsanka Herath <asanka@secure-endpoints.com>
Fri, 15 Jan 2010 20:39:12 +0000 (15:39 -0500)
committerJeffrey Altman <jaltman|account-1000011@unknown>
Sat, 16 Jan 2010 15:53:29 +0000 (07:53 -0800)
The syscfg_GetIFInfo() call uses the interface info returned by
GetAdaptersAddresses().  Also manually query the MTU value in the
registry for any interfaces bound to the same adapter and use the
smallest such MTU as the value returned by syscfg_GetIFInfo().

Change-Id: I8a1d487b51f6674ff6ebbf6b1f20d37b1e278279
Reviewed-on: http://gerrit.openafs.org/1105
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsreg/syscfg.c

index a980ca8..820e2f4 100644 (file)
 #include "afsreg.h"
 #include "syscfg.h"
 
+#ifdef DEBUG
+#include <strsafe.h>
+#endif
+
 static int IsLoopback(char * guid);
 int syscfg_GetIFInfo_2000(int *count, int *addrs, int *masks, int *mtus, int *flags);
 
+DWORD GetMTUForAddress(PIP_ADAPTER_ADDRESSES cAddress)
+{
+    DWORD min_mtu = 0xFFFFFFFF;         /* Default */
+
+    HKEY hk_services = NULL;
+
+    HKEY hk_adapters = NULL;
+
+    HKEY hk_adapter = NULL;
+
+    char * ipconfig = NULL;
+
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services", 0,
+                     KEY_READ, &hk_services) != ERROR_SUCCESS)
+        goto done;
+
+    if (RegOpenKeyEx(hk_services, "Tcpip\\Parameters\\Adapters", 0, KEY_READ,
+                     &hk_adapters)
+        != ERROR_SUCCESS)
+        goto done;
+
+    if (RegOpenKeyEx(hk_adapters, cAddress->AdapterName, 0, KEY_READ, &hk_adapter)
+        != ERROR_SUCCESS)
+        goto done;
+
+    {
+        DWORD cb_alloc = 0;
+        DWORD cb_ipc = 0;
+        DWORD type = 0;
+        char * this_ipc;
+
+        if (RegQueryValueEx(hk_adapter, "IpConfig", 0, NULL, NULL, &cb_ipc)
+            != ERROR_SUCCESS)
+            goto done;
+
+        cb_alloc = cb_ipc + sizeof(char) * 2;
+        ipconfig = malloc(cb_alloc);
+        if (ipconfig == NULL)
+            goto done;
+
+        if (RegQueryValueEx(hk_adapter, "IpConfig", 0, &type, ipconfig,
+                            &cb_ipc) != ERROR_SUCCESS) {
+            goto done;
+        }
+
+        if (cb_ipc < cb_alloc)
+            memset(ipconfig + cb_ipc / sizeof(char), 0,
+                   (cb_alloc - cb_ipc) / sizeof(char));
+
+        for (this_ipc = ipconfig; (this_ipc - ipconfig) < cb_alloc / sizeof(char) &&
+                 *this_ipc; this_ipc = this_ipc + (strlen(this_ipc) + 1)) {
+
+            HKEY hk_interface = NULL;
+            DWORD mtu = 0;
+            DWORD cb_mtu;
+
+            if (RegOpenKeyEx(hk_services, this_ipc, 0, KEY_READ,
+                             &hk_interface) != ERROR_SUCCESS)
+                continue;
+
+            cb_mtu = sizeof(mtu);
+            if (RegQueryValueEx(hk_interface, "MTU", NULL, NULL, &mtu,
+                                &cb_mtu) == ERROR_SUCCESS) {
+                min_mtu = min(min_mtu, mtu);
+            }
+
+            RegCloseKey(hk_interface);
+        }
+    }
+
+ done:
+    if (ipconfig)
+        free(ipconfig);
+
+    if (hk_services != NULL)
+        RegCloseKey(hk_services);
+
+    if (hk_adapters != NULL)
+        RegCloseKey(hk_adapters);
+
+    if (hk_adapter != NULL)
+        RegCloseKey(hk_adapter);
+
+    return min_mtu;
+}
+
 /* syscfg_GetIFInfo
  *
  * Retrieve IP addresses, subnet masks, MTU sizes, and flags for all
@@ -83,11 +173,11 @@ int syscfg_GetIFInfo(int *count, int *addrs, int *masks, int *mtus, int *flags)
         nConfig = -1;
         goto done;
     }
-    
+
     /* second pass to get the actual data */
     free(pIpTbl);
     pIpTbl = (PMIB_IPADDRTABLE) malloc(outBufLen);
-    
+
     dwRetVal = GetIpAddrTable(pIpTbl, &outBufLen, FALSE);
     if (dwRetVal != NO_ERROR) {
         free(pIpTbl);
@@ -95,9 +185,9 @@ int syscfg_GetIFInfo(int *count, int *addrs, int *masks, int *mtus, int *flags)
         nConfig = -1;
         goto done;
     }
-    
+
     pAddresses = (IP_ADAPTER_ADDRESSES*) malloc(sizeof(IP_ADAPTER_ADDRESSES));
-    
+
     /* first call gets required buffer size */
     if (pGetAdaptersAddresses(AF_INET, 
                               0, 
@@ -137,17 +227,28 @@ int syscfg_GetIFInfo(int *count, int *addrs, int *masks, int *mtus, int *flags)
                instance GUID, check if this is a MS loopback device */
             if (IsLoopback(cAddress->AdapterName))
                 continue;
-            
+
             /* ok. looks good.  Now fish out all the addresses from the
                address table corresponding to the interface, and add them
                to the list */
             for (i=0;i<pIpTbl->dwNumEntries;i++) {
                 if (pIpTbl->table[i].dwIndex == cAddress->IfIndex)
                 {
+                    DWORD if_mtu;
+
+                    if_mtu = GetMTUForAddress(cAddress);
+#ifdef DEBUG
+                    if (if_mtu < cAddress->Mtu) {
+                        char s[1024];
+                        StringCbPrintf(s, sizeof(s), "MTU from registry is less than MTU from adapter address (%d vs %d)\n", if_mtu, cAddress->Mtu);
+                        OutputDebugString(s);
+                    }
+#endif
+
                     if (n < maxCount) {
                         addrs[n] = ntohl(pIpTbl->table[i].dwAddr);
                         masks[n] = ntohl(pIpTbl->table[i].dwMask);
-                        mtus[n] = cAddress->Mtu;
+                        mtus[n] = min(cAddress->Mtu, if_mtu);
                         flags[n] = 0;
                         n++;
                     }