gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r18370 - in gnunet/src: include util


From: gnunet
Subject: [GNUnet-SVN] r18370 - in gnunet/src: include util
Date: Tue, 29 Nov 2011 12:47:40 +0100

Author: grothoff
Date: 2011-11-29 12:47:40 +0100 (Tue, 29 Nov 2011)
New Revision: 18370

Modified:
   gnunet/src/include/winproc.h
   gnunet/src/util/Makefile.am
   gnunet/src/util/os_network.c
   gnunet/src/util/win.cc
   gnunet/src/util/winproc.c
Log:
LRN: new code for GNUNET_OS_network_interfaces_list on W32 improving support 
for IPv6 and subnets/masks, see Mantis 1958

Modified: gnunet/src/include/winproc.h
===================================================================
--- gnunet/src/include/winproc.h        2011-11-29 09:52:10 UTC (rev 18369)
+++ gnunet/src/include/winproc.h        2011-11-29 11:47:40 UTC (rev 18370)
@@ -62,6 +62,10 @@
                                            PULONG pdwSize, BOOL bOrder);
   typedef DWORD WINAPI (*TGetIfTable) (PMIB_IFTABLE pIfTable, PULONG pdwSize,
                                        BOOL bOrder);
+  typedef DWORD WINAPI (*TGetBestInterfaceEx) (struct sockaddr *, PDWORD);
+  /* TODO: Explicitly import -A variants (i.e. TCreateHardLinkA) or -W
+   * variants (TCreateHardLinkW), etc.
+   */
   typedef DWORD WINAPI (*TCreateHardLink) (LPCTSTR lpFileName,
                                            LPCTSTR lpExistingFileName,
                                            LPSECURITY_ATTRIBUTES
@@ -99,8 +103,6 @@
   typedef SC_HANDLE WINAPI (*TOpenService) (SC_HANDLE hSCManager,
                                             LPCTSTR lpServiceName,
                                             DWORD dwDesiredAccess);
-  typedef DWORD WINAPI (*TGetBestInterface) (IPAddr dwDestAddr,
-                                             PDWORD pdwBestIfIndex);
   typedef DWORD WINAPI (*TGetAdaptersInfo) (PIP_ADAPTER_INFO pAdapterInfo,
                                             PULONG pOutBufLen);
   typedef NET_API_STATUS WINAPI (*TNetUserAdd) (LPCWSTR, DWORD, PBYTE, PDWORD);
@@ -158,6 +160,7 @@
                                                 PSID psidGroup, PACL pDacl,
                                                 PACL pSacl);
 
+  extern TGetBestInterfaceEx GNGetBestInterfaceEx;
   extern TNtQuerySystemInformation GNNtQuerySystemInformation;
   extern TGetIfEntry GNGetIfEntry;
   extern TGetIpAddrTable GNGetIpAddrTable;
@@ -172,8 +175,7 @@
   extern TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
   extern TControlService GNControlService;
   extern TOpenService GNOpenService;
-  extern TGetBestInterface GNGetBestInterface;
-  extern TGetAdaptersInfo GGetAdaptersInfo;
+  extern TGetAdaptersInfo GNGetAdaptersInfo;
   extern TNetUserAdd GNNetUserAdd;
   extern TNetUserSetInfo GNNetUserSetInfo;
   extern TLsaOpenPolicy GNLsaOpenPolicy;
@@ -202,6 +204,23 @@
                             DWORD dwAccessMask);
   char *winErrorStr (const char *prefix, int dwErr);
   void EnumNICs (PMIB_IFTABLE * pIfTable, PMIB_IPADDRTABLE * pAddrTable);
+
+#define ENUMNICS3_MASK_OK 0x01
+#define ENUMNICS3_BCAST_OK 0x02
+
+struct EnumNICs3_results
+{
+  unsigned char flags;
+  int is_default;
+  char pretty_name[1001];
+  size_t addr_size;
+  struct sockaddr address;
+  struct sockaddr mask;
+  struct sockaddr broadcast;
+};
+
+  int EnumNICs3 (struct EnumNICs3_results **, int *EnumNICs3_results_count);
+  void EnumNICs3_free (struct EnumNICs3_results *);
   int GNInitWinEnv ();
   void GNShutdownWinEnv ();
 

Modified: gnunet/src/util/Makefile.am
===================================================================
--- gnunet/src/util/Makefile.am 2011-11-29 09:52:10 UTC (rev 18369)
+++ gnunet/src/util/Makefile.am 2011-11-29 11:47:40 UTC (rev 18370)
@@ -17,7 +17,7 @@
   -no-undefined -Wl,--export-all-symbols 
 libgnunetutilwin_la_LIBADD = \
   -lshell32 -liconv -lstdc++ \
