CVS: winex/dlls/netapi32 netapi32.c,1.6,1.7

[email protected] 31 Jul 2007 17:31:40 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/dlls/netapi32 netapi32.c,1.6,1.7Update of /var/lib/cvsd/cvsroot/winex/dlls/netapi32
In directory agravaine:/tmp/cvs-serv20246/dlls/netapi32

Modified Files:
	netapi32.c 
Log Message:

- fix interface checking to not use hardcoded buffer size
- support retrieving MAC address on MacOS X


Index: netapi32.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/netapi32/netapi32.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- netapi32.c	31 Jul 2007 17:31:31 -0000	1.6
+++ netapi32.c	31 Jul 2007 17:31:38 -0000	1.7
@@ -37,14 +37,11 @@
 #endif
 
 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-#  ifndef max
-#   define max(a,b) ((a) > (b) ? (a) : (b))
-#  endif
-#  define ifreq_size(i) max(sizeof(struct ifreq),\
-sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
-# else
-#  define ifreq_size(i) sizeof(struct ifreq)
-# endif /* defined(HAVE_STRUCT_SOCKADDR_SA_LEN) */
+#define ifreq_len(ifr) \
+ max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
+#else
+#define ifreq_len(ifr) sizeof(struct ifreq)
+#endif
 
 WINE_DEFAULT_DEBUG_CHANNEL(netbios);
 
@@ -76,7 +73,57 @@
     memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6);
     return 0;
 }
-#   else
+#elif defined(__APPLE__)
+#include <sys/sysctl.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+
+int get_hw_address (int sd, struct ifreq *ifr, unsigned char *addr)
+{
+  DWORD ret;
+  struct if_msghdr *ifm;
+  struct sockaddr_dl *sdl;
+  u_char *p, *buf;
+  size_t mibLen;
+  int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
+  int addrLen;
+  BOOL found = FALSE;
+
+  if (sysctl(mib, 6, NULL, &mibLen, NULL, 0) < 0)
+    return -1;
+
+  buf = HeapAlloc(GetProcessHeap(), 0, mibLen);
+  if (!buf)
+    return -1;
+
+  if (sysctl(mib, 6, buf, &mibLen, NULL, 0) < 0) {
+    HeapFree(GetProcessHeap(), 0, buf);
+    return -1;
+  }
+
+  ret = ERROR_INVALID_DATA;
+  for (p = buf; !found && p < buf + mibLen; p += ifm->ifm_msglen) {
+    ifm = (struct if_msghdr *)p;
+    sdl = (struct sockaddr_dl *)(ifm + 1);
+
+    if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0)
+      continue;
+
+    if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
+     memcmp(sdl->sdl_data, ifr->ifr_name,
+            max(sdl->sdl_nlen, strlen(ifr->ifr_name))) != 0)
+      continue;
+
+    found = TRUE;
+    addrLen = min(8, sdl->sdl_alen);
+    if (addrLen > 0)
+        memcpy(addr, LLADDR(sdl), addrLen);
+      /* zero out remaining bytes for broken implementations */
+  }
+  HeapFree(GetProcessHeap(), 0, buf);
+  return 0;
+}
+#else
 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
 {
     return -1;
@@ -88,10 +135,11 @@
 {
 #ifdef HAVE_NET_IF_H
     int             sd;
-    struct ifreq    ifr, *ifrp;
     struct ifconf   ifc;
-    unsigned char   buf[1024];
-    int             i, ofs;
+    int             i;
+    int             lastlen, numAddresses = 2;
+    int             ioctlRet = 0;
+    caddr_t         ifPtr;
 #endif
     LANA_ENUM *lanas = NULL;
 
@@ -114,24 +162,49 @@
     if (sd < 0)
         return NRC_OPENERROR;
 
-    memset(buf, 0, sizeof(buf));
-    ifc.ifc_len = sizeof(buf);
-    ifc.ifc_buf = buf;
-    /* get the ifconf interface */
-    if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
+    ifc.ifc_len = 0;
+    ifc.ifc_buf = NULL;
+
+    do {
+       lastlen = ifc.ifc_len;
+       HeapFree (GetProcessHeap (), 0, ifc.ifc_buf);
+       numAddresses *= 2;
+
+       ifc.ifc_len = sizeof (struct ifreq) * numAddresses;
+       ifc.ifc_buf = HeapAlloc (GetProcessHeap (), 0, ifc.ifc_len);
+       if (!ifc.ifc_buf)
+       {
+          close (sd);
+          return NRC_OPENERROR;
+       }
+
+       ioctlRet = ioctl (sd, SIOCGIFCONF, (char *)&ifc);
+    } while ((ioctlRet == 0) && (ifc.ifc_len != lastlen));
+
+    if (ioctlRet)
     {
-        close(sd);
-        return NRC_OPENERROR;
+       HeapFree (GetProcessHeap (), 0, ifc.ifc_buf);
+       close (sd);
+       return NRC_OPENERROR;
     }
 
     /* loop through the interfaces, looking for a valid one */
     /* n = ifc.ifc_len; */
-    ofs = 0;
-    for (i = 0; i < ifc.ifc_len; i++)
+    ifPtr = ifc.ifc_buf;
+    i = 0;
+    while (ifPtr && (ifPtr < (ifc.ifc_buf + ifc.ifc_len)))
     {
         unsigned char *a = NETBIOS_Adapter[i].address;
+        struct ifreq   ifr, *ifrp;
+
+        ifrp = (struct ifreq *)ifPtr;
+
+        ifPtr += ifreq_len ((struct ifreq *)ifPtr);
+        i++;
+
+        if (ifrp->ifr_addr.sa_family != AF_INET)
+           continue;
 
-        ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs);
         strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
 
         /* try to get the address for this interface */
@@ -145,17 +218,18 @@
                         a[0],a[1],a[2],a[3],a[4],a[5]);
 
             if (a[0] || a[1] || a[2] || a[3] || a[4] || a[5])
-               NETBIOS_Adapter[i].valid = TRUE;
+               NETBIOS_Adapter[i - 1].valid = TRUE;
 
             if (lanas)
             {
-               lanas->lana[lanas->length] = i;
+               lanas->lana[lanas->length] = i - 1;
                lanas->length++;
             }
         }
-        ofs += ifreq_size(ifr);
     }
     close(sd);
+    HeapFree (GetProcessHeap (), 0, ifc.ifc_buf);
+
 #endif /* HAVE_NET_IF_H */
     EnumDone = TRUE;
     return NRC_GOODRET;