Hi,

A user of Cygwin/Xfree86 reported that cygwin did not report an interface
for his wireless network adapter. It seems that the GetIfTable function
did not return all network adapters on his computer. As a workaround to
this problem i changed the code to use GetIfEntry for each configured
address. 

I also had to change the algorithm for finding all addresses configured
for one network adapter and changed the previous code which could only
enumerate 10 addresses per adapter to use sprintf and raised that limit too.

I also added code for getting the device metric for an interface. I'm 
not sure if this is correctly solved and I have no problems with removing 
this part again. 

2002-11-09  Alexander Gottwald <[EMAIL PROTECTED]>

    * net.cc (get_2k_ifconf): Get the interface entries with the GetIfEntry 
    call intead of the GetIfTable call. Query the interface metric from the 
    IpForwardTable. Clean-up multiple IP address naming.
    
bye
    ago
-- 
 [EMAIL PROTECTED] 
 http://www.gotti.org           ICQ: 126018723
--- winsup/cygwin/net.cc.orig   Sat Nov  9 18:36:52 2002
+++ winsup/cygwin/net.cc        Sat Nov  9 18:38:23 2002
@@ -1216,125 +1216,189 @@ static void
 get_2k_ifconf (struct ifconf *ifc, int what)
 {
   int cnt = 0;
-  char eth[2] = "/", ppp[2] = "/", slp[2] = "/", sub[2] = "0", tok[2] = "/";
+  int ethId = 0, pppId = 0, slpId = 0, tokId = 0; 
 
   /* Union maps buffer to correct struct */
   struct ifreq *ifr = ifc->ifc_req;
 
-  DWORD if_cnt, ip_cnt, lip, lnp;
-  DWORD siz_if_table = 0;
+  DWORD ip_cnt, ipf_cnt, lip, lnp;
   DWORD siz_ip_table = 0;
-  PMIB_IFTABLE ift;
+  DWORD siz_ipfwd_table = 0;
   PMIB_IPADDRTABLE ipt;
+  PMIB_IFROW ifrow;
+  PMIB_IPFORWARDTABLE ipfwdt;
   struct sockaddr_in *sa = NULL;
   struct sockaddr *so = NULL;
 
-  if (GetIfTable (NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
-      GetIpAddrTable (NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
-      (ift = (PMIB_IFTABLE) alloca (siz_if_table)) &&
-      (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) &&
-      !GetIfTable (ift, &siz_if_table, TRUE) &&
-      !GetIpAddrTable (ipt, &siz_ip_table, TRUE))
+  typedef struct ifcount_t {
+      DWORD ifIndex;
+      DWORD routeIndex;
+      DWORD metric;
+      size_t count;
+      unsigned int enumerated;  // for eth0:1
+      unsigned int classId;     // for eth0, tok0 ...
+      
+  };
+  ifcount_t *iflist, *ifEntry;
+
+  if (GetIpAddrTable (NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER
+      && GetIpForwardTable(NULL, &siz_ipfwd_table, FALSE) == 
+ERROR_INSUFFICIENT_BUFFER    
+      && (ifrow = (PMIB_IFROW) alloca (sizeof (MIB_IFROW)))
+      && (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table))
+      && (ipfwdt = (PMIB_IPFORWARDTABLE) alloca (siz_ipfwd_table))
+      && !GetIpAddrTable (ipt, &siz_ip_table, TRUE)
+      && !GetIpForwardTable(ipfwdt, &siz_ipfwd_table, FALSE))
     {
-      /* Iterate over all known interfaces */
-      for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt)
+      iflist = (ifcount_t *)alloca(sizeof(ifcount_t) * (ipt->dwNumEntries + 1));
+      memset(iflist, 0,  sizeof(ifcount_t) * (ipt->dwNumEntries + 1));
+      for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
+        {
+          ifEntry = iflist; 
+          /* search for matching entry (and stop at first free entry) */
+          while (ifEntry->count != 0) {
+            if (ifEntry->ifIndex == ipt->table[ip_cnt].dwIndex) 
+              break;  
+            ifEntry++;
+          }
+          if (ifEntry->count == 0) {
+              ifEntry->count = 1;
+              ifEntry->metric = 1;
+              ifEntry->ifIndex = ipt->table[ip_cnt].dwIndex; 
+          } else {
+              ifEntry->count++;
+          }    
+        }
+      // reset the last element. This is just the stopper for the loop.
+      iflist[ipt->dwNumEntries].count = 0;
+      
+      ifEntry = iflist;
+      while (ifEntry->count > 0) {
+        for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt) 
+          if (ipfwdt->table[ipf_cnt].dwForwardIfIndex  == ifEntry->ifIndex) {
+            ifEntry->routeIndex = ipf_cnt;
+            ifEntry->metric = ipfwdt->table[ipf_cnt].dwForwardMetric1;
+            break;        
+          }    
+        ifEntry++;
+      }  
+      
+      /* Iterate over all configured IP-addresses */
+      for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
        {
-         *sub = '0';
-         /* Iterate over all configured IP-addresses */
-         for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
+         memset (ifrow, 0, sizeof (MIB_IFROW));
+         ifrow->dwIndex = ipt->table[ip_cnt].dwIndex;
+         if (GetIfEntry (ifrow) != NO_ERROR)
+           continue;
+          
+          ifcount_t *ifEntry = iflist; 
+          /* search for matching entry (and stop at first free entry) */
+          while (ifEntry->count != 0) {
+            if (ifEntry->ifIndex == ipt->table[ip_cnt].dwIndex) 
+              break;  
+            ifEntry++;
+          }
+
+         /* Setup the interface name */
+         switch (ifrow->dwType)
            {
-             /* Does the IP address belong to the interface? */
-             if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
-               {
-                 /* Setup the interface name */
-                 switch (ift->table[if_cnt].dwType)
-                   {
-                     case MIB_IF_TYPE_TOKENRING:
-                       ++*tok;
-                       strcpy (ifr->ifr_name, "tok");
-                       strcat (ifr->ifr_name, tok);
-                       break;
-                     case MIB_IF_TYPE_ETHERNET:
-                       if (*sub == '0')
-                         ++*eth;
-                       strcpy (ifr->ifr_name, "eth");
-                       strcat (ifr->ifr_name, eth);
-                       break;
-                     case MIB_IF_TYPE_PPP:
-                       ++*ppp;
-                       strcpy (ifr->ifr_name, "ppp");
-                       strcat (ifr->ifr_name, ppp);
-                       break;
-                     case MIB_IF_TYPE_SLIP:
-                       ++*slp;
-                       strcpy (ifr->ifr_name, "slp");
-                       strcat (ifr->ifr_name, slp);
-                       break;
-                     case MIB_IF_TYPE_LOOPBACK:
-                       strcpy (ifr->ifr_name, "lo");
-                       break;
-                     default:
-                       continue;
-                   }
-                 if (*sub > '0')
-                   {
-                     strcat (ifr->ifr_name, ":");
-                     strcat (ifr->ifr_name, sub);
-                   }
-                 ++*sub;
-                 /* setup sockaddr struct */
-                 switch (what)
-                   {
-                     case SIOCGIFCONF:
-                     case SIOCGIFADDR:
-                       sa = (struct sockaddr_in *) &ifr->ifr_addr;
-                       sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
-                       sa->sin_family = AF_INET;
-                       sa->sin_port = 0;
-                       break;
-                     case SIOCGIFBRDADDR:
-                       sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+           case MIB_IF_TYPE_TOKENRING:
+              if (ifEntry->enumerated == 0) {
+                ifEntry->classId = tokId++;
+               __small_sprintf(ifr->ifr_name, "tok%u", ifEntry->classId);
+              } else {
+               __small_sprintf(ifr->ifr_name, "tok%u:%u", ifEntry->classId, 
+                  ifEntry->enumerated-1);
+              }
+              ifEntry->enumerated++;
+             break;
+           case MIB_IF_TYPE_ETHERNET:
+              if (ifEntry->enumerated == 0) {
+                ifEntry->classId = ethId++;
+               __small_sprintf(ifr->ifr_name, "eth%u", ifEntry->classId);
+              } else {
+               __small_sprintf(ifr->ifr_name, "eth%u:%u", ifEntry->classId, 
+                  ifEntry->enumerated-1);
+              }
+              ifEntry->enumerated++;
+             break;
+           case MIB_IF_TYPE_PPP:
+              if (ifEntry->enumerated == 0) {
+                ifEntry->classId = pppId++;
+               __small_sprintf(ifr->ifr_name, "ppp%u", ifEntry->classId);
+              } else {
+               __small_sprintf(ifr->ifr_name, "ppp%u:%u", ifEntry->classId, 
+                  ifEntry->enumerated-1);
+              }
+              ifEntry->enumerated++;
+             break;
+           case MIB_IF_TYPE_SLIP:
+              if (ifEntry->enumerated == 0) {
+                ifEntry->classId = slpId++;
+               __small_sprintf(ifr->ifr_name, "slp%u", ifEntry->classId);
+              } else {
+               __small_sprintf(ifr->ifr_name, "slp%u:%u", ifEntry->classId, 
+                  ifEntry->enumerated-1);
+              }
+              ifEntry->enumerated++;
+             break;
+           case MIB_IF_TYPE_LOOPBACK:
+             strcpy (ifr->ifr_name, "lo");
+             break;
+           default:
+             continue;
+           }
+         /* setup sockaddr struct */
+         switch (what)
+           {
+           case SIOCGIFCONF:
+           case SIOCGIFADDR:
+             sa = (struct sockaddr_in *) &ifr->ifr_addr;
+             sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
+             sa->sin_family = AF_INET;
+             sa->sin_port = 0;
+             break;
+           case SIOCGIFBRDADDR:
+             sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
 #if 0
-                       /* Unfortunately, the field returns only crap. */
-                       sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
+             /* Unfortunately, the field returns only crap. */
+             sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
 #else
-                       lip = ipt->table[ip_cnt].dwAddr;
-                       lnp = ipt->table[ip_cnt].dwMask;
-                       sa->sin_addr.s_addr = lip & lnp | ~lnp;
-                       sa->sin_family = AF_INET;
-                       sa->sin_port = 0;
+             lip = ipt->table[ip_cnt].dwAddr;
+             lnp = ipt->table[ip_cnt].dwMask;
+             sa->sin_addr.s_addr = lip & lnp | ~lnp;
+             sa->sin_family = AF_INET;
+             sa->sin_port = 0;
 #endif
-                       break;
-                     case SIOCGIFNETMASK:
-                       sa = (struct sockaddr_in *) &ifr->ifr_netmask;
-                       sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
-                       sa->sin_family = AF_INET;
-                       sa->sin_port = 0;
-                       break;
-                     case SIOCGIFHWADDR:
-                       so = &ifr->ifr_hwaddr;
-                       for (UINT i = 0; i < IFHWADDRLEN; ++i)
-                         if (i >= ift->table[if_cnt].dwPhysAddrLen)
-                           so->sa_data[i] = '\0';
-                         else
-                           so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
-                       so->sa_family = AF_INET;
-                       break;
-                     case SIOCGIFMETRIC:
-                       ifr->ifr_metric = 1;
-                       break;
-                     case SIOCGIFMTU:
-                       ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
-                       break;
-                   }
-                 ++cnt;
-                 if ((caddr_t) ++ifr >
-                     ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
-                   goto done;
-               }
+             break;
+           case SIOCGIFNETMASK:
+             sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+             sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
+             sa->sin_family = AF_INET;
+             sa->sin_port = 0;
+             break;
+           case SIOCGIFHWADDR:
+             so = &ifr->ifr_hwaddr;
+             for (UINT i = 0; i < IFHWADDRLEN; ++i)
+               if (i >= ifrow->dwPhysAddrLen)
+                 so->sa_data[i] = '\0';
+               else
+                 so->sa_data[i] = ifrow->bPhysAddr[i];
+             so->sa_family = AF_INET;
+             break;
+           case SIOCGIFMETRIC:
+             ifr->ifr_metric = ifEntry->metric;
+             break;
+           case SIOCGIFMTU:
+             ifr->ifr_mtu = ifrow->dwMtu;
+             break;
            }
+         ++cnt;
+         if ((caddr_t)++ ifr >
+             ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
+           goto done;
        }
     }
+
 done:
   /* Set the correct length */
   ifc->ifc_len = cnt * sizeof (struct ifreq);
--- winsup/cygwin/autoload.cc.orig      Sat Nov  9 18:36:52 2002
+++ winsup/cygwin/autoload.cc   Sat Nov  9 18:42:17 2002
@@ -485,7 +485,9 @@ LoadDLLfuncEx (WSAEventSelect, 12, ws2_3
 LoadDLLfuncEx (WSAEnumNetworkEvents, 12, ws2_32, 1)
 
 LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
+LoadDLLfuncEx (GetIfEntry, 4, iphlpapi, 1)
 LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1)
+LoadDLLfuncEx (GetIpForwardTable, 12, iphlpapi, 1)
 
 LoadDLLfunc (CoInitialize, 4, ole32)
 LoadDLLfunc (CoUninitialize, 0, ole32)

Reply via email to