[Top][All Lists]
[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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r18370 - in gnunet/src: include util,
gnunet <=