-  -lcomdlg32 -lgdi32
+  -lcomdlg32 -lgdi32 -liphlpapi
 WINLIB = libgnunetutilwin.la
 endif
 

Modified: gnunet/src/util/os_network.c
===================================================================
--- gnunet/src/util/os_network.c        2011-11-29 09:52:10 UTC (rev 18369)
+++ gnunet/src/util/os_network.c        2011-11-29 11:47:40 UTC (rev 18370)
@@ -25,6 +25,7 @@
  * @author Nils Durner
  * @author Heikki Lindholm
  * @author Jake Dust
+ * @author LRN
  */
 
 #include "platform.h"
@@ -46,128 +47,26 @@
                                    void *proc_cls)
 {
 #ifdef MINGW
-  PMIB_IFTABLE pTable;
-  PMIB_IPADDRTABLE pAddrTable;
-  DWORD dwIfIdx, dwExternalNIC;
-  IPAddr theIP;
+  int r;
+  int i;
+  struct EnumNICs3_results *results = NULL;
+  int results_count;
 
-  /* Determine our external NIC  */
-  theIP = inet_addr ("192.0.34.166");   /* www.example.com */
-  if ((!GNGetBestInterface) ||
-      (GNGetBestInterface (theIP, &dwExternalNIC) != NO_ERROR))
-  {
-    dwExternalNIC = 0;
-  }
+  r = EnumNICs3 (&results, &results_count);
+  if (r != GNUNET_OK)
+    return;
 
-  /* Enumerate NICs */
-  EnumNICs (&pTable, &pAddrTable);
-
-  if (pTable)
+  for (i = 0; i < results_count; i++)
   {
-    for (dwIfIdx = 0; dwIfIdx <= pTable->dwNumEntries; dwIfIdx++)
-    {
-      char szEntry[1001];
-      DWORD dwIP = 0;
-      PIP_ADAPTER_INFO pAdapterInfo;
-      PIP_ADAPTER_INFO pAdapter = NULL;
-      DWORD dwRetVal = 0;
-
-      /* Get IP-Address */
-      int i;
-
-      for (i = 0; i < pAddrTable->dwNumEntries; i++)
-      {
-        if (pAddrTable->table[i].dwIndex == pTable->table[dwIfIdx].dwIndex)
-        {
-          dwIP = pAddrTable->table[i].dwAddr;
-          break;
-        }
-      }
-
-      if (dwIP)
-      {
-        BYTE bPhysAddr[MAXLEN_PHYSADDR];
-        char *pszIfName = NULL;
-        char dst[INET_ADDRSTRLEN];
-        struct sockaddr_in sa;
-
-        /* Get friendly interface name */
-        pAdapterInfo = (IP_ADAPTER_INFO *) malloc (sizeof (IP_ADAPTER_INFO));
-        ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
-
-        /* Make an initial call to GetAdaptersInfo to get
-         * the necessary size into the ulOutBufLen variable */
-        if (GGetAdaptersInfo (pAdapterInfo, &ulOutBufLen) ==
-            ERROR_BUFFER_OVERFLOW)
-        {
-          free (pAdapterInfo);
-          pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);
-        }
-
-        if ((dwRetVal =
-             GGetAdaptersInfo (pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
-        {
-          pAdapter = pAdapterInfo;
-          while (pAdapter)
-          {
-            if (pTable->table[dwIfIdx].dwIndex == pAdapter->Index)
-            {
-              char szKey[251];
-              long lLen = 250;
-
-              sprintf (szKey,
-                       "SYSTEM\\CurrentControlSet\\Control\\Network\\"
-                       
"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
-                       pAdapter->AdapterName);
-              pszIfName = (char *) malloc (251);
-              if (QueryRegistry
-                  (HKEY_LOCAL_MACHINE, szKey, "Name", pszIfName,
-                   &lLen) != ERROR_SUCCESS)
-              {
-                free (pszIfName);
-                pszIfName = NULL;
-              }
-            }
-            pAdapter = pAdapter->Next;
-          }
-        }
-        free (pAdapterInfo);
-
-        /* Set entry */
-        memset (bPhysAddr, 0, MAXLEN_PHYSADDR);
-        memcpy (bPhysAddr, pTable->table[dwIfIdx].bPhysAddr,
-                pTable->table[dwIfIdx].dwPhysAddrLen);
-
-        snprintf (szEntry, 1000, "%s (%s - %I64u)",
-                  pszIfName ? pszIfName : (char *) pTable->
-                  table[dwIfIdx].bDescr, inet_ntop (AF_INET, &dwIP, dst,
-                                                    INET_ADDRSTRLEN),
-                  *((unsigned long long *) bPhysAddr));
-        szEntry[1000] = 0;
-
-        if (pszIfName)
-          free (pszIfName);
-
-        sa.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-        sa.sin_len = (u_char) sizeof (struct sockaddr_in);
-#endif
-        sa.sin_addr.S_un.S_addr = dwIP;
-
-        if (GNUNET_OK !=
-            proc (proc_cls, szEntry,
-                  pTable->table[dwIfIdx].dwIndex == dwExternalNIC,
-                  (const struct sockaddr *) &sa,
-                  NULL,
-                  NULL,
-                  sizeof (sa)))
-          break;
-      }
-    }
-    GlobalFree (pAddrTable);
-    GlobalFree (pTable);
+    if (GNUNET_OK != proc (proc_cls, results[i].pretty_name,
+        results[i].is_default,
+        &results[i].address,
+        results[i].flags & ENUMNICS3_MASK_OK ? &results[i].mask : NULL,
+        results[i].flags & ENUMNICS3_BCAST_OK ? &results[i].broadcast : NULL,
+        results[i].addr_size))
+      break;
   }
-
+  EnumNICs3_free (results);
   return;
 
 #elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS

Modified: gnunet/src/util/win.cc
===================================================================
--- gnunet/src/util/win.cc      2011-11-29 09:52:10 UTC (rev 18369)
+++ gnunet/src/util/win.cc      2011-11-29 11:47:40 UTC (rev 18370)
@@ -44,161 +44,608 @@
 
 int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);
 
-/**
- * Enumerate all network adapters
- */
-void EnumNICs(PMIB_IFTABLE *pIfTable, PMIB_IPADDRTABLE *pAddrTable)
+#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
+  union { \
+    struct { \
+      ULONG Length; \
+      DWORD Flags; \
+    }; \
+  }; \
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \
+  SOCKET_ADDRESS                     Address; \
+  IP_PREFIX_ORIGIN                   PrefixOrigin; \
+  IP_SUFFIX_ORIGIN                   SuffixOrigin; \
+  IP_DAD_STATE                       DadState; \
+  ULONG                              ValidLifetime; \
+  ULONG                              PreferredLifetime; \
+  ULONG                              LeaseLifetime;
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \
+  UINT8                              OnLinkPrefixLength;
+
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \
+  _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
+  struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \
+  _IP_ADAPTER_UNICAST_ADDRESS_BASE \
+  addition \
+} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;
+
+/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */
+_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)
+
+
+typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {
+  union {
+    ULONGLONG Alignment;
+    struct {
+      ULONG Length;
+      DWORD Reserved;
+    };
+  };
+  struct _IP_ADAPTER_WINS_SERVER_ADDRESS  *Next;
+  SOCKET_ADDRESS                         Address;
+} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, 
*PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
+
+typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {
+  union {
+    ULONGLONG Alignment;
+    struct {
+      ULONG Length;
+      DWORD Reserved;
+    };
+  };
+  struct _IP_ADAPTER_GATEWAY_ADDRESS  *Next;
+  SOCKET_ADDRESS                     Address;
+} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, 
*PIP_ADAPTER_GATEWAY_ADDRESS_LH;
+
+typedef UINT32 NET_IF_COMPARTMENT_ID;
+typedef GUID NET_IF_NETWORK_GUID;
+
+typedef enum _NET_IF_CONNECTION_TYPE {
+  NET_IF_CONNECTION_DEDICATED   = 1,
+  NET_IF_CONNECTION_PASSIVE,
+  NET_IF_CONNECTION_DEMAND,
+  NET_IF_CONNECTION_MAXIMUM 
+} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;
+
+typedef enum  {
+  TUNNEL_TYPE_NONE      = 0,
+  TUNNEL_TYPE_OTHER,
+  TUNNEL_TYPE_DIRECT,
+  TUNNEL_TYPE_6TO4,
+  TUNNEL_TYPE_ISATAP,
+  TUNNEL_TYPE_TEREDO,
+  TUNNEL_TYPE_IPHTTPS 
+} TUNNEL_TYPE, *PTUNNEL_TYPE;
+
+/*
+A DUID consists of a two-octet type code represented in network byte
+   order, followed by a variable number of octets that make up the
+   actual identifier.  A DUID can be no more than 128 octets long (not
+   including the type code).
+*/
+#define MAX_DHCPV6_DUID_LENGTH 130
+
+typedef union _NET_LUID {
+  ULONG64 Value;
+  struct {
+    ULONG64 Reserved  :24;
+    ULONG64 NetLuidIndex  :24;
+    ULONG64 IfType  :16;
+  } Info;
+} NET_LUID, *PNET_LUID, IF_LUID;
+
+#define MAX_DNS_SUFFIX_STRING_LENGTH 246
+
+typedef struct _IP_ADAPTER_DNS_SUFFIX {
+  struct _IP_ADAPTER_DNS_SUFFIX  *Next;
+  WCHAR                         String[MAX_DNS_SUFFIX_STRING_LENGTH];
+} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;
+
+
+
+#define _IP_ADAPTER_ADDRESSES_HEAD \
+  union { \
+    ULONGLONG Alignment; \
+    struct { \
+      ULONG Length; \
+      DWORD IfIndex; \
+    }; \
+  };
+
+#define _IP_ADAPTER_ADDRESSES_BASE \
+  PCHAR                              AdapterName; \
+  PIP_ADAPTER_UNICAST_ADDRESS        FirstUnicastAddress; \
+  PIP_ADAPTER_ANYCAST_ADDRESS        FirstAnycastAddress; \
+  PIP_ADAPTER_MULTICAST_ADDRESS      FirstMulticastAddress; \
+  PIP_ADAPTER_DNS_SERVER_ADDRESS     FirstDnsServerAddress; \
+  PWCHAR                             DnsSuffix; \
+  PWCHAR                             Description; \
+  PWCHAR                             FriendlyName; \
+  BYTE                               
PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \
+  DWORD                              PhysicalAddressLength; \
+  DWORD                              Flags; \
+  DWORD                              Mtu; \
+  DWORD                              IfType; \
+  IF_OPER_STATUS                     OperStatus;
+
+#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
+  DWORD                              Ipv6IfIndex; \
+  DWORD                              ZoneIndices[16]; \
+  PIP_ADAPTER_PREFIX                 FirstPrefix; \
+
+
+#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \
+  _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
+  ULONG64                            TransmitLinkSpeed; \
+  ULONG64                            ReceiveLinkSpeed; \
+  PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \
+  PIP_ADAPTER_GATEWAY_ADDRESS_LH     FirstGatewayAddress; \
+  ULONG                              Ipv4Metric; \
+  ULONG                              Ipv6Metric; \
+  IF_LUID                            Luid; \
+  SOCKET_ADDRESS                     Dhcpv4Server; \
+  NET_IF_COMPARTMENT_ID              CompartmentId; \
+  NET_IF_NETWORK_GUID                NetworkGuid; \
+  NET_IF_CONNECTION_TYPE             ConnectionType; \
+  TUNNEL_TYPE                        TunnelType; \
+  SOCKET_ADDRESS                     Dhcpv6Server; \
+  BYTE                               Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; 
\
+  ULONG                              Dhcpv6ClientDuidLength; \
+  ULONG                              Dhcpv6Iaid;
+
+#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \
+  _IP_ADAPTER_ADDRESSES_ADD_VISTA \
+  PIP_ADAPTER_DNS_SUFFIX             FirstDnsSuffix;
+
+#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \
+typedef struct _IP_ADAPTER_ADDRESSES##suffix { \
+  _IP_ADAPTER_ADDRESSES_HEAD \
+  struct _IP_ADAPTER_ADDRESSES##suffix *Next; \
+  _IP_ADAPTER_ADDRESSES_BASE \
+  addition \
+} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;
+  
+
+/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */
+_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)
+_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)
+_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)
+
+static int
+EnumNICs_IPv6_get_ifs_count (SOCKET s)
 {
-  DWORD dwSize, dwRet;
+  DWORD dwret = 0, err;
+  int iret;
+  iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,
+      &dwret, NULL, NULL);
+  err = GetLastError ();
+  if (iret == SOCKET_ERROR && err == WSAEFAULT)
+    return dwret;
+  else if (iret == 0)
+    return 0;
+  return GNUNET_SYSERR;
+}
 
