VirtualBox

source: vbox/trunk/src/VBox/Main/win/NetIfList-win.cpp@ 15738

Last change on this file since 15738 was 15548, checked in by vboxsync, 16 years ago

fixed file headers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.6 KB
Line 
1/* $Id: NetIfList-win.cpp 15548 2008-12-15 21:33:35Z vboxsync $ */
2/** @file
3 * Main - NetIfList, Windows implementation.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_MAIN
28
29#include <iprt/asm.h>
30#include <iprt/err.h>
31#include <list>
32
33#define _WIN32_DCOM
34#include <winsock2.h>
35#include <ws2tcpip.h>
36#include <windows.h>
37
38#ifdef VBOX_WITH_NETFLT
39#include "VBox/WinNetConfig.h"
40#endif
41
42#include <iphlpapi.h>
43
44#include "Logging.h"
45#include "HostNetworkInterfaceImpl.h"
46#include "netif.h"
47
48
49static int collectNetIfInfo(Bstr &strName, PNETIFINFO pInfo)
50{
51 DWORD dwRc;
52 /*
53 * Most of the hosts probably have less than 10 adapters,
54 * so we'll mostly succeed from the first attempt.
55 */
56 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
57 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
58 if (!pAddresses)
59 return VERR_NO_MEMORY;
60 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
61 if (dwRc == ERROR_BUFFER_OVERFLOW)
62 {
63 /* Impressive! More than 10 adapters! Get more memory and try again. */
64 RTMemFree(pAddresses);
65 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
66 if (!pAddresses)
67 return VERR_NO_MEMORY;
68 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
69 }
70 if (dwRc == NO_ERROR)
71 {
72 PIP_ADAPTER_ADDRESSES pAdapter;
73 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
74 {
75 char *pszUuid = RTStrDup(pAdapter->AdapterName);
76 size_t len = strlen(pszUuid) - 1;
77 if (pszUuid[0] == '{' && pszUuid[len] == '}')
78 {
79 pszUuid[len] = 0;
80 if (!RTUuidCompareStr(&pInfo->Uuid, pszUuid + 1))
81 {
82 bool fIPFound, fIPv6Found;
83 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
84 fIPFound = fIPv6Found = false;
85 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
86 {
87 switch (pAddr->Address.lpSockaddr->sa_family)
88 {
89 case AF_INET:
90 if (!fIPFound)
91 {
92 fIPFound = true;
93 memcpy(&pInfo->IPAddress,
94 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
95 sizeof(pInfo->IPAddress));
96 }
97 break;
98 case AF_INET6:
99 if (!fIPv6Found)
100 {
101 fIPv6Found = true;
102 memcpy(&pInfo->IPv6Address,
103 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
104 sizeof(pInfo->IPv6Address));
105 }
106 break;
107 }
108 }
109 PIP_ADAPTER_PREFIX pPrefix;
110 fIPFound = fIPv6Found = false;
111 for (pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next)
112 {
113 switch (pPrefix->Address.lpSockaddr->sa_family)
114 {
115 case AF_INET:
116 if (!fIPFound)
117 {
118 fIPFound = true;
119 ASMBitSetRange(&pInfo->IPNetMask, 0, pPrefix->PrefixLength);
120 }
121 break;
122 case AF_INET6:
123 if (!fIPv6Found)
124 {
125 fIPv6Found = true;
126 ASMBitSetRange(&pInfo->IPv6NetMask, 0, pPrefix->PrefixLength);
127 }
128 break;
129 }
130 }
131 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
132 Log(("collectNetIfInfo: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
133 else
134 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
135 pInfo->enmType = NETIF_T_ETHERNET;
136 pInfo->enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
137 RTStrFree(pszUuid);
138 break;
139 }
140 }
141 RTStrFree(pszUuid);
142 }
143 }
144 RTMemFree(pAddresses);
145
146 return VINF_SUCCESS;
147}
148
149#ifdef VBOX_WITH_NETFLT
150# define VBOX_APP_NAME L"VirtualBox"
151
152static int vboxNetWinAddComponent(std::list <ComObjPtr <HostNetworkInterface> > * pPist, INetCfgComponent * pncc)
153{
154 LPWSTR lpszName;
155 GUID IfGuid;
156 HRESULT hr;
157 int rc = VERR_GENERAL_FAILURE;
158
159 hr = pncc->GetDisplayName( &lpszName );
160 Assert(hr == S_OK);
161 if(hr == S_OK)
162 {
163 size_t cUnicodeName = wcslen(lpszName) + 1;
164 size_t uniLen = (cUnicodeName * 2 + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
165 Bstr name (uniLen + 1 /* extra zero */);
166 wcscpy((wchar_t *) name.mutableRaw(), lpszName);
167
168 hr = pncc->GetInstanceGuid(&IfGuid);
169 Assert(hr == S_OK);
170 if (hr == S_OK)
171 {
172 NETIFINFO Info;
173 memset(&Info, 0, sizeof(Info));
174 Info.Uuid = *(Guid(IfGuid).raw());
175 rc = collectNetIfInfo(name, &Info);
176 if (RT_FAILURE(rc))
177 {
178 Log(("vboxNetWinAddComponent: collectNetIfInfo() -> %Vrc\n", rc));
179 }
180 /* create a new object and add it to the list */
181 ComObjPtr <HostNetworkInterface> iface;
182 iface.createObject();
183 /* remove the curly bracket at the end */
184 if (SUCCEEDED (iface->init (name, &Info)))
185 {
186 pPist->push_back (iface);
187 rc = VINF_SUCCESS;
188 }
189 else
190 {
191 Assert(0);
192 }
193 }
194 CoTaskMemFree(lpszName);
195 }
196
197 return rc;
198}
199
200#else /* #ifndef VBOX_WITH_NETFLT */
201/**
202 * Windows helper function for NetIfList().
203 *
204 * @returns true / false.
205 *
206 * @param guid The GUID.
207 */
208static bool IsTAPDevice(const char *guid)
209{
210 HKEY hNetcard;
211 LONG status;
212 DWORD len;
213 int i = 0;
214 bool ret = false;
215
216 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ, &hNetcard);
217 if (status != ERROR_SUCCESS)
218 return false;
219
220 for (;;)
221 {
222 char szEnumName[256];
223 char szNetCfgInstanceId[256];
224 DWORD dwKeyType;
225 HKEY hNetCardGUID;
226
227 len = sizeof(szEnumName);
228 status = RegEnumKeyExA(hNetcard, i, szEnumName, &len, NULL, NULL, NULL, NULL);
229 if (status != ERROR_SUCCESS)
230 break;
231
232 status = RegOpenKeyExA(hNetcard, szEnumName, 0, KEY_READ, &hNetCardGUID);
233 if (status == ERROR_SUCCESS)
234 {
235 len = sizeof(szNetCfgInstanceId);
236 status = RegQueryValueExA(hNetCardGUID, "NetCfgInstanceId", NULL, &dwKeyType, (LPBYTE)szNetCfgInstanceId, &len);
237 if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
238 {
239 char szNetProductName[256];
240 char szNetProviderName[256];
241
242 szNetProductName[0] = 0;
243 len = sizeof(szNetProductName);
244 status = RegQueryValueExA(hNetCardGUID, "ProductName", NULL, &dwKeyType, (LPBYTE)szNetProductName, &len);
245
246 szNetProviderName[0] = 0;
247 len = sizeof(szNetProviderName);
248 status = RegQueryValueExA(hNetCardGUID, "ProviderName", NULL, &dwKeyType, (LPBYTE)szNetProviderName, &len);
249
250 if ( !strcmp(szNetCfgInstanceId, guid)
251 && !strcmp(szNetProductName, "VirtualBox TAP Adapter")
252 && ( (!strcmp(szNetProviderName, "innotek GmbH"))
253 || (!strcmp(szNetProviderName, "Sun Microsystems, Inc."))))
254 {
255 ret = true;
256 RegCloseKey(hNetCardGUID);
257 break;
258 }
259 }
260 RegCloseKey(hNetCardGUID);
261 }
262 ++i;
263 }
264
265 RegCloseKey(hNetcard);
266 return ret;
267}
268#endif /* #ifndef VBOX_WITH_NETFLT */
269
270int NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
271{
272#ifndef VBOX_WITH_NETFLT
273 static const char *NetworkKey = "SYSTEM\\CurrentControlSet\\Control\\Network\\"
274 "{4D36E972-E325-11CE-BFC1-08002BE10318}";
275 HKEY hCtrlNet;
276 LONG status;
277 DWORD len;
278 status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, NetworkKey, 0, KEY_READ, &hCtrlNet);
279 if (status != ERROR_SUCCESS)
280 {
281 Log(("NetIfList: Could not open registry key \"%s\"", NetworkKey));
282 return E_FAIL;
283 }
284
285 for (int i = 0;; ++ i)
286 {
287 char szNetworkGUID [256];
288 HKEY hConnection;
289 char szNetworkConnection [256];
290
291 len = sizeof (szNetworkGUID);
292 status = RegEnumKeyExA (hCtrlNet, i, szNetworkGUID, &len, NULL, NULL, NULL, NULL);
293 if (status != ERROR_SUCCESS)
294 break;
295
296 if (!IsTAPDevice(szNetworkGUID))
297 continue;
298
299 RTStrPrintf (szNetworkConnection, sizeof (szNetworkConnection),
300 "%s\\Connection", szNetworkGUID);
301 status = RegOpenKeyExA (hCtrlNet, szNetworkConnection, 0, KEY_READ, &hConnection);
302 if (status == ERROR_SUCCESS)
303 {
304 DWORD dwKeyType;
305 status = RegQueryValueExW (hConnection, TEXT("Name"), NULL,
306 &dwKeyType, NULL, &len);
307 if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
308 {
309 size_t uniLen = (len + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
310 Bstr name (uniLen + 1 /* extra zero */);
311 status = RegQueryValueExW (hConnection, TEXT("Name"), NULL,
312 &dwKeyType, (LPBYTE) name.mutableRaw(), &len);
313 if (status == ERROR_SUCCESS)
314 {
315 LogFunc(("Connection name %ls\n", name.mutableRaw()));
316 /* put a trailing zero, just in case (see MSDN) */
317 name.mutableRaw() [uniLen] = 0;
318 /* create a new object and add it to the list */
319 ComObjPtr <HostNetworkInterface> iface;
320 iface.createObject();
321 /* remove the curly bracket at the end */
322 szNetworkGUID [strlen(szNetworkGUID) - 1] = '\0';
323
324 NETIFINFO Info;
325 memset(&Info, 0, sizeof(Info));
326 Info.Uuid = *(Guid(szNetworkGUID + 1).raw());
327 int rc = collectNetIfInfo(name, &Info);
328 if (RT_FAILURE(rc))
329 {
330 Log(("vboxNetWinAddComponent: collectNetIfInfo() -> %Vrc\n", rc));
331 }
332
333 if (SUCCEEDED (iface->init (name, &Info)))
334 list.push_back (iface);
335 }
336 }
337 RegCloseKey (hConnection);
338 }
339 }
340 RegCloseKey (hCtrlNet);
341#else /* # if defined VBOX_WITH_NETFLT */
342 INetCfg *pNc;
343 INetCfgComponent *pMpNcc;
344 INetCfgComponent *pTcpIpNcc;
345 LPWSTR lpszApp;
346 HRESULT hr;
347 IEnumNetCfgBindingPath *pEnumBp;
348 INetCfgBindingPath *pBp;
349 IEnumNetCfgBindingInterface *pEnumBi;
350 INetCfgBindingInterface *pBi;
351
352 /* we are using the INetCfg API for getting the list of miniports */
353 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
354 VBOX_APP_NAME,
355 &pNc,
356 &lpszApp );
357 Assert(hr == S_OK);
358 if(hr == S_OK)
359 {
360# ifdef VBOX_NETFLT_ONDEMAND_BIND
361 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
362 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
363# else
364 /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
365 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
366# ifndef VBOX_WITH_HARDENING
367 if(hr != S_OK)
368 {
369 /* TODO: try to install the netflt from here */
370 }
371# endif
372
373# endif
374
375 if(hr == S_OK)
376 {
377 hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
378 Assert(hr == S_OK);
379 if ( hr == S_OK )
380 {
381 hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
382 Assert(hr == S_OK || hr == S_FALSE);
383 while( hr == S_OK )
384 {
385 /* S_OK == enabled, S_FALSE == disabled */
386 if(pBp->IsEnabled() == S_OK)
387 {
388 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
389 Assert(hr == S_OK);
390 if ( hr == S_OK )
391 {
392 hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
393 Assert(hr == S_OK);
394 while(hr == S_OK)
395 {
396 hr = pBi->GetLowerComponent( &pMpNcc );
397 Assert(hr == S_OK);
398 if(hr == S_OK)
399 {
400 vboxNetWinAddComponent(&list, pMpNcc);
401 VBoxNetCfgWinReleaseRef( pMpNcc );
402 }
403 VBoxNetCfgWinReleaseRef(pBi);
404
405 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
406 }
407 VBoxNetCfgWinReleaseRef(pEnumBi);
408 }
409 }
410 VBoxNetCfgWinReleaseRef(pBp);
411
412 hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
413 }
414 VBoxNetCfgWinReleaseRef(pEnumBp);
415 }
416 VBoxNetCfgWinReleaseRef(pTcpIpNcc);
417 }
418 else
419 {
420 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
421 }
422
423 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
424 }
425#endif /* # if defined VBOX_WITH_NETFLT */
426 return VINF_SUCCESS;
427}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette