aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-11-29 11:47:40 +0000
committerChristian Grothoff <christian@grothoff.org>2011-11-29 11:47:40 +0000
commitd155690a24d645e746d7cd12e5c1d47646d96558 (patch)
tree657f47d48cf70950ba240ebc0414a71f6cac6bed /src
parentba232c9d203303cd2beb2994fc49c5d5b700d85c (diff)
downloadgnunet-d155690a24d645e746d7cd12e5c1d47646d96558.tar.gz
gnunet-d155690a24d645e746d7cd12e5c1d47646d96558.zip
LRN: new code for GNUNET_OS_network_interfaces_list on W32 improving support for IPv6 and subnets/masks, see Mantis 1958
Diffstat (limited to 'src')
-rw-r--r--src/include/winproc.h27
-rw-r--r--src/util/Makefile.am2
-rw-r--r--src/util/os_network.c135
-rw-r--r--src/util/win.cc693
-rw-r--r--src/util/winproc.c14
5 files changed, 618 insertions, 253 deletions
diff --git a/src/include/winproc.h b/src/include/winproc.h
index 05c4ac1bf..ac4eecdfb 100644
--- a/src/include/winproc.h
+++ b/src/include/winproc.h
@@ -62,6 +62,10 @@ extern "C"
62 PULONG pdwSize, BOOL bOrder); 62 PULONG pdwSize, BOOL bOrder);
63 typedef DWORD WINAPI (*TGetIfTable) (PMIB_IFTABLE pIfTable, PULONG pdwSize, 63 typedef DWORD WINAPI (*TGetIfTable) (PMIB_IFTABLE pIfTable, PULONG pdwSize,
64 BOOL bOrder); 64 BOOL bOrder);
65 typedef DWORD WINAPI (*TGetBestInterfaceEx) (struct sockaddr *, PDWORD);
66 /* TODO: Explicitly import -A variants (i.e. TCreateHardLinkA) or -W
67 * variants (TCreateHardLinkW), etc.
68 */
65 typedef DWORD WINAPI (*TCreateHardLink) (LPCTSTR lpFileName, 69 typedef DWORD WINAPI (*TCreateHardLink) (LPCTSTR lpFileName,
66 LPCTSTR lpExistingFileName, 70 LPCTSTR lpExistingFileName,
67 LPSECURITY_ATTRIBUTES 71 LPSECURITY_ATTRIBUTES
@@ -99,8 +103,6 @@ extern "C"
99 typedef SC_HANDLE WINAPI (*TOpenService) (SC_HANDLE hSCManager, 103 typedef SC_HANDLE WINAPI (*TOpenService) (SC_HANDLE hSCManager,
100 LPCTSTR lpServiceName, 104 LPCTSTR lpServiceName,
101 DWORD dwDesiredAccess); 105 DWORD dwDesiredAccess);
102 typedef DWORD WINAPI (*TGetBestInterface) (IPAddr dwDestAddr,
103 PDWORD pdwBestIfIndex);
104 typedef DWORD WINAPI (*TGetAdaptersInfo) (PIP_ADAPTER_INFO pAdapterInfo, 106 typedef DWORD WINAPI (*TGetAdaptersInfo) (PIP_ADAPTER_INFO pAdapterInfo,
105 PULONG pOutBufLen); 107 PULONG pOutBufLen);
106 typedef NET_API_STATUS WINAPI (*TNetUserAdd) (LPCWSTR, DWORD, PBYTE, PDWORD); 108 typedef NET_API_STATUS WINAPI (*TNetUserAdd) (LPCWSTR, DWORD, PBYTE, PDWORD);
@@ -158,6 +160,7 @@ extern "C"
158 PSID psidGroup, PACL pDacl, 160 PSID psidGroup, PACL pDacl,
159 PACL pSacl); 161 PACL pSacl);
160 162
163 extern TGetBestInterfaceEx GNGetBestInterfaceEx;
161 extern TNtQuerySystemInformation GNNtQuerySystemInformation; 164 extern TNtQuerySystemInformation GNNtQuerySystemInformation;
162 extern TGetIfEntry GNGetIfEntry; 165 extern TGetIfEntry GNGetIfEntry;
163 extern TGetIpAddrTable GNGetIpAddrTable; 166 extern TGetIpAddrTable GNGetIpAddrTable;
@@ -172,8 +175,7 @@ extern "C"
172 extern TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; 175 extern TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
173 extern TControlService GNControlService; 176 extern TControlService GNControlService;
174 extern TOpenService GNOpenService; 177 extern TOpenService GNOpenService;
175 extern TGetBestInterface GNGetBestInterface; 178 extern TGetAdaptersInfo GNGetAdaptersInfo;
176 extern TGetAdaptersInfo GGetAdaptersInfo;
177 extern TNetUserAdd GNNetUserAdd; 179 extern TNetUserAdd GNNetUserAdd;
178 extern TNetUserSetInfo GNNetUserSetInfo; 180 extern TNetUserSetInfo GNNetUserSetInfo;
179 extern TLsaOpenPolicy GNLsaOpenPolicy; 181 extern TLsaOpenPolicy GNLsaOpenPolicy;
@@ -202,6 +204,23 @@ extern "C"
202 DWORD dwAccessMask); 204 DWORD dwAccessMask);
203 char *winErrorStr (const char *prefix, int dwErr); 205 char *winErrorStr (const char *prefix, int dwErr);
204 void EnumNICs (PMIB_IFTABLE * pIfTable, PMIB_IPADDRTABLE * pAddrTable); 206 void EnumNICs (PMIB_IFTABLE * pIfTable, PMIB_IPADDRTABLE * pAddrTable);
207
208#define ENUMNICS3_MASK_OK 0x01
209#define ENUMNICS3_BCAST_OK 0x02
210
211struct EnumNICs3_results
212{
213 unsigned char flags;
214 int is_default;
215 char pretty_name[1001];
216 size_t addr_size;
217 struct sockaddr address;
218 struct sockaddr mask;
219 struct sockaddr broadcast;
220};
221
222 int EnumNICs3 (struct EnumNICs3_results **, int *EnumNICs3_results_count);
223 void EnumNICs3_free (struct EnumNICs3_results *);
205 int GNInitWinEnv (); 224 int GNInitWinEnv ();
206 void GNShutdownWinEnv (); 225 void GNShutdownWinEnv ();
207 226
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c62fc4246..a2e7f2449 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -17,7 +17,7 @@ libgnunetutilwin_la_LDFLAGS = \
17 -no-undefined -Wl,--export-all-symbols 17 -no-undefined -Wl,--export-all-symbols
18libgnunetutilwin_la_LIBADD = \ 18libgnunetutilwin_la_LIBADD = \
19 -lshell32 -liconv -lstdc++ \ 19 -lshell32 -liconv -lstdc++ \
20 -lcomdlg32 -lgdi32 20 -lcomdlg32 -lgdi32 -liphlpapi
21WINLIB = libgnunetutilwin.la 21WINLIB = libgnunetutilwin.la
22endif 22endif
23 23
diff --git a/src/util/os_network.c b/src/util/os_network.c
index 54a4e7577..a4758496e 100644
--- a/src/util/os_network.c
+++ b/src/util/os_network.c
@@ -25,6 +25,7 @@
25 * @author Nils Durner 25 * @author Nils Durner
26 * @author Heikki Lindholm 26 * @author Heikki Lindholm
27 * @author Jake Dust 27 * @author Jake Dust
28 * @author LRN
28 */ 29 */
29 30
30#include "platform.h" 31#include "platform.h"
@@ -46,128 +47,26 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc,
46 void *proc_cls) 47 void *proc_cls)
47{ 48{
48#ifdef MINGW 49#ifdef MINGW
49 PMIB_IFTABLE pTable; 50 int r;
50 PMIB_IPADDRTABLE pAddrTable; 51 int i;
51 DWORD dwIfIdx, dwExternalNIC; 52 struct EnumNICs3_results *results = NULL;
52 IPAddr theIP; 53 int results_count;
53 54
54 /* Determine our external NIC */ 55 r = EnumNICs3 (&results, &results_count);
55 theIP = inet_addr ("192.0.34.166"); /* www.example.com */ 56 if (r != GNUNET_OK)
56 if ((!GNGetBestInterface) || 57 return;
57 (GNGetBestInterface (theIP, &dwExternalNIC) != NO_ERROR))
58 {
59 dwExternalNIC = 0;
60 }
61
62 /* Enumerate NICs */
63 EnumNICs (&pTable, &pAddrTable);
64 58
65 if (pTable) 59 for (i = 0; i < results_count; i++)
66 { 60 {
67 for (dwIfIdx = 0; dwIfIdx <= pTable->dwNumEntries; dwIfIdx++) 61 if (GNUNET_OK != proc (proc_cls, results[i].pretty_name,
68 { 62 results[i].is_default,
69 char szEntry[1001]; 63 &results[i].address,
70 DWORD dwIP = 0; 64 results[i].flags & ENUMNICS3_MASK_OK ? &results[i].mask : NULL,
71 PIP_ADAPTER_INFO pAdapterInfo; 65 results[i].flags & ENUMNICS3_BCAST_OK ? &results[i].broadcast : NULL,
72 PIP_ADAPTER_INFO pAdapter = NULL; 66 results[i].addr_size))
73 DWORD dwRetVal = 0; 67 break;
74
75 /* Get IP-Address */
76 int i;
77
78 for (i = 0; i < pAddrTable->dwNumEntries; i++)
79 {
80 if (pAddrTable->table[i].dwIndex == pTable->table[dwIfIdx].dwIndex)
81 {
82 dwIP = pAddrTable->table[i].dwAddr;
83 break;
84 }
85 }
86
87 if (dwIP)
88 {
89 BYTE bPhysAddr[MAXLEN_PHYSADDR];
90 char *pszIfName = NULL;
91 char dst[INET_ADDRSTRLEN];
92 struct sockaddr_in sa;
93
94 /* Get friendly interface name */
95 pAdapterInfo = (IP_ADAPTER_INFO *) malloc (sizeof (IP_ADAPTER_INFO));
96 ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
97
98 /* Make an initial call to GetAdaptersInfo to get
99 * the necessary size into the ulOutBufLen variable */
100 if (GGetAdaptersInfo (pAdapterInfo, &ulOutBufLen) ==
101 ERROR_BUFFER_OVERFLOW)
102 {
103 free (pAdapterInfo);
104 pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);
105 }
106
107 if ((dwRetVal =
108 GGetAdaptersInfo (pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
109 {
110 pAdapter = pAdapterInfo;
111 while (pAdapter)
112 {
113 if (pTable->table[dwIfIdx].dwIndex == pAdapter->Index)
114 {
115 char szKey[251];
116 long lLen = 250;
117
118 sprintf (szKey,
119 "SYSTEM\\CurrentControlSet\\Control\\Network\\"
120 "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
121 pAdapter->AdapterName);
122 pszIfName = (char *) malloc (251);
123 if (QueryRegistry
124 (HKEY_LOCAL_MACHINE, szKey, "Name", pszIfName,
125 &lLen) != ERROR_SUCCESS)
126 {
127 free (pszIfName);
128 pszIfName = NULL;
129 }
130 }
131 pAdapter = pAdapter->Next;
132 }
133 }
134 free (pAdapterInfo);
135
136 /* Set entry */
137 memset (bPhysAddr, 0, MAXLEN_PHYSADDR);
138 memcpy (bPhysAddr, pTable->table[dwIfIdx].bPhysAddr,
139 pTable->table[dwIfIdx].dwPhysAddrLen);
140
141 snprintf (szEntry, 1000, "%s (%s - %I64u)",
142 pszIfName ? pszIfName : (char *) pTable->
143 table[dwIfIdx].bDescr, inet_ntop (AF_INET, &dwIP, dst,
144 INET_ADDRSTRLEN),
145 *((unsigned long long *) bPhysAddr));
146 szEntry[1000] = 0;
147
148 if (pszIfName)
149 free (pszIfName);
150
151 sa.sin_family = AF_INET;
152#if HAVE_SOCKADDR_IN_SIN_LEN
153 sa.sin_len = (u_char) sizeof (struct sockaddr_in);
154#endif
155 sa.sin_addr.S_un.S_addr = dwIP;
156
157 if (GNUNET_OK !=
158 proc (proc_cls, szEntry,
159 pTable->table[dwIfIdx].dwIndex == dwExternalNIC,
160 (const struct sockaddr *) &sa,
161 NULL,
162 NULL,
163 sizeof (sa)))
164 break;
165 }
166 }
167 GlobalFree (pAddrTable);
168 GlobalFree (pTable);
169 } 68 }
170 69 EnumNICs3_free (results);
171 return; 70 return;
172 71
173#elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS 72#elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS
diff --git a/src/util/win.cc b/src/util/win.cc
index b462033b9..594b9a210 100644
--- a/src/util/win.cc
+++ b/src/util/win.cc
@@ -44,161 +44,608 @@ extern "C" {
44 44
45int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows); 45int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);
46 46
47/** 47#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
48 * Enumerate all network adapters 48 union { \
49 */ 49 struct { \
50void EnumNICs(PMIB_IFTABLE *pIfTable, PMIB_IPADDRTABLE *pAddrTable) 50 ULONG Length; \
51{ 51 DWORD Flags; \
52 DWORD dwSize, dwRet; 52 }; \
53 }; \
54
55#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \
56 SOCKET_ADDRESS Address; \
57 IP_PREFIX_ORIGIN PrefixOrigin; \
58 IP_SUFFIX_ORIGIN SuffixOrigin; \
59 IP_DAD_STATE DadState; \
60 ULONG ValidLifetime; \
61 ULONG PreferredLifetime; \
62 ULONG LeaseLifetime;
63
64#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \
65 UINT8 OnLinkPrefixLength;
66
67
68#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \
69typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \
70 _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
71 struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \
72 _IP_ADAPTER_UNICAST_ADDRESS_BASE \
73 addition \
74} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;
75
76/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */
77_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)
78
79
80typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {
81 union {
82 ULONGLONG Alignment;
83 struct {
84 ULONG Length;
85 DWORD Reserved;
86 };
87 };
88 struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;
89 SOCKET_ADDRESS Address;
90} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
91
92typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {
93 union {
94 ULONGLONG Alignment;
95 struct {
96 ULONG Length;
97 DWORD Reserved;
98 };
99 };
100 struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;
101 SOCKET_ADDRESS Address;
102} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;
103
104typedef UINT32 NET_IF_COMPARTMENT_ID;
105typedef GUID NET_IF_NETWORK_GUID;
106
107typedef enum _NET_IF_CONNECTION_TYPE {
108 NET_IF_CONNECTION_DEDICATED = 1,
109 NET_IF_CONNECTION_PASSIVE,
110 NET_IF_CONNECTION_DEMAND,
111 NET_IF_CONNECTION_MAXIMUM
112} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;
113
114typedef enum {
115 TUNNEL_TYPE_NONE = 0,
116 TUNNEL_TYPE_OTHER,
117 TUNNEL_TYPE_DIRECT,
118 TUNNEL_TYPE_6TO4,
119 TUNNEL_TYPE_ISATAP,
120 TUNNEL_TYPE_TEREDO,
121 TUNNEL_TYPE_IPHTTPS
122} TUNNEL_TYPE, *PTUNNEL_TYPE;
53 123
54 *pIfTable = NULL; 124/*
125A DUID consists of a two-octet type code represented in network byte
126 order, followed by a variable number of octets that make up the
127 actual identifier. A DUID can be no more than 128 octets long (not
128 including the type code).
129*/
130#define MAX_DHCPV6_DUID_LENGTH 130
131
132typedef union _NET_LUID {
133 ULONG64 Value;
134 struct {
135 ULONG64 Reserved :24;
136 ULONG64 NetLuidIndex :24;
137 ULONG64 IfType :16;
138 } Info;
139} NET_LUID, *PNET_LUID, IF_LUID;
140
141#define MAX_DNS_SUFFIX_STRING_LENGTH 246
142
143typedef struct _IP_ADAPTER_DNS_SUFFIX {
144 struct _IP_ADAPTER_DNS_SUFFIX *Next;
145 WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];
146} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;
147
148
149
150#define _IP_ADAPTER_ADDRESSES_HEAD \
151 union { \
152 ULONGLONG Alignment; \
153 struct { \
154 ULONG Length; \
155 DWORD IfIndex; \
156 }; \
157 };
158
159#define _IP_ADAPTER_ADDRESSES_BASE \
160 PCHAR AdapterName; \
161 PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \
162 PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \
163 PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \
164 PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \
165 PWCHAR DnsSuffix; \
166 PWCHAR Description; \
167 PWCHAR FriendlyName; \
168 BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \
169 DWORD PhysicalAddressLength; \
170 DWORD Flags; \
171 DWORD Mtu; \
172 DWORD IfType; \
173 IF_OPER_STATUS OperStatus;
174
175#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
176 DWORD Ipv6IfIndex; \
177 DWORD ZoneIndices[16]; \
178 PIP_ADAPTER_PREFIX FirstPrefix; \
179
180
181#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \
182 _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
183 ULONG64 TransmitLinkSpeed; \
184 ULONG64 ReceiveLinkSpeed; \
185 PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \
186 PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \
187 ULONG Ipv4Metric; \
188 ULONG Ipv6Metric; \
189 IF_LUID Luid; \
190 SOCKET_ADDRESS Dhcpv4Server; \
191 NET_IF_COMPARTMENT_ID CompartmentId; \
192 NET_IF_NETWORK_GUID NetworkGuid; \
193 NET_IF_CONNECTION_TYPE ConnectionType; \
194 TUNNEL_TYPE TunnelType; \
195 SOCKET_ADDRESS Dhcpv6Server; \
196 BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \
197 ULONG Dhcpv6ClientDuidLength; \
198 ULONG Dhcpv6Iaid;
199
200#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \
201 _IP_ADAPTER_ADDRESSES_ADD_VISTA \
202 PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;
203
204#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \
205typedef struct _IP_ADAPTER_ADDRESSES##suffix { \
206 _IP_ADAPTER_ADDRESSES_HEAD \
207 struct _IP_ADAPTER_ADDRESSES##suffix *Next; \
208 _IP_ADAPTER_ADDRESSES_BASE \
209 addition \
210} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;
211
212
213/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */
214_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)
215_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)
216_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)
217
218static int
219EnumNICs_IPv6_get_ifs_count (SOCKET s)
220{
221 DWORD dwret = 0, err;
222 int iret;
223 iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,
224 &dwret, NULL, NULL);
225 err = GetLastError ();
226 if (iret == SOCKET_ERROR && err == WSAEFAULT)
227 return dwret;
228 else if (iret == 0)
229 return 0;
230 return GNUNET_SYSERR;
231}
55 232
56 if (pAddrTable) 233static int
57 *pAddrTable = NULL; 234EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)
235{
236 int iret;
237 DWORD dwret = 0;
238 iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,
239 &dwret, NULL, NULL);
58 240
59 if (GNGetIfTable) 241 if (iret != 0 || dwret != size)
60 { 242 {
61 dwSize = dwRet = 0; 243 /* It's supposed to succeed! And size should be the same */
244 return GNUNET_SYSERR;
245 }
246 return GNUNET_OK;
247}
62 248
63 *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, sizeof(MIB_IFTABLE)); 249#undef GNUNET_malloc
250#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \
251 HEAP_GENERATE_EXCEPTIONS, a)
64 252
65 /* Get size of table */ 253#undef GNUNET_free
66 if (GNGetIfTable(*pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 254#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)
67 {
68 GlobalFree(*pIfTable);
69 *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, dwSize);
70 }
71 255
72 if ((dwRet = GNGetIfTable(*pIfTable, &dwSize, 0)) == NO_ERROR && 256#undef GNUNET_free_non_null
73 pAddrTable) 257#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0)
74 {
75 DWORD dwIfIdx, dwSize = sizeof(MIB_IPADDRTABLE);
76 *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);
77 258
78 /* Make an initial call to GetIpAddrTable to get the 259static int
79 necessary size */ 260EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)
80 if (GNGetIpAddrTable(*pAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 261{
262 int iret;
263 DWORD dwret = 0;
264 DWORD error;
265 INTERFACE_INFO *ii = NULL;
266 DWORD ii_size = sizeof (INTERFACE_INFO) * 15;
267 while (TRUE)
268 {
269 if (ii_size >= sizeof (INTERFACE_INFO) * 1000)
270 return GNUNET_SYSERR;
271 ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);
272 dwret = 0;
273 iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,
274 &dwret, NULL, NULL);
275 error = GetLastError ();
276 if (iret == SOCKET_ERROR)
277 {
278 if (error == WSAEFAULT)
81 { 279 {
82 GlobalFree(*pAddrTable); 280 GNUNET_free (ii);
83 *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize); 281 ii_size *= 2;
282 continue;
84 } 283 }
85 GNGetIpAddrTable(*pAddrTable, &dwSize, 0); 284 GNUNET_free (ii);
285 return GNUNET_SYSERR;
286 }
287 else
288 {
289 *inf = ii;
290 *size = dwret;
291 return GNUNET_OK;
86 } 292 }
87 } 293 }
294 return GNUNET_SYSERR;
295}
296
297int
298EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)
299{
300 int result = 0;
301 SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET;
302 DWORD dwret1 = 0, dwret2;
303 DWORD err1, err2;
304 int ifs4len = 0, ifs6len = 0;
305 INTERFACE_INFO *interfaces4 = NULL;
306 SOCKET_ADDRESS_LIST *interfaces6 = NULL;
307 SetLastError (0);
308 s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
309 err1 = GetLastError ();
310 SetLastError (0);
311 s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
312 err2 = GetLastError ();
313 if (s6 != INVALID_SOCKET)
314 {
315 ifs6len = EnumNICs_IPv6_get_ifs_count (s6);
316 if (ifs6len > 0)
317 {
318 interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);
319 result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;
320 }
321 closesocket (s6);
322 s6 = INVALID_SOCKET;
323 }
324
325 if (s4 != INVALID_SOCKET)
326 {
327 result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;
328 closesocket (s4);
329 s4 = INVALID_SOCKET;
330 }
331 if (ifs6len + ifs4len == 0)
332 goto error;
333
334 if (!result)
335 {
336 *ifs4 = interfaces4;
337 *ifs4_len = ifs4len;
338 *ifs6 = interfaces6;
339 return GNUNET_OK;
340 }
341error:
342 if (interfaces4 != NULL)
343 GNUNET_free (interfaces4);
344 if (interfaces6 != NULL)
345 GNUNET_free (interfaces6);
346 if (s4 != INVALID_SOCKET)
347 closesocket (s4);
348 if (s6 != INVALID_SOCKET)
349 closesocket (s6);
350 return GNUNET_SYSERR;
88} 351}
89 352
90/** 353/**
91 * Lists all network interfaces in a combo box 354 * Returns GNUNET_OK on OK, GNUNET_SYSERR on error
92 * Used by the basic GTK configurator
93 *
94 * @param callback function to call for each NIC
95 * @param callback_cls closure for callback
96 */ 355 */
97 int ListNICs(void (*callback) (void *, const char *, int), void * callback_cls) 356int
357EnumNICs3 (struct EnumNICs3_results **results, int *results_count)
98{ 358{
99 PMIB_IFTABLE pTable; 359 DWORD dwRetVal = 0;
100 PMIB_IPADDRTABLE pAddrTable; 360 int count = 0;
101 DWORD dwIfIdx, dwExternalNIC; 361 ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |
102 IPAddr theIP; 362 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
103 363 struct sockaddr_in6 examplecom6;
104 /* Determine our external NIC */ 364 IPAddr examplecom;
105 theIP = inet_addr("192.0.34.166"); /* www.example.com */ 365 DWORD best_interface = 0;
106 if ((! GNGetBestInterface) || 366 DWORD best_interface6 = 0;
107 (GNGetBestInterface(theIP, &dwExternalNIC) != NO_ERROR)) 367
368 int use_enum2 = 0;
369 INTERFACE_INFO *interfaces4 = NULL;
370 int interfaces4_len = 0;
371 SOCKET_ADDRESS_LIST *interfaces6 = NULL;
372
373 unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
374 IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;
375 IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
376
377 if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)
378 == ERROR_BUFFER_OVERFLOW)
379 {
380 GNUNET_free (pAddresses);
381 pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
382 }
383
384 dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
385
386 if (dwRetVal != NO_ERROR)
387 {
388 GNUNET_free (pAddresses);
389 return GNUNET_SYSERR;
390 }
391
392 if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))
393 {
394 use_enum2 = 1;
395
396 /* Enumerate NICs using WSAIoctl() */
397 if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))
398 {
399 GNUNET_free (pAddresses);
400 return GNUNET_SYSERR;
401 }
402 }
403
404 examplecom = inet_addr("192.0.34.166"); /* www.example.com */
405 if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)
406 best_interface = 0;
407
408 if (GNGetBestInterfaceEx != NULL)
108 { 409 {
109 dwExternalNIC = 0; 410 examplecom6.sin6_family = AF_INET6;
411 examplecom6.sin6_port = 0;
412 examplecom6.sin6_flowinfo = 0;
413 examplecom6.sin6_scope_id = 0;
414 inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",
415 (struct sockaddr *) &examplecom6.sin6_addr);
416 dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,
417 &best_interface6);
418 if (dwRetVal != NO_ERROR)
419 best_interface6 = 0;
110 } 420 }
111 421
112 /* Enumerate NICs */ 422 /* Give IPv6 a priority */
113 EnumNICs(&pTable, &pAddrTable); 423 if (best_interface6 != 0)
424 best_interface = best_interface6;
114 425
115 if (pTable) 426 count = 0;
427 for (pCurrentAddress = pAddresses;
428 pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
116 { 429 {
117 for(dwIfIdx=0; dwIfIdx <= pTable->dwNumEntries; dwIfIdx++) 430 if (pCurrentAddress->OperStatus == IfOperStatusUp)
118 { 431 {
119 char szEntry[1001]; 432 IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
120 DWORD dwIP = 0; 433 for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
121 int iItm; 434 unicast = unicast->Next)
122 PIP_ADAPTER_INFO pAdapterInfo;
123 PIP_ADAPTER_INFO pAdapter = NULL;
124 DWORD dwRetVal = 0;
125
126 /* Get IP-Address */
127 int i;
128 for(i = 0; i < pAddrTable->dwNumEntries; i++)
129 { 435 {
130 if (pAddrTable->table[i].dwIndex == pTable->table[dwIfIdx].dwIndex) 436 if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||
437 unicast->Address.lpSockaddr->sa_family == AF_INET6) &&
438 (unicast->DadState == IpDadStateDeprecated ||
439 unicast->DadState == IpDadStatePreferred))
440 count += 1;
441 }
442 }
443 }
444
445 if (count == 0)
446 {
447 *results = NULL;
448 *results_count = 0;
449 GNUNET_free (pAddresses);
450 GNUNET_free_non_null (interfaces4);
451 GNUNET_free_non_null (interfaces6);
452 return GNUNET_OK;
453 }
454
455 *results = (struct EnumNICs3_results *) GNUNET_malloc (
456 sizeof (struct EnumNICs3_results) * count);
457 *results_count = count;
458
459 count = 0;
460 for (pCurrentAddress = pAddresses;
461 pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
462 {
463 struct EnumNICs3_results *r;
464 IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
465 if (pCurrentAddress->OperStatus != IfOperStatusUp)
466 continue;
467 for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
468 unicast = unicast->Next)
469 {
470 int i, j;
471 int mask_length = -1;
472 char dst[INET6_ADDRSTRLEN + 1];
473
474 if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&
475 unicast->Address.lpSockaddr->sa_family != AF_INET6) ||
476 (unicast->DadState != IpDadStateDeprecated &&
477 unicast->DadState != IpDadStatePreferred))
478 continue;
479
480 r = &(*results)[count];
481 r->flags = 0;
482 if (pCurrentAddress->IfIndex > 0 &&
483 pCurrentAddress->IfIndex == best_interface &&
484 unicast->Address.lpSockaddr->sa_family == AF_INET)
485 r->is_default = 1;
486 else if (pCurrentAddress->Ipv6IfIndex > 0 &&
487 pCurrentAddress->Ipv6IfIndex == best_interface6 &&
488 unicast->Address.lpSockaddr->sa_family == AF_INET6)
489 r->is_default = 1;
490 else
491 r->is_default = 0;
492
493 /* Don't choose default interface twice */
494 if (r->is_default)
495 best_interface = best_interface6 = 0;
496
497 if (!use_enum2)
498 {
499 memcpy (&r->address, unicast->Address.lpSockaddr,
500 unicast->Address.iSockaddrLength);
501 memset (&r->mask, 0, sizeof (struct sockaddr));
502 mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->
503 OnLinkPrefixLength;
504 /* OnLinkPrefixLength is the number of leading 1s in the mask.
505 * OnLinkPrefixLength is available on Vista and later (hence use_enum2).
506 */
507 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
131 { 508 {
132 dwIP = pAddrTable->table[i].dwAddr; 509 struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
133 break; 510 for (i = 0; i < mask_length; i++)
511 ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
134 } 512 }
513 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
514 {
515 struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;
516 struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;
517 for (i = 0; i < mask_length; i++)
518 ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
519 memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
520 for (i = mask_length; i < 128; i++)
521 ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
522 }
523 r->flags |= ENUMNICS3_MASK_OK;
135 } 524 }
136 525 else
137 if (dwIP)
138 { 526 {
139 BYTE bPhysAddr[MAXLEN_PHYSADDR]; 527 int found = 0;
140 char *pszIfName = NULL; 528 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
141 char dst[INET_ADDRSTRLEN]; 529 {
142 530 for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++)
143 /* Get friendly interface name */ 531 {
144 pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO)); 532 struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
145 ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); 533 if (memcpy (&interfaces4[i].iiAddress.Address,
146 534 unicast->Address.lpSockaddr,
147 /* Make an initial call to GetAdaptersInfo to get 535 unicast->Address.iSockaddrLength) != 0)
148 the necessary size into the ulOutBufLen variable */ 536 continue;
149 if (GGetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { 537 found = 1;
150 free(pAdapterInfo); 538 memcpy (&r->address, &interfaces4[i].iiAddress.Address,
151 pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen); 539 sizeof (struct sockaddr_in));
152 } 540 memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,
153 541 sizeof (struct sockaddr_in));
154 if ((dwRetVal = GGetAdaptersInfo( pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { 542 for (mask_length = 0;
155 pAdapter = pAdapterInfo; 543 ((unsigned char *) &m->sin_addr)[mask_length / 8] &
156 while (pAdapter) { 544 0x80 >> (mask_length % 8); mask_length++)
157 if (pTable->table[dwIfIdx].dwIndex == pAdapter->Index) 545 {
158 { 546 }
159 char szKey[251]; 547 r->flags |= ENUMNICS3_MASK_OK;
160 long lLen = 250; 548 }
161 549 }
162 sprintf(szKey, "SYSTEM\\CurrentControlSet\\Control\\Network\\" 550 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
163 "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", 551 {
164 pAdapter->AdapterName); 552 for (i = 0;
165 pszIfName = (char *) malloc(251); 553 interfaces6 != NULL && !found && i < interfaces6->iAddressCount;
166 if (QueryRegistry(HKEY_LOCAL_MACHINE, szKey, "Name", pszIfName, 554 i++)
167 &lLen) != ERROR_SUCCESS) 555 {
168 { 556 if (memcpy (interfaces6->Address[i].lpSockaddr,
169 free(pszIfName); 557 unicast->Address.lpSockaddr,
170 pszIfName = NULL; 558 unicast->Address.iSockaddrLength) != 0)
171 } 559 continue;
172 } 560 found = 1;
173 pAdapter = pAdapter->Next; 561 memcpy (&r->address, interfaces6->Address[i].lpSockaddr,
174 } 562 sizeof (struct sockaddr_in6));
175 } 563 /* TODO: Find a way to reliably get network mask for IPv6 on XP */
176 free(pAdapterInfo); 564 memset (&r->mask, 0, sizeof (struct sockaddr));
177 565 r->flags &= ~ENUMNICS3_MASK_OK;
178 /* Set entry */ 566 }
179 memset(bPhysAddr, 0, MAXLEN_PHYSADDR); 567 }
180 memcpy(bPhysAddr, 568 if (!found)
181 pTable->table[dwIfIdx].bPhysAddr, 569 {
182 pTable->table[dwIfIdx].dwPhysAddrLen); 570 DebugBreak ();
183 571 }
184 snprintf(szEntry, 1000, "%s (%s - %I64u)", 572 }
185 pszIfName ? pszIfName : (char *) pTable->table[dwIfIdx].bDescr, 573 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
186 inet_ntop (AF_INET, &dwIP, dst, INET_ADDRSTRLEN), 574 {
187 *((unsigned long long *) bPhysAddr)); 575 struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
188 szEntry[1000] = 0; 576 struct sockaddr_in *a = (struct sockaddr_in *) &r->address;
189 577 /* copy address to broadcast, then flip all the trailing bits not
190 if (pszIfName) 578 * falling under netmask to 1,
191 free(pszIfName); 579 * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.
192 580 */
193 callback(callback_cls, 581 memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
194 szEntry, 582 for (i = mask_length; i < 32; i++)
195 pAddrTable->table[dwIfIdx].dwIndex == dwExternalNIC); 583 ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
584 r->flags |= ENUMNICS3_BCAST_OK;
585 r->addr_size = sizeof (struct sockaddr_in);
586 inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);
587 }
588 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
589 {
590 struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;
591 /* for IPv6 broadcast is not defined, zero it down */
592 memset (&r->broadcast, 0, sizeof (struct sockaddr));
593 r->flags &= ~ENUMNICS3_BCAST_OK;
594 r->addr_size = sizeof (struct sockaddr_in6);
595 inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);
196 } 596 }
597
598 i = 0;
599 i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
600 "%S (%s", pCurrentAddress->FriendlyName, dst);
601 for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)
602 i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
603 "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);
604 i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");
605 r->pretty_name[1000] = '\0';
606 count += 1;
197 } 607 }
198 GlobalFree(pAddrTable);
199 GlobalFree(pTable);
200 } 608 }
201 609
610 if (use_enum2)
611 {
612 GNUNET_free_non_null (interfaces4);
613 GNUNET_free_non_null (interfaces6);
614 }
615
616 GNUNET_free (pAddresses);
617 return GNUNET_OK;
618}
619
620void
621EnumNICs3_free (struct EnumNICs3_results *r)
622{
623 GNUNET_free (r);
624}
625
626
627/**
628 * Lists all network interfaces in a combo box
629 * Used by the basic GTK configurator
630 *
631 * @param callback function to call for each NIC
632 * @param callback_cls closure for callback
633 */
634int
635ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)
636{
637 int r;
638 int i;
639 struct EnumNICs3_results *results = NULL;
640 int results_count;
641
642 r = EnumNICs3 (&results, &results_count);
643 if (r != GNUNET_OK)
644 return GNUNET_NO;
645
646 for (i = 0; i < results_count; i++)
647 callback (callback_cls, results[i].pretty_name, results[i].is_default);
648 GNUNET_free_non_null (results);
202 return GNUNET_YES; 649 return GNUNET_YES;
203} 650}
204 651
diff --git a/src/util/winproc.c b/src/util/winproc.c
index 252cacbfb..b5245313a 100644
--- a/src/util/winproc.c
+++ b/src/util/winproc.c
@@ -46,8 +46,8 @@ TSetServiceStatus GNSetServiceStatus;
46TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; 46TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
47TControlService GNControlService; 47TControlService GNControlService;
48TOpenService GNOpenService; 48TOpenService GNOpenService;
49TGetBestInterface GNGetBestInterface; 49TGetBestInterfaceEx GNGetBestInterfaceEx;
50TGetAdaptersInfo GGetAdaptersInfo; 50TGetAdaptersInfo GNGetAdaptersInfo;
51TNetUserAdd GNNetUserAdd; 51TNetUserAdd GNNetUserAdd;
52TNetUserSetInfo GNNetUserSetInfo; 52TNetUserSetInfo GNNetUserSetInfo;
53TLsaOpenPolicy GNLsaOpenPolicy; 53TLsaOpenPolicy GNLsaOpenPolicy;
@@ -117,9 +117,9 @@ GNInitWinEnv ()
117 GNGetIpAddrTable = 117 GNGetIpAddrTable =
118 (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable"); 118 (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
119 GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable"); 119 GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
120 GNGetBestInterface = 120 GNGetBestInterfaceEx =
121 (TGetBestInterface) GetProcAddress (hIphlpapi, "GetBestInterface"); 121 (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx");
122 GGetAdaptersInfo = 122 GNGetAdaptersInfo =
123 (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo"); 123 (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
124 } 124 }
125 else 125 else
@@ -127,8 +127,8 @@ GNInitWinEnv ()
127 GNGetIfEntry = NULL; 127 GNGetIfEntry = NULL;
128 GNGetIpAddrTable = NULL; 128 GNGetIpAddrTable = NULL;
129 GNGetIfTable = NULL; 129 GNGetIfTable = NULL;
130 GNGetBestInterface = NULL; 130 GNGetBestInterfaceEx = NULL;
131 GGetAdaptersInfo = NULL; 131 GNGetAdaptersInfo = NULL;
132 } 132 }
133 133
134 /* Service & Account functions */ 134 /* Service & Account functions */