-  *pIfTable = NULL;
+static int
+EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)
+{
+  int iret;
+  DWORD dwret = 0;
+  iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,
+      &dwret, NULL, NULL);
 
-  if (pAddrTable)
-    *pAddrTable = NULL;
-
-  if (GNGetIfTable)
+  if (iret != 0 || dwret != size)
   {
-    dwSize = dwRet = 0;
+    /* It's supposed to succeed! And size should be the same */
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
 
-    *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, sizeof(MIB_IFTABLE));
+#undef GNUNET_malloc
+#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \
+    HEAP_GENERATE_EXCEPTIONS, a)
 
-    /* Get size of table */
-    if (GNGetIfTable(*pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
-    {
-      GlobalFree(*pIfTable);
-      *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, dwSize);
-    }
+#undef GNUNET_free
+#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)
 
-    if ((dwRet = GNGetIfTable(*pIfTable, &dwSize, 0)) == NO_ERROR &&
-      pAddrTable)
+#undef GNUNET_free_non_null
+#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while 
(0)
+
+static int
+EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)
+{
+  int iret;
+  DWORD dwret = 0;
+  DWORD error;
+  INTERFACE_INFO *ii = NULL;
+  DWORD ii_size = sizeof (INTERFACE_INFO) * 15;
+  while (TRUE)
+  {
+    if (ii_size >= sizeof (INTERFACE_INFO) * 1000)
+      return GNUNET_SYSERR;
+    ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);
+    dwret = 0;
+    iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,
+        &dwret, NULL, NULL);
+    error = GetLastError ();
+    if (iret == SOCKET_ERROR)
     {
-      DWORD dwIfIdx, dwSize = sizeof(MIB_IPADDRTABLE);
-      *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);
-
-      /* Make an initial call to GetIpAddrTable to get the
-         necessary size */
-      if (GNGetIpAddrTable(*pAddrTable, &dwSize, 0) == 
ERROR_INSUFFICIENT_BUFFER)
+      if (error == WSAEFAULT)
       {
-        GlobalFree(*pAddrTable);
-        *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);
+        GNUNET_free (ii);
+        ii_size *= 2;
+        continue;
       }
