HW address w/o connection in iphlpapi

Michael Ost most at museresearch.com
Wed Jan 18 14:04:05 CST 2006


> Hi Michael, 
> 
>> When you boot a linux box without an ethernet connection, and eth0 
>> configuration fails, GetAdaptersInfo does not return MAC address info
>> for eth0. 
>> The problem seems to be that enumerateInterfaces (in 
>> dlls/iphlpapi/ifenum.c) doesn't create a record for eth0, because 
>> SIOCGIFCONF doesn't return one. 
> 
> Mmm.  Yeah, I think an alternative to SIOCGIFCONF might be the thing. 

Wait. This works better than getifaddrs. It successfully returns info
for "down" devices on my RH8 based linux box, with my creaky old
wine-20050419. get_ifaddrs makes the same calls that you were, in its
implementation. So it has the same problem. But it's alot easier to
program with than the ioctl you used. 

You made comments in the source about if_indextoname having issues. So
perhaps this patch won't be useful to you. But it works for us, so I'll
apply it to our wine sources unless/until something better comes along.
Have at it! 

Cheers... mo 

-------------- next part --------------
--- wine-20050419/dlls/iphlpapi/ifenum.c.20050419	2006-01-16 17:33:15.000000000 -0800
+++ wine-20050419/dlls/iphlpapi/ifenum.c	2006-01-17 17:26:01.000000000 -0800
@@ -184,40 +184,6 @@
   return map;
 }
 
-static int isLoopbackInterface(int fd, const char *name)
-{
-  int ret = 0;
-
-  if (name) {
-    struct ifreq ifr;
-
-    lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
-      ret = ifr.ifr_flags & IFF_LOOPBACK;
-  }
-  return ret;
-}
-
-static void countInterfaces(int fd, caddr_t buf, size_t len)
-{
-  caddr_t ifPtr = buf;
-  DWORD numNonLoopbackInterfaces = 0, numLoopbackInterfaces = 0;
-
-  while (ifPtr && ifPtr < buf + len) {
-    struct ifreq *ifr = (struct ifreq *)ifPtr;
-
-    if (isLoopbackInterface(fd, ifr->ifr_name))
-      numLoopbackInterfaces++;
-    else
-      numNonLoopbackInterfaces++;
-    ifPtr += ifreq_len(ifr);
-  }
-  gNonLoopbackInterfaceMap = sizeMap(gNonLoopbackInterfaceMap,
-   numNonLoopbackInterfaces);
-  gLoopbackInterfaceMap = sizeMap(gLoopbackInterfaceMap,
-   numLoopbackInterfaces);
-}
-
 /* Stores the name in the given map, and increments the map's numInterfaces
  * member if stored successfully.  Will store in the same slot as previously if
  * usedLastPass is set, otherwise will store in a new slot.
@@ -272,6 +238,104 @@
   }
 }
 
+#ifdef HAVE_NET_IF_H
+static int isLoopbackInterface(int fd, const char *name)
+{
+  int ret = 0;
+
+  if (name) {
+    struct ifreq ifr;
+
+    lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
+    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
+      ret = ifr.ifr_flags & IFF_LOOPBACK;
+  }
+  return ret;
+}
+
+static void enumerateInterfaces(void)
+{
+  int fd;
+  int nonLoopbacks;
+  int loopbacks;
+  struct if_nameindex* ifnames;
+  struct if_nameindex* ifn;
+
+  fd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (fd != -1) {
+    ifnames = if_nameindex();
+ 	if (ifnames) {
+      EnterCriticalSection(&mapCS);
+
+      nonLoopbacks = 0;
+      loopbacks = 0;
+	  for (ifn = ifnames; ifn->if_name != 0; ifn = &ifn[1]) {
+       if (isLoopbackInterface(fd, ifn->if_name))
+          loopbacks++;
+        else
+          nonLoopbacks++;
+       }
+
+      gNonLoopbackInterfaceMap = sizeMap(gNonLoopbackInterfaceMap,
+       nonLoopbacks);
+      gLoopbackInterfaceMap = sizeMap(gLoopbackInterfaceMap,
+       loopbacks);
+
+      markOldInterfaces(gNonLoopbackInterfaceMap);
+      markOldInterfaces(gLoopbackInterfaceMap);
+
+      /* add table entries for them them */
+	  for (ifn = ifnames; ifn->if_name != 0; ifn = &ifn[1]) {
+       if (isLoopbackInterface(fd, ifn->if_name))
+          storeInterfaceInMap(gLoopbackInterfaceMap, ifn->if_name);
+        else
+          storeInterfaceInMap(gNonLoopbackInterfaceMap, ifn->if_name);
+      }
+
+      LeaveCriticalSection(&mapCS);
+      if_freenameindex(ifnames);
+	}
+    else 
+      perror("iphlpapi/ifenum.c::if_nameindex()");
+  }
+  else
+    perror("iphlpapi/ifenum.c::socket()");
+}
+#else	 // !HAVE_NET_IF_H
+static int isLoopbackInterface(int fd, const char *name)
+{
+  int ret = 0;
+
+  if (name) {
+    struct ifreq ifr;
+
+    lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
+    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
+      ret = ifr.ifr_flags & IFF_LOOPBACK;
+  }
+  return ret;
+}
+
+static void countInterfaces(int fd, caddr_t buf, size_t len)
+{
+  caddr_t ifPtr = buf;
+  DWORD numNonLoopbackInterfaces = 0, numLoopbackInterfaces = 0;
+
+  while (ifPtr && ifPtr < buf + len) {
+    struct ifreq *ifr = (struct ifreq *)ifPtr;
+
+    if (isLoopbackInterface(fd, ifr->ifr_name))
+      numLoopbackInterfaces++;
+    else
+      numNonLoopbackInterfaces++;
+    ifPtr += ifreq_len(ifr);
+  }
+  gNonLoopbackInterfaceMap = sizeMap(gNonLoopbackInterfaceMap,
+   numNonLoopbackInterfaces);
+  gLoopbackInterfaceMap = sizeMap(gLoopbackInterfaceMap,
+   numLoopbackInterfaces);
+}
+
 static void classifyInterfaces(int fd, caddr_t buf, size_t len)
 {
   caddr_t ifPtr = buf;
@@ -335,6 +399,7 @@
     close(fd);
   }
 }
+#endif
 
 DWORD getNumNonLoopbackInterfaces(void)
 {


More information about the wine-devel mailing list