VirtualBox

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

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

list tap adaptors

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.2 KB
Line 
1/* $Id: NetIfList-win.cpp 16899 2009-02-18 12:40:55Z 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#include "devguid.h"
41#endif
42
43#include <iphlpapi.h>
44
45#include "Logging.h"
46#include "HostNetworkInterfaceImpl.h"
47#include "netif.h"
48
49
50static int collectNetIfInfo(Bstr &strName, PNETIFINFO pInfo)
51{
52 DWORD dwRc;
53 /*
54 * Most of the hosts probably have less than 10 adapters,
55 * so we'll mostly succeed from the first attempt.
56 */
57 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
58 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
59 if (!pAddresses)
60 return VERR_NO_MEMORY;
61 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
62 if (dwRc == ERROR_BUFFER_OVERFLOW)
63 {
64 /* Impressive! More than 10 adapters! Get more memory and try again. */
65 RTMemFree(pAddresses);
66 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
67 if (!pAddresses)
68 return VERR_NO_MEMORY;
69 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
70 }
71 if (dwRc == NO_ERROR)
72 {
73 PIP_ADAPTER_ADDRESSES pAdapter;
74 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
75 {
76 char *pszUuid = RTStrDup(pAdapter->AdapterName);
77 size_t len = strlen(pszUuid) - 1;
78 if (pszUuid[0] == '{' && pszUuid[len] == '}')
79 {
80 pszUuid[len] = 0;
81 if (!RTUuidCompareStr(&pInfo->Uuid, pszUuid + 1))
82 {
83 bool fIPFound, fIPv6Found;
84 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
85 fIPFound = fIPv6Found = false;
86 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
87 {
88 switch (pAddr->Address.lpSockaddr->sa_family)
89 {
90 case AF_INET:
91 if (!fIPFound)
92 {
93 fIPFound = true;
94 memcpy(&pInfo->IPAddress,
95 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
96 sizeof(pInfo->IPAddress));
97 }
98 break;
99 case AF_INET6:
100 if (!fIPv6Found)
101 {
102 fIPv6Found = true;
103 memcpy(&pInfo->IPv6Address,
104 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
105 sizeof(pInfo->IPv6Address));
106 }
107 break;
108 }
109 }
110 PIP_ADAPTER_PREFIX pPrefix;
111 fIPFound = fIPv6Found = false;
112 for (pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next)
113 {
114 switch (pPrefix->Address.lpSockaddr->sa_family)
115 {
116 case AF_INET:
117 if (!fIPFound)
118 {
119 fIPFound = true;
120 ASMBitSetRange(&pInfo->IPNetMask, 0, pPrefix->PrefixLength);
121 }
122 break;
123 case AF_INET6:
124 if (!fIPv6Found)
125 {
126 fIPv6Found = true;
127 ASMBitSetRange(&pInfo->IPv6NetMask, 0, pPrefix->PrefixLength);
128 }
129 break;
130 }
131 }
132 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
133 Log(("collectNetIfInfo: Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
134 else
135 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
136 pInfo->enmType = NETIF_T_ETHERNET;
137 pInfo->enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
138 RTStrFree(pszUuid);
139 break;
140 }
141 }
142 RTStrFree(pszUuid);
143 }
144 }
145 RTMemFree(pAddresses);
146
147 return VINF_SUCCESS;
148}
149
150#ifdef VBOX_WITH_NETFLT
151# define VBOX_APP_NAME L"VirtualBox"
152
153static int vboxNetWinAddComponent(std::list <ComObjPtr <HostNetworkInterface> > * pPist, INetCfgComponent * pncc)
154{
155 LPWSTR lpszName;
156 GUID IfGuid;
157 HRESULT hr;
158 int rc = VERR_GENERAL_FAILURE;
159
160 hr = pncc->GetDisplayName( &lpszName );
161 Assert(hr == S_OK);
162 if(hr == S_OK)
163 {
164 size_t cUnicodeName = wcslen(lpszName) + 1;
165 size_t uniLen = (cUnicodeName * 2 + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
166 Bstr name (uniLen + 1 /* extra zero */);
167 wcscpy((wchar_t *) name.mutableRaw(), lpszName);
168
169 hr = pncc->GetInstanceGuid(&IfGuid);
170 Assert(hr == S_OK);
171 if (hr == S_OK)
172 {
173 NETIFINFO Info;
174 memset(&Info, 0, sizeof(Info));
175 Info.Uuid = *(Guid(IfGuid).raw());
176 rc = collectNetIfInfo(name, &Info);
177 if (RT_FAILURE(rc))
178 {
179 Log(("vboxNetWinAddComponent: collectNetIfInfo() -> %Vrc\n", rc));
180 }
181 /* create a new object and add it to the list */
182 ComObjPtr <HostNetworkInterface> iface;
183 iface.createObject();
184 /* remove the curly bracket at the end */
185 if (SUCCEEDED (iface->init (name, &Info)))
186 {
187 pPist->push_back (iface);
188 rc = VINF_SUCCESS;
189 }
190 else
191 {
192 Assert(0);
193 }
194 }
195 CoTaskMemFree(lpszName);
196 }
197
198 return rc;
199}
200
201#else /* #ifndef VBOX_WITH_NETFLT */
202/**
203 * Windows helper function for NetIfList().
204 *
205 * @returns true / false.
206 *
207 * @param guid The GUID.
208 */
209static bool IsTAPDevice(const char *guid)
210{
211 HKEY hNetcard;
212 LONG status;
213 DWORD len;
214 int i = 0;
215 bool ret = false;
216
217 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ, &hNetcard);
218 if (status != ERROR_SUCCESS)
219 return false;
220
221 for (;;)
222 {
223 char szEnumName[256];
224 char szNetCfgInstanceId[256];
225 DWORD dwKeyType;
226 HKEY hNetCardGUID;
227
228 len = sizeof(szEnumName);
229 status = RegEnumKeyExA(hNetcard, i, szEnumName, &len, NULL, NULL, NULL, NULL);
230 if (status != ERROR_SUCCESS)
231 break;
232
233 status = RegOpenKeyExA(hNetcard, szEnumName, 0, KEY_READ, &hNetCardGUID);
234 if (status == ERROR_SUCCESS)
235 {
236 len = sizeof(szNetCfgInstanceId);
237 status = RegQueryValueExA(hNetCardGUID, "NetCfgInstanceId", NULL, &dwKeyType, (LPBYTE)szNetCfgInstanceId, &len);
238 if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
239 {
240 char szNetProductName[256];
241 char szNetProviderName[256];
242
243 szNetProductName[0] = 0;
244 len = sizeof(szNetProductName);
245 status = RegQueryValueExA(hNetCardGUID, "ProductName", NULL, &dwKeyType, (LPBYTE)szNetProductName, &len);
246
247 szNetProviderName[0] = 0;
248 len = sizeof(szNetProviderName);
249 status = RegQueryValueExA(hNetCardGUID, "ProviderName", NULL, &dwKeyType, (LPBYTE)szNetProviderName, &len);
250
251 if ( !strcmp(szNetCfgInstanceId, guid)
252 && !strcmp(szNetProductName, "VirtualBox TAP Adapter")
253 && ( (!strcmp(szNetProviderName, "innotek GmbH"))
254 || (!strcmp(szNetProviderName, "Sun Microsystems, Inc."))))
255 {
256 ret = true;
257 RegCloseKey(hNetCardGUID);
258 break;
259 }
260 }
261 RegCloseKey(hNetCardGUID);
262 }
263 ++i;
264 }
265
266 RegCloseKey(hNetcard);
267 return ret;
268}
269#endif /* #ifndef VBOX_WITH_NETFLT */
270
271int NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
272{
273#ifndef VBOX_WITH_NETFLT
274 static const char *NetworkKey = "SYSTEM\\CurrentControlSet\\Control\\Network\\"
275 "{4D36E972-E325-11CE-BFC1-08002BE10318}";
276 HKEY hCtrlNet;
277 LONG status;
278 DWORD len;
279 status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, NetworkKey, 0, KEY_READ, &hCtrlNet);
280 if (status != ERROR_SUCCESS)
281 {
282 Log(("NetIfList: Could not open registry key \"%s\"", NetworkKey));
283 return E_FAIL;
284 }
285
286 for (int i = 0;; ++ i)
287 {
288 char szNetworkGUID [256];
289 HKEY hConnection;
290 char szNetworkConnection [256];
291
292 len = sizeof (szNetworkGUID);
293 status = RegEnumKeyExA (hCtrlNet, i, szNetworkGUID, &len, NULL, NULL, NULL, NULL);
294 if (status != ERROR_SUCCESS)
295 break;
296
297 if (!IsTAPDevice(szNetworkGUID))
298 continue;
299
300 RTStrPrintf (szNetworkConnection, sizeof (szNetworkConnection),
301 "%s\\Connection", szNetworkGUID);
302 status = RegOpenKeyExA (hCtrlNet, szNetworkConnection, 0, KEY_READ, &hConnection);
303 if (status == ERROR_SUCCESS)
304 {
305 DWORD dwKeyType;
306 status = RegQueryValueExW (hConnection, TEXT("Name"), NULL,
307 &dwKeyType, NULL, &len);
308 if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
309 {
310 size_t uniLen = (len + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
311 Bstr name (uniLen + 1 /* extra zero */);
312 status = RegQueryValueExW (hConnection, TEXT("Name"), NULL,
313 &dwKeyType, (LPBYTE) name.mutableRaw(), &len);
314 if (status == ERROR_SUCCESS)
315 {
316 LogFunc(("Connection name %ls\n", name.mutableRaw()));
317 /* put a trailing zero, just in case (see MSDN) */
318 name.mutableRaw() [uniLen] = 0;
319 /* create a new object and add it to the list */
320 ComObjPtr <HostNetworkInterface> iface;
321 iface.createObject();
322 /* remove the curly bracket at the end */
323 szNetworkGUID [strlen(szNetworkGUID) - 1] = '\0';
324
325 NETIFINFO Info;
326 memset(&Info, 0, sizeof(Info));
327 Info.Uuid = *(Guid(szNetworkGUID + 1).raw());
328 int rc = collectNetIfInfo(name, &Info);
329 if (RT_FAILURE(rc))
330 {
331 Log(("vboxNetWinAddComponent: collectNetIfInfo() -> %Vrc\n", rc));
332 }
333
334 if (SUCCEEDED (iface->init (name, &Info)))
335 list.push_back (iface);
336 }
337 }
338 RegCloseKey (hConnection);
339 }
340 }
341 RegCloseKey (hCtrlNet);
342#else /* # if defined VBOX_WITH_NETFLT */
343 INetCfg *pNc;
344 INetCfgComponent *pMpNcc;
345 INetCfgComponent *pTcpIpNcc;
346 LPWSTR lpszApp;
347 HRESULT hr;
348 IEnumNetCfgBindingPath *pEnumBp;
349 INetCfgBindingPath *pBp;
350 IEnumNetCfgBindingInterface *pEnumBi;
351 INetCfgBindingInterface *pBi;
352
353 /* we are using the INetCfg API for getting the list of miniports */
354 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
355 VBOX_APP_NAME,
356 &pNc,
357 &lpszApp );
358 Assert(hr == S_OK);
359 if(hr == S_OK)
360 {
361# ifdef VBOX_NETFLT_ONDEMAND_BIND
362 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
363 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
364# else
365 /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
366 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
367# ifndef VBOX_WITH_HARDENING
368 if(hr != S_OK)
369 {
370 /* TODO: try to install the netflt from here */
371 }
372# endif
373
374# endif
375
376 if(hr == S_OK)
377 {
378 hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
379 Assert(hr == S_OK);
380 if ( hr == S_OK )
381 {
382 hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
383 Assert(hr == S_OK || hr == S_FALSE);
384 while( hr == S_OK )
385 {
386 /* S_OK == enabled, S_FALSE == disabled */
387 if(pBp->IsEnabled() == S_OK)
388 {
389 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
390 Assert(hr == S_OK);
391 if ( hr == S_OK )
392 {
393 hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
394 Assert(hr == S_OK);
395 while(hr == S_OK)
396 {
397 hr = pBi->GetLowerComponent( &pMpNcc );
398 Assert(hr == S_OK);
399 if(hr == S_OK)
400 {
401 ULONG uComponentStatus;
402 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
403#ifndef DEBUG_bird
404 Assert(hr == S_OK);
405#endif
406 if(hr == S_OK)
407 {
408 if(uComponentStatus == 0)
409 {
410 vboxNetWinAddComponent(&list, pMpNcc);
411 }
412 }
413 VBoxNetCfgWinReleaseRef( pMpNcc );
414 }
415 VBoxNetCfgWinReleaseRef(pBi);
416
417 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
418 }
419 VBoxNetCfgWinReleaseRef(pEnumBi);
420 }
421 }
422 VBoxNetCfgWinReleaseRef(pBp);
423
424 hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
425 }
426 VBoxNetCfgWinReleaseRef(pEnumBp);
427 }
428 VBoxNetCfgWinReleaseRef(pTcpIpNcc);
429 }
430 else
431 {
432 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
433 }
434
435 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
436 }
437#endif /* # if defined VBOX_WITH_NETFLT */
438 return VINF_SUCCESS;
439}
440
441int NetIfListTap(std::list <ComObjPtr <HostNetworkInterface> > &list)
442{
443#ifndef VBOX_WITH_NETFLT
444 /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
445 return VERR_NOT_IMPLEMENTED;
446#else /* # if defined VBOX_WITH_NETFLT */
447 INetCfg *pNc;
448 INetCfgComponent *pMpNcc;
449 LPWSTR lpszApp = NULL;
450 HRESULT hr;
451 IEnumNetCfgComponent *pEnumComponent;
452
453 /* we are using the INetCfg API for getting the list of miniports */
454 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
455 VBOX_APP_NAME,
456 &pNc,
457 &lpszApp );
458 Assert(hr == S_OK);
459 if(hr == S_OK)
460 {
461 hr = VBoxNetCfgWinGetComponentEnum(pNc, &GUID_DEVCLASS_NET, &pEnumComponent);
462 if(hr == S_OK)
463 {
464 while(hr = VBoxNetCfgWinGetNextComponent(pEnumComponent, &pMpNcc) == S_OK)
465 {
466 ULONG uComponentStatus;
467 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
468#ifndef DEBUG_bird
469 Assert(hr == S_OK);
470#endif
471 if(hr == S_OK)
472 {
473 if(uComponentStatus == 0)
474 {
475 LPWSTR pId;
476 hr = pMpNcc->GetId(&pId);
477 Assert(hr == S_OK);
478 if(hr == S_OK)
479 {
480 if(!wcscmp(pId, L"sun_VBoxNetAdp"))
481 {
482 vboxNetWinAddComponent(&list, pMpNcc);
483 }
484 CoTaskMemFree(pId);
485 }
486 }
487 }
488 VBoxNetCfgWinReleaseRef(pMpNcc);
489 }
490 Assert(hr == S_OK || hr == S_FALSE);
491
492 VBoxNetCfgWinReleaseRef(pEnumComponent);
493 }
494 else
495 {
496 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
497 }
498
499 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
500 }
501 else if(lpszApp)
502 {
503 CoTaskMemFree(lpszApp);
504 }
505#endif /* # if defined VBOX_WITH_NETFLT */
506 return VINF_SUCCESS;
507}
Note: See TracBrowser for help on using the repository browser.

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