-      GNGetIpAddrTable(*pAddrTable, &dwSize, 0);
+      GNUNET_free (ii);
+      return GNUNET_SYSERR;
     }
+    else
+    {
+      *inf = ii;
+      *size = dwret;
+      return GNUNET_OK;
+    }
   }
+  return GNUNET_SYSERR;
 }
 
+int
+EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)
+{
+  int result = 0;
+  SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET;
+  DWORD dwret1 = 0, dwret2;
+  DWORD err1, err2;
+  int ifs4len = 0, ifs6len = 0;
+  INTERFACE_INFO *interfaces4 = NULL;
+  SOCKET_ADDRESS_LIST *interfaces6 = NULL;
+  SetLastError (0);
+  s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  err1 = GetLastError ();
+  SetLastError (0);
+  s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+  err2 = GetLastError ();
+  if (s6 != INVALID_SOCKET)
+  {
+    ifs6len = EnumNICs_IPv6_get_ifs_count (s6);
+    if (ifs6len > 0)
+    {
+      interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);
+      result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;
+    }
+    closesocket (s6);
+    s6 = INVALID_SOCKET;
+  }
+
+  if (s4 != INVALID_SOCKET)
+  {
+    result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;
+    closesocket (s4);
+    s4 = INVALID_SOCKET;
+  }
+  if (ifs6len + ifs4len == 0)
+    goto error;
+
+  if (!result)
+  {
+    *ifs4 = interfaces4;
+    *ifs4_len = ifs4len;
+    *ifs6 = interfaces6;
+    return GNUNET_OK;
+  }
+error:
+  if (interfaces4 != NULL)
+    GNUNET_free (interfaces4);
+  if (interfaces6 != NULL)
+    GNUNET_free (interfaces6);
+  if (s4 != INVALID_SOCKET)
+    closesocket (s4);
+  if (s6 != INVALID_SOCKET)
+    closesocket (s6);
+  return GNUNET_SYSERR;
+}
+
 /**
- * Lists all network interfaces in a combo box
- * Used by the basic GTK configurator
- *
- * @param callback function to call for each NIC
- * @param callback_cls closure for callback
+ * Returns GNUNET_OK on OK, GNUNET_SYSERR on error
  */
-  int ListNICs(void (*callback) (void *, const char *, int), void * 
callback_cls)
+int
+EnumNICs3 (struct EnumNICs3_results **results, int *results_count)
 {
-  PMIB_IFTABLE pTable;
-  PMIB_IPADDRTABLE pAddrTable;
-  DWORD dwIfIdx, dwExternalNIC;
-  IPAddr theIP;
+  DWORD dwRetVal = 0;
+  int count = 0;
+  ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |
+      GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
+  struct sockaddr_in6 examplecom6;
+  IPAddr examplecom;
+  DWORD best_interface = 0;
+  DWORD best_interface6 = 0;
 
-  /* Determine our external NIC  */
-  theIP = inet_addr("192.0.34.166"); /* www.example.com */
-  if ((! GNGetBestInterface) ||
-      (GNGetBestInterface(theIP, &dwExternalNIC) != NO_ERROR))
+  int use_enum2 = 0;
+  INTERFACE_INFO *interfaces4 = NULL;
+  int interfaces4_len = 0;
+  SOCKET_ADDRESS_LIST *interfaces6 = NULL;
+
+  unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
+  IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;
+  IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc 
(outBufLen);
+
+  if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)
+      == ERROR_BUFFER_OVERFLOW)
   {
-    dwExternalNIC = 0;
+    GNUNET_free (pAddresses);
+    pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
   }
 
-  /* Enumerate NICs */
-  EnumNICs(&pTable, &pAddrTable);
+  dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, 
&outBufLen);
 
-  if (pTable)
+  if (dwRetVal != NO_ERROR)
   {
-    for(dwIfIdx=0; dwIfIdx <= pTable->dwNumEntries; dwIfIdx++)
+    GNUNET_free (pAddresses);
+    return GNUNET_SYSERR;
+  }
+
+  if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))
+  {
+    use_enum2 = 1;
+
+    /* Enumerate NICs using WSAIoctl() */
+    if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))
     {
-      char szEntry[1001];
-      DWORD dwIP = 0;
-      int iItm;
-               PIP_ADAPTER_INFO pAdapterInfo;
-               PIP_ADAPTER_INFO pAdapter = NULL;
-               DWORD dwRetVal = 0;
+      GNUNET_free (pAddresses);
+      return GNUNET_SYSERR;
+    }
+  }
 
-      /* Get IP-Address */
-      int i;
-      for(i = 0; i < pAddrTable->dwNumEntries; i++)
+  examplecom = inet_addr("192.0.34.166"); /* www.example.com */
+  if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)
+    best_interface = 0;
+
+  if (GNGetBestInterfaceEx != NULL)
+  {
+    examplecom6.sin6_family = AF_INET6;
+    examplecom6.sin6_port = 0;
+    examplecom6.sin6_flowinfo = 0;
+    examplecom6.sin6_scope_id = 0;
+    inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",
+        (struct sockaddr *) &examplecom6.sin6_addr);
+    dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,
+        &best_interface6);
+    if (dwRetVal != NO_ERROR)
+      best_interface6 = 0;
+  }
+
+  /* Give IPv6 a priority */
+  if (best_interface6 != 0)
+    best_interface = best_interface6;
+
+  count = 0;
+  for (pCurrentAddress = pAddresses;
+      pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
+  {
+    if (pCurrentAddress->OperStatus == IfOperStatusUp)
+    {
+      IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
+      for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
+          unicast = unicast->Next)
       {
-        if (pAddrTable->table[i].dwIndex == pTable->table[dwIfIdx].dwIndex)
+        if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||
+            unicast->Address.lpSockaddr->sa_family == AF_INET6) &&
+            (unicast->DadState == IpDadStateDeprecated ||
+            unicast->DadState == IpDadStatePreferred))
+          count += 1;
+      }
+    }
+  }
+
+  if (count == 0)
+  {
+    *results = NULL;
+    *results_count = 0;
+    GNUNET_free (pAddresses);
+    GNUNET_free_non_null (interfaces4);
+    GNUNET_free_non_null (interfaces6);
+    return GNUNET_OK;
+  }
+
+  *results = (struct EnumNICs3_results *) GNUNET_malloc (
+      sizeof (struct EnumNICs3_results) * count);
+  *results_count = count;
+
+  count = 0;
+  for (pCurrentAddress = pAddresses;
+      pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
+  {
+    struct EnumNICs3_results *r;
+    IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
+    if (pCurrentAddress->OperStatus != IfOperStatusUp)
+      continue;
+    for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
+        unicast = unicast->Next)
+    {
+      int i, j;
+      int mask_length = -1;
+      char dst[INET6_ADDRSTRLEN + 1];
+
+      if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&
+          unicast->Address.lpSockaddr->sa_family != AF_INET6) ||
+          (unicast->DadState != IpDadStateDeprecated &&
+          unicast->DadState != IpDadStatePreferred))
+        continue;
+
+      r = &(*results)[count];
+      r->flags = 0;
+      if (pCurrentAddress->IfIndex > 0 &&
+          pCurrentAddress->IfIndex == best_interface &&
+          unicast->Address.lpSockaddr->sa_family == AF_INET)
+        r->is_default = 1;
+      else if (pCurrentAddress->Ipv6IfIndex > 0 &&
+          pCurrentAddress->Ipv6IfIndex == best_interface6 &&
+          unicast->Address.lpSockaddr->sa_family == AF_INET6)
+        r->is_default = 1;
+      else
+        r->is_default = 0;
+
+      /* Don't choose default interface twice */
+      if (r->is_default)
+        best_interface = best_interface6 = 0;
+
+      if (!use_enum2)
+      {
+        memcpy (&r->address, unicast->Address.lpSockaddr,
+            unicast->Address.iSockaddrLength);
+        memset (&r->mask, 0, sizeof (struct sockaddr));
+        mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->
+              OnLinkPrefixLength;
+        /* OnLinkPrefixLength is the number of leading 1s in the mask.
+         * OnLinkPrefixLength is available on Vista and later (hence 
use_enum2).
+         */
+        if (unicast->Address.lpSockaddr->sa_family == AF_INET)
         {
-          dwIP = pAddrTable->table[i].dwAddr;
-          break;
+          struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
+          for (i = 0; i < mask_length; i++)
+              ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
         }
+        else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
+        {
+          struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;
+          struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;
+          for (i = 0; i < mask_length; i++)
+            ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
+          memcpy (&r->broadcast, &r->address, 
unicast->Address.iSockaddrLength);
+          for (i = mask_length; i < 128; i++)
+            ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
+        }
+        r->flags |= ENUMNICS3_MASK_OK;
       }
-
-      if (dwIP)
+      else
       {
-        BYTE bPhysAddr[MAXLEN_PHYSADDR];
-                 char *pszIfName = NULL;
-        char dst[INET_ADDRSTRLEN];
+        int found = 0;
+        if (unicast->Address.lpSockaddr->sa_family == AF_INET)
+        {
+          for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); 
i++)
+          {
+            struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
+            if (memcpy (&interfaces4[i].iiAddress.Address,
+                unicast->Address.lpSockaddr,
+                unicast->Address.iSockaddrLength) != 0)
+              continue;
+            found = 1;
+            memcpy (&r->address, &interfaces4[i].iiAddress.Address,
+                sizeof (struct sockaddr_in));
+            memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,
+                sizeof (struct sockaddr_in));
+            for (mask_length = 0;
+                ((unsigned char *) &m->sin_addr)[mask_length / 8] &
+                0x80 >> (mask_length % 8); mask_length++)
+            {
+            }
+            r->flags |= ENUMNICS3_MASK_OK;
+          }
+        }
+        else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
+        {
+          for (i = 0;
+              interfaces6 != NULL && !found && i < interfaces6->iAddressCount;
+              i++)
+          {
+            if (memcpy (interfaces6->Address[i].lpSockaddr,
+                unicast->Address.lpSockaddr,
+                unicast->Address.iSockaddrLength) != 0)
+              continue;
+            found = 1;
+            memcpy (&r->address, interfaces6->Address[i].lpSockaddr,
+                sizeof (struct sockaddr_in6));
+            /* TODO: Find a way to reliably get network mask for IPv6 on XP */
+            memset (&r->mask, 0, sizeof (struct sockaddr));
+            r->flags &= ~ENUMNICS3_MASK_OK;
+          }
+        }
+        if (!found)
+        {
+          DebugBreak ();
+        }
+      }
+      if (unicast->Address.lpSockaddr->sa_family == AF_INET)
+      {
+        struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
+        struct sockaddr_in *a = (struct sockaddr_in *) &r->address;
+        /* copy address to broadcast, then flip all the trailing bits not
+         * falling under netmask to 1,
+         * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.
+         */
+        memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
+        for (i = mask_length; i < 32; i++)
+          ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
+        r->flags |= ENUMNICS3_BCAST_OK;
+        r->addr_size = sizeof (struct sockaddr_in);
+        inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);
+      }
+      else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
+      {
+        struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;
+        /* for IPv6 broadcast is not defined, zero it down */
+        memset (&r->broadcast, 0, sizeof (struct sockaddr));
+        r->flags &= ~ENUMNICS3_BCAST_OK;
+        r->addr_size = sizeof (struct sockaddr_in6);
+        inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);
+      }
 
-        /* Get friendly interface name */
-                       pAdapterInfo = (IP_ADAPTER_INFO *) 
malloc(sizeof(IP_ADAPTER_INFO));
-                       ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
+      i = 0;
+      i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
+          "%S (%s", pCurrentAddress->FriendlyName, dst);
+      for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)
+        i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
+            "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);
+      i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");
+      r->pretty_name[1000] = '\0';
+      count += 1;
+    }
+  }
 
-                       /* Make an initial call to GetAdaptersInfo to get
-                          the necessary size into the ulOutBufLen variable */
-                       if (GGetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == 
ERROR_BUFFER_OVERFLOW) {
-                         free(pAdapterInfo);
-                         pAdapterInfo = (IP_ADAPTER_INFO *) malloc 
(ulOutBufLen);
-                       }
+  if (use_enum2)
+  {
+    GNUNET_free_non_null (interfaces4);
+    GNUNET_free_non_null (interfaces6);
+  }
 
-                       if ((dwRetVal = GGetAdaptersInfo( pAdapterInfo, 
&ulOutBufLen)) == NO_ERROR) {
-                         pAdapter = pAdapterInfo;
-                         while (pAdapter) {
-                               if (pTable->table[dwIfIdx].dwIndex == 
pAdapter->Index)
-                               {
-                                       char szKey[251];
-                                       long lLen = 250;
+  GNUNET_free (pAddresses);
+  return GNUNET_OK;
+}
 
-                                       sprintf(szKey, 
"SYSTEM\\CurrentControlSet\\Control\\Network\\"
-                                               
"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
-                                               pAdapter->AdapterName);
-                                       pszIfName = (char *) malloc(251);
-                                       if (QueryRegistry(HKEY_LOCAL_MACHINE, 
szKey, "Name", pszIfName,
-                                               &lLen) != ERROR_SUCCESS)
-                                       {
-                                               free(pszIfName);
-                                               pszIfName = NULL;
-                                       }
-                               }
-                           pAdapter = pAdapter->Next;
-                         }
-                       }
-                       free(pAdapterInfo);
+void
+EnumNICs3_free (struct EnumNICs3_results *r)
+{
+  GNUNET_free (r);
+}
 
-                       /* Set entry */
-        memset(bPhysAddr, 0, MAXLEN_PHYSADDR);
-        memcpy(bPhysAddr,
-          pTable->table[dwIfIdx].bPhysAddr,
-          pTable->table[dwIfIdx].dwPhysAddrLen);
 
-        snprintf(szEntry, 1000, "%s (%s - %I64u)",
-          pszIfName ? pszIfName : (char *) pTable->table[dwIfIdx].bDescr,
-          inet_ntop (AF_INET, &dwIP, dst, INET_ADDRSTRLEN),
-          *((unsigned long long *) bPhysAddr));
-        szEntry[1000] = 0;
+/**
+ * Lists all network interfaces in a combo box
+ * Used by the basic GTK configurator
+ *
+ * @param callback function to call for each NIC
+ * @param callback_cls closure for callback
+ */
+int
+ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)
+{
+  int r;
+  int i;
+  struct EnumNICs3_results *results = NULL;
+  int results_count;
 
-        if (pszIfName)
-               free(pszIfName);
+  r = EnumNICs3 (&results, &results_count);
+  if (r != GNUNET_OK)
+    return GNUNET_NO;
 
-        callback(callback_cls,
-                szEntry, 
-                pAddrTable->table[dwIfIdx].dwIndex == dwExternalNIC);
-      }
-    }
-    GlobalFree(pAddrTable);
-    GlobalFree(pTable);
-  }
-
+  for (i = 0; i < results_count; i++)
+    callback (callback_cls, results[i].pretty_name, results[i].is_default);
+  GNUNET_free_non_null (results);
   return GNUNET_YES;
 }
 

Modified: gnunet/src/util/winproc.c
===================================================================
--- gnunet/src/util/winproc.c   2011-11-29 09:52:10 UTC (rev 18369)
+++ gnunet/src/util/winproc.c   2011-11-29 11:47:40 UTC (rev 18370)
@@ -46,8 +46,8 @@
 TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
 TControlService GNControlService;
 TOpenService GNOpenService;
-TGetBestInterface GNGetBestInterface;
-TGetAdaptersInfo GGetAdaptersInfo;
+TGetBestInterfaceEx GNGetBestInterfaceEx;
+TGetAdaptersInfo GNGetAdaptersInfo;
 TNetUserAdd GNNetUserAdd;
 TNetUserSetInfo GNNetUserSetInfo;
 TLsaOpenPolicy GNLsaOpenPolicy;
@@ -117,9 +117,9 @@
     GNGetIpAddrTable =
         (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
     GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
-    GNGetBestInterface =
-        (TGetBestInterface) GetProcAddress (hIphlpapi, "GetBestInterface");
-    GGetAdaptersInfo =
+    GNGetBestInterfaceEx =
+        (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx");
+    GNGetAdaptersInfo =
         (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
   }
   else
@@ -127,8 +127,8 @@
     GNGetIfEntry = NULL;
     GNGetIpAddrTable = NULL;
     GNGetIfTable = NULL;
-    GNGetBestInterface = NULL;
-    GGetAdaptersInfo = NULL;
+    GNGetBestInterfaceEx = NULL;
+    GNGetAdaptersInfo = NULL;
   }
 
   /* Service & Account functions */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]