VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/win/NetIf-win.cpp@ 69063

Last change on this file since 69063 was 68620, checked in by vboxsync, 8 years ago

netIfIsWireless: CreateFile always fails for one of the adapters on my box (probably messed up config), so please don't assert. Cleaned up the code so it doesn't ignore GetBindName failure, uses IPRT instead of wide-char crt APIs for safe string construction, and correct a variable prefix or two.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 72.9 KB
Line 
1/* $Id: NetIf-win.cpp 68620 2017-09-04 17:30:59Z vboxsync $ */
2/** @file
3 * Main - NetIfList, Windows implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2016 Oracle Corporation
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
18
19
20/*********************************************************************************************************************************
21* Header Files *
22*********************************************************************************************************************************/
23#define LOG_GROUP LOG_GROUP_MAIN
24
25#define NETIF_WITHOUT_NETCFG
26
27#include <iprt/err.h>
28#include <list>
29
30#define _WIN32_DCOM
31#include <iprt/win/winsock2.h>
32#include <iprt/win/ws2tcpip.h>
33#include <iprt/win/windows.h>
34#include <tchar.h>
35
36#ifdef VBOX_WITH_NETFLT
37# include "VBox/VBoxNetCfg-win.h"
38# include "devguid.h"
39#endif
40
41#include <iprt/win/iphlpapi.h>
42#include <iprt/win/ntddndis.h>
43
44#include "Logging.h"
45#include "HostNetworkInterfaceImpl.h"
46#include "ProgressImpl.h"
47#include "VirtualBoxImpl.h"
48#include "netif.h"
49#include "ThreadTask.h"
50
51#ifdef VBOX_WITH_NETFLT
52#include <Wbemidl.h>
53#include <comdef.h>
54
55#include "svchlp.h"
56
57#include <shellapi.h>
58#define INITGUID
59#include <guiddef.h>
60#include <devguid.h>
61#include <iprt/win/objbase.h>
62#include <iprt/win/setupapi.h>
63#include <iprt/win/shlobj.h>
64#include <cfgmgr32.h>
65
66#define VBOX_APP_NAME L"VirtualBox"
67
68static int getDefaultInterfaceIndex()
69{
70 PMIB_IPFORWARDTABLE pIpTable;
71 DWORD dwSize = sizeof(MIB_IPFORWARDTABLE) * 20;
72 DWORD dwRC = NO_ERROR;
73 int iIndex = -1;
74
75 pIpTable = (MIB_IPFORWARDTABLE *)RTMemAlloc(dwSize);
76 if (GetIpForwardTable(pIpTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
77 {
78 RTMemFree(pIpTable);
79 pIpTable = (MIB_IPFORWARDTABLE *)RTMemAlloc(dwSize);
80 if (!pIpTable)
81 return -1;
82 }
83 dwRC = GetIpForwardTable(pIpTable, &dwSize, 0);
84 if (dwRC == NO_ERROR)
85 {
86 for (unsigned int i = 0; i < pIpTable->dwNumEntries; i++)
87 if (pIpTable->table[i].dwForwardDest == 0)
88 {
89 iIndex = pIpTable->table[i].dwForwardIfIndex;
90 break;
91 }
92 }
93 RTMemFree(pIpTable);
94 return iIndex;
95}
96
97static int collectNetIfInfo(Bstr &strName, Guid &guid, PNETIFINFO pInfo, int iDefault)
98{
99 RT_NOREF(strName);
100
101 /*
102 * Most of the hosts probably have less than 10 adapters,
103 * so we'll mostly succeed from the first attempt.
104 */
105 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
106 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
107 if (!pAddresses)
108 return VERR_NO_MEMORY;
109 DWORD dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
110 if (dwRc == ERROR_BUFFER_OVERFLOW)
111 {
112 /* Impressive! More than 10 adapters! Get more memory and try again. */
113 RTMemFree(pAddresses);
114 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
115 if (!pAddresses)
116 return VERR_NO_MEMORY;
117 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
118 }
119 if (dwRc == NO_ERROR)
120 {
121 PIP_ADAPTER_ADDRESSES pAdapter;
122 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
123 {
124 char *pszUuid = RTStrDup(pAdapter->AdapterName);
125 size_t len = strlen(pszUuid) - 1;
126 if (pszUuid[0] == '{' && pszUuid[len] == '}')
127 {
128 pszUuid[len] = 0;
129 if (!RTUuidCompareStr(&pInfo->Uuid, pszUuid + 1))
130 {
131 bool fIPFound, fIPv6Found;
132 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
133 fIPFound = fIPv6Found = false;
134 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
135 {
136 switch (pAddr->Address.lpSockaddr->sa_family)
137 {
138 case AF_INET:
139 if (!fIPFound)
140 {
141 fIPFound = true;
142 memcpy(&pInfo->IPAddress,
143 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
144 sizeof(pInfo->IPAddress));
145 }
146 break;
147 case AF_INET6:
148 if (!fIPv6Found)
149 {
150 fIPv6Found = true;
151 memcpy(&pInfo->IPv6Address,
152 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
153 sizeof(pInfo->IPv6Address));
154 }
155 break;
156 }
157 }
158 PIP_ADAPTER_PREFIX pPrefix;
159 fIPFound = fIPv6Found = false;
160 for (pPrefix = pAdapter->FirstPrefix; pPrefix; pPrefix = pPrefix->Next)
161 {
162 switch (pPrefix->Address.lpSockaddr->sa_family)
163 {
164 case AF_INET:
165 if (!fIPFound)
166 {
167 if (pPrefix->PrefixLength <= sizeof(pInfo->IPNetMask) * 8)
168 {
169 fIPFound = true;
170 RTNetPrefixToMaskIPv4(pPrefix->PrefixLength, &pInfo->IPNetMask);
171 }
172 else
173 LogFunc(("Unexpected IPv4 prefix length of %d\n",
174 pPrefix->PrefixLength));
175 }
176 break;
177 case AF_INET6:
178 if (!fIPv6Found)
179 {
180 if (pPrefix->PrefixLength <= sizeof(pInfo->IPv6NetMask) * 8)
181 {
182 fIPv6Found = true;
183 RTNetPrefixToMaskIPv6(pPrefix->PrefixLength, &pInfo->IPv6NetMask);
184 }
185 else
186 LogFunc(("Unexpected IPv6 prefix length of %d\n",
187 pPrefix->PrefixLength));
188 }
189 break;
190 }
191 }
192 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
193 LogFunc(("Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
194 else
195 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
196 pInfo->enmMediumType = NETIF_T_ETHERNET;
197 pInfo->enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
198 pInfo->fIsDefault = (pAdapter->IfIndex == (DWORD)iDefault);
199 RTStrFree(pszUuid);
200 break;
201 }
202 }
203 RTStrFree(pszUuid);
204 }
205
206 ADAPTER_SETTINGS Settings;
207 HRESULT hr = VBoxNetCfgWinGetAdapterSettings((const GUID *)guid.raw(), &Settings);
208 if (hr == S_OK)
209 {
210 if (Settings.ip)
211 {
212 pInfo->IPAddress.u = Settings.ip;
213 pInfo->IPNetMask.u = Settings.mask;
214 }
215 pInfo->fDhcpEnabled = Settings.bDhcp;
216 }
217 else
218 {
219 pInfo->fDhcpEnabled = false;
220 }
221 }
222 RTMemFree(pAddresses);
223
224 return VINF_SUCCESS;
225}
226
227/* svc helper func */
228
229struct StaticIpConfig
230{
231 ULONG IPAddress;
232 ULONG IPNetMask;
233};
234
235struct StaticIpV6Config
236{
237 BSTR IPV6Address;
238 ULONG IPV6NetMaskLength;
239};
240
241class NetworkInterfaceHelperClientData : public ThreadVoidData
242{
243public:
244 NetworkInterfaceHelperClientData(){};
245 ~NetworkInterfaceHelperClientData(){};
246
247 SVCHlpMsg::Code msgCode;
248 /* for SVCHlpMsg::CreateHostOnlyNetworkInterface */
249 Bstr name;
250 ComObjPtr<HostNetworkInterface> iface;
251 ComObjPtr<VirtualBox> vBox;
252 /* for SVCHlpMsg::RemoveHostOnlyNetworkInterface */
253 Guid guid;
254
255 union
256 {
257 StaticIpConfig StaticIP;
258 StaticIpV6Config StaticIPV6;
259 } u;
260
261};
262
263static HRESULT netIfNetworkInterfaceHelperClient(SVCHlpClient *aClient,
264 Progress *aProgress,
265 void *aUser, int *aVrc)
266{
267 LogFlowFuncEnter();
268 LogFlowFunc(("aClient={%p}, aProgress={%p}, aUser={%p}\n",
269 aClient, aProgress, aUser));
270
271 AssertReturn( (aClient == NULL && aProgress == NULL && aVrc == NULL)
272 || (aClient != NULL && aProgress != NULL && aVrc != NULL),
273 E_POINTER);
274 AssertReturn(aUser, E_POINTER);
275
276 NetworkInterfaceHelperClientData* d = static_cast<NetworkInterfaceHelperClientData *>(aUser);
277
278 if (aClient == NULL)
279 {
280 /* "cleanup only" mode, just return (it will free aUser) */
281 return S_OK;
282 }
283
284 HRESULT rc = S_OK;
285 int vrc = VINF_SUCCESS;
286
287 switch (d->msgCode)
288 {
289 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
290 {
291 LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
292 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
293
294 /* write message and parameters */
295 vrc = aClient->write(d->msgCode);
296 if (RT_FAILURE(vrc)) break;
297// vrc = aClient->write(Utf8Str(d->name));
298// if (RT_FAILURE(vrc)) break;
299
300 /* wait for a reply */
301 bool endLoop = false;
302 while (!endLoop)
303 {
304 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
305
306 vrc = aClient->read(reply);
307 if (RT_FAILURE(vrc)) break;
308
309 switch (reply)
310 {
311 case SVCHlpMsg::CreateHostOnlyNetworkInterface_OK:
312 {
313 /* read the GUID */
314 Guid guid;
315 Utf8Str name;
316 vrc = aClient->read(name);
317 if (RT_FAILURE(vrc)) break;
318 vrc = aClient->read(guid);
319 if (RT_FAILURE(vrc)) break;
320
321 LogFlowFunc(("Network connection GUID = {%RTuuid}\n", guid.raw()));
322
323 /* initialize the object returned to the caller by
324 * CreateHostOnlyNetworkInterface() */
325 rc = d->iface->init(Bstr(name), Bstr(name), guid, HostNetworkInterfaceType_HostOnly);
326 if (SUCCEEDED(rc))
327 {
328 rc = d->iface->i_setVirtualBox(d->vBox);
329 if (SUCCEEDED(rc))
330 {
331 rc = d->iface->updateConfig();
332 }
333 }
334 endLoop = true;
335 break;
336 }
337 case SVCHlpMsg::Error:
338 {
339 /* read the error message */
340 Utf8Str errMsg;
341 vrc = aClient->read(errMsg);
342 if (RT_FAILURE(vrc)) break;
343
344 rc = E_FAIL;
345 d->iface->setError(E_FAIL, errMsg.c_str());
346 endLoop = true;
347 break;
348 }
349 default:
350 {
351 endLoop = true;
352 rc = E_FAIL;/// @todo ComAssertMsgFailedBreak((
353 //"Invalid message code %d (%08lX)\n",
354 //reply, reply),
355 //rc = E_FAIL);
356 }
357 }
358 }
359
360 break;
361 }
362 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
363 {
364 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
365 LogFlowFunc(("Network connection GUID = {%RTuuid}\n", d->guid.raw()));
366
367 /* write message and parameters */
368 vrc = aClient->write(d->msgCode);
369 if (RT_FAILURE(vrc)) break;
370 vrc = aClient->write(d->guid);
371 if (RT_FAILURE(vrc)) break;
372
373 /* wait for a reply */
374 bool endLoop = false;
375 while (!endLoop)
376 {
377 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
378
379 vrc = aClient->read(reply);
380 if (RT_FAILURE(vrc)) break;
381
382 switch (reply)
383 {
384 case SVCHlpMsg::OK:
385 {
386 /* no parameters */
387 rc = S_OK;
388 endLoop = true;
389 break;
390 }
391 case SVCHlpMsg::Error:
392 {
393 /* read the error message */
394 Utf8Str errMsg;
395 vrc = aClient->read(errMsg);
396 if (RT_FAILURE(vrc)) break;
397
398 rc = E_FAIL;
399 d->iface->setError(E_FAIL, errMsg.c_str());
400 endLoop = true;
401 break;
402 }
403 default:
404 {
405 endLoop = true;
406 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
407 //"Invalid message code %d (%08lX)\n",
408 //reply, reply),
409 //rc = E_FAIL);
410 }
411 }
412 }
413
414 break;
415 }
416 case SVCHlpMsg::EnableDynamicIpConfig: /* see usage in code */
417 {
418 LogFlowFunc(("EnableDynamicIpConfig:\n"));
419 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
420
421 /* write message and parameters */
422 vrc = aClient->write(d->msgCode);
423 if (RT_FAILURE(vrc)) break;
424 vrc = aClient->write(d->guid);
425 if (RT_FAILURE(vrc)) break;
426
427 /* wait for a reply */
428 bool endLoop = false;
429 while (!endLoop)
430 {
431 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
432
433 vrc = aClient->read(reply);
434 if (RT_FAILURE(vrc)) break;
435
436 switch (reply)
437 {
438 case SVCHlpMsg::OK:
439 {
440 /* no parameters */
441 rc = d->iface->updateConfig();
442 endLoop = true;
443 break;
444 }
445 case SVCHlpMsg::Error:
446 {
447 /* read the error message */
448 Utf8Str errMsg;
449 vrc = aClient->read(errMsg);
450 if (RT_FAILURE(vrc)) break;
451
452 rc = E_FAIL;
453 d->iface->setError(E_FAIL, errMsg.c_str());
454 endLoop = true;
455 break;
456 }
457 default:
458 {
459 endLoop = true;
460 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
461 //"Invalid message code %d (%08lX)\n",
462 //reply, reply),
463 //rc = E_FAIL);
464 }
465 }
466 }
467
468 break;
469 }
470 case SVCHlpMsg::EnableStaticIpConfig: /* see usage in code */
471 {
472 LogFlowFunc(("EnableStaticIpConfig:\n"));
473 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
474
475 /* write message and parameters */
476 vrc = aClient->write(d->msgCode);
477 if (RT_FAILURE(vrc)) break;
478 vrc = aClient->write(d->guid);
479 if (RT_FAILURE(vrc)) break;
480 vrc = aClient->write(d->u.StaticIP.IPAddress);
481 if (RT_FAILURE(vrc)) break;
482 vrc = aClient->write(d->u.StaticIP.IPNetMask);
483 if (RT_FAILURE(vrc)) break;
484
485 /* wait for a reply */
486 bool endLoop = false;
487 while (!endLoop)
488 {
489 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
490
491 vrc = aClient->read(reply);
492 if (RT_FAILURE(vrc)) break;
493
494 switch (reply)
495 {
496 case SVCHlpMsg::OK:
497 {
498 /* no parameters */
499 rc = d->iface->updateConfig();
500 endLoop = true;
501 break;
502 }
503 case SVCHlpMsg::Error:
504 {
505 /* read the error message */
506 Utf8Str errMsg;
507 vrc = aClient->read(errMsg);
508 if (RT_FAILURE(vrc)) break;
509
510 rc = E_FAIL;
511 d->iface->setError(E_FAIL, errMsg.c_str());
512 endLoop = true;
513 break;
514 }
515 default:
516 {
517 endLoop = true;
518 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
519 //"Invalid message code %d (%08lX)\n",
520 //reply, reply),
521 //rc = E_FAIL);
522 }
523 }
524 }
525
526 break;
527 }
528 case SVCHlpMsg::EnableStaticIpConfigV6: /* see usage in code */
529 {
530 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
531 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
532
533 /* write message and parameters */
534 vrc = aClient->write(d->msgCode);
535 if (RT_FAILURE(vrc)) break;
536 vrc = aClient->write(d->guid);
537 if (RT_FAILURE(vrc)) break;
538 vrc = aClient->write(Utf8Str(d->u.StaticIPV6.IPV6Address));
539 if (RT_FAILURE(vrc)) break;
540 vrc = aClient->write(d->u.StaticIPV6.IPV6NetMaskLength);
541 if (RT_FAILURE(vrc)) break;
542
543 /* wait for a reply */
544 bool endLoop = false;
545 while (!endLoop)
546 {
547 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
548
549 vrc = aClient->read(reply);
550 if (RT_FAILURE(vrc)) break;
551
552 switch (reply)
553 {
554 case SVCHlpMsg::OK:
555 {
556 /* no parameters */
557 rc = d->iface->updateConfig();
558 endLoop = true;
559 break;
560 }
561 case SVCHlpMsg::Error:
562 {
563 /* read the error message */
564 Utf8Str errMsg;
565 vrc = aClient->read(errMsg);
566 if (RT_FAILURE(vrc)) break;
567
568 rc = E_FAIL;
569 d->iface->setError(E_FAIL, errMsg.c_str());
570 endLoop = true;
571 break;
572 }
573 default:
574 {
575 endLoop = true;
576 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
577 //"Invalid message code %d (%08lX)\n",
578 //reply, reply),
579 //rc = E_FAIL);
580 }
581 }
582 }
583
584 break;
585 }
586 case SVCHlpMsg::DhcpRediscover: /* see usage in code */
587 {
588 LogFlowFunc(("DhcpRediscover:\n"));
589 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
590
591 /* write message and parameters */
592 vrc = aClient->write(d->msgCode);
593 if (RT_FAILURE(vrc)) break;
594 vrc = aClient->write(d->guid);
595 if (RT_FAILURE(vrc)) break;
596
597 /* wait for a reply */
598 bool endLoop = false;
599 while (!endLoop)
600 {
601 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
602
603 vrc = aClient->read(reply);
604 if (RT_FAILURE(vrc)) break;
605
606 switch (reply)
607 {
608 case SVCHlpMsg::OK:
609 {
610 /* no parameters */
611 rc = d->iface->updateConfig();
612 endLoop = true;
613 break;
614 }
615 case SVCHlpMsg::Error:
616 {
617 /* read the error message */
618 Utf8Str errMsg;
619 vrc = aClient->read(errMsg);
620 if (RT_FAILURE(vrc)) break;
621
622 rc = E_FAIL;
623 d->iface->setError(E_FAIL, errMsg.c_str());
624 endLoop = true;
625 break;
626 }
627 default:
628 {
629 endLoop = true;
630 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
631 //"Invalid message code %d (%08lX)\n",
632 //reply, reply),
633 //rc = E_FAIL);
634 }
635 }
636 }
637
638 break;
639 }
640 default:
641 rc = E_FAIL; /// @todo ComAssertMsgFailedBreak((
642// "Invalid message code %d (%08lX)\n",
643// d->msgCode, d->msgCode),
644// rc = E_FAIL);
645 }
646
647 if (aVrc)
648 *aVrc = vrc;
649
650 LogFlowFunc(("rc=0x%08X, vrc=%Rrc\n", rc, vrc));
651 LogFlowFuncLeave();
652 return rc;
653}
654
655
656int netIfNetworkInterfaceHelperServer(SVCHlpClient *aClient,
657 SVCHlpMsg::Code aMsgCode)
658{
659 LogFlowFuncEnter();
660 LogFlowFunc(("aClient={%p}, aMsgCode=%d\n", aClient, aMsgCode));
661
662 AssertReturn(aClient, VERR_INVALID_POINTER);
663
664 int vrc = VINF_SUCCESS;
665 HRESULT hrc;
666
667 switch (aMsgCode)
668 {
669 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
670 {
671 LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
672
673// Utf8Str name;
674// vrc = aClient->read(name);
675// if (RT_FAILURE(vrc)) break;
676
677 Guid guid;
678 Utf8Str errMsg;
679 Bstr name;
680 Bstr bstrErr;
681
682#ifdef VBOXNETCFG_DELAYEDRENAME
683 Bstr devId;
684 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), devId.asOutParam(),
685 bstrErr.asOutParam());
686#else /* !VBOXNETCFG_DELAYEDRENAME */
687 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), name.asOutParam(),
688 bstrErr.asOutParam());
689#endif /* !VBOXNETCFG_DELAYEDRENAME */
690
691 if (hrc == S_OK)
692 {
693 ULONG ip, mask;
694 hrc = VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(&ip, &mask);
695 if (hrc == S_OK)
696 {
697 /* ip returned by VBoxNetCfgWinGenHostOnlyNetworkNetworkIp is a network ip,
698 * i.e. 192.168.xxx.0, assign 192.168.xxx.1 for the hostonly adapter */
699 ip = ip | (1 << 24);
700 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID*)guid.raw(), ip, mask);
701 if (hrc != S_OK)
702 LogRel(("VBoxNetCfgWinEnableStaticIpConfig failed (0x%x)\n", hrc));
703 }
704 else
705 LogRel(("VBoxNetCfgWinGenHostOnlyNetworkNetworkIp failed (0x%x)\n", hrc));
706#ifdef VBOXNETCFG_DELAYEDRENAME
707 hrc = VBoxNetCfgWinRenameHostOnlyConnection((const GUID*)guid.raw(), devId.raw(), name.asOutParam());
708 if (hrc != S_OK)
709 LogRel(("VBoxNetCfgWinRenameHostOnlyConnection failed, error = 0x%x", hrc));
710#endif /* VBOXNETCFG_DELAYEDRENAME */
711 /* write success followed by GUID */
712 vrc = aClient->write(SVCHlpMsg::CreateHostOnlyNetworkInterface_OK);
713 if (RT_FAILURE(vrc)) break;
714 vrc = aClient->write(Utf8Str(name));
715 if (RT_FAILURE(vrc)) break;
716 vrc = aClient->write(guid);
717 if (RT_FAILURE(vrc)) break;
718 }
719 else
720 {
721 vrc = VERR_GENERAL_FAILURE;
722 errMsg = Utf8Str(bstrErr);
723 /* write failure followed by error message */
724 if (errMsg.isEmpty())
725 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
726 vrc = aClient->write(SVCHlpMsg::Error);
727 if (RT_FAILURE(vrc)) break;
728 vrc = aClient->write(errMsg);
729 if (RT_FAILURE(vrc)) break;
730 }
731
732 break;
733 }
734 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
735 {
736 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
737
738 Guid guid;
739 Bstr bstrErr;
740
741 vrc = aClient->read(guid);
742 if (RT_FAILURE(vrc)) break;
743
744 Utf8Str errMsg;
745 hrc = VBoxNetCfgWinRemoveHostOnlyNetworkInterface((const GUID*)guid.raw(), bstrErr.asOutParam());
746
747 if (hrc == S_OK)
748 {
749 /* write parameter-less success */
750 vrc = aClient->write(SVCHlpMsg::OK);
751 if (RT_FAILURE(vrc)) break;
752 }
753 else
754 {
755 vrc = VERR_GENERAL_FAILURE;
756 errMsg = Utf8Str(bstrErr);
757 /* write failure followed by error message */
758 if (errMsg.isEmpty())
759 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
760 vrc = aClient->write(SVCHlpMsg::Error);
761 if (RT_FAILURE(vrc)) break;
762 vrc = aClient->write(errMsg);
763 if (RT_FAILURE(vrc)) break;
764 }
765
766 break;
767 }
768 case SVCHlpMsg::EnableStaticIpConfigV6:
769 {
770 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
771
772 Guid guid;
773 Utf8Str ipV6;
774 ULONG maskLengthV6;
775 vrc = aClient->read(guid);
776 if (RT_FAILURE(vrc)) break;
777 vrc = aClient->read(ipV6);
778 if (RT_FAILURE(vrc)) break;
779 vrc = aClient->read(maskLengthV6);
780 if (RT_FAILURE(vrc)) break;
781
782 Utf8Str errMsg;
783 vrc = VERR_NOT_IMPLEMENTED;
784
785 if (RT_SUCCESS(vrc))
786 {
787 /* write success followed by GUID */
788 vrc = aClient->write(SVCHlpMsg::OK);
789 if (RT_FAILURE(vrc)) break;
790 }
791 else
792 {
793 /* write failure followed by error message */
794 if (errMsg.isEmpty())
795 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
796 vrc = aClient->write(SVCHlpMsg::Error);
797 if (RT_FAILURE(vrc)) break;
798 vrc = aClient->write(errMsg);
799 if (RT_FAILURE(vrc)) break;
800 }
801
802 break;
803 }
804 case SVCHlpMsg::EnableStaticIpConfig:
805 {
806 LogFlowFunc(("EnableStaticIpConfig:\n"));
807
808 Guid guid;
809 ULONG ip, mask;
810 vrc = aClient->read(guid);
811 if (RT_FAILURE(vrc)) break;
812 vrc = aClient->read(ip);
813 if (RT_FAILURE(vrc)) break;
814 vrc = aClient->read(mask);
815 if (RT_FAILURE(vrc)) break;
816
817 Utf8Str errMsg;
818 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID *)guid.raw(), ip, mask);
819
820 if (hrc == S_OK)
821 {
822 /* write success followed by GUID */
823 vrc = aClient->write(SVCHlpMsg::OK);
824 if (RT_FAILURE(vrc)) break;
825 }
826 else
827 {
828 vrc = VERR_GENERAL_FAILURE;
829 /* write failure followed by error message */
830 if (errMsg.isEmpty())
831 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
832 vrc = aClient->write(SVCHlpMsg::Error);
833 if (RT_FAILURE(vrc)) break;
834 vrc = aClient->write(errMsg);
835 if (RT_FAILURE(vrc)) break;
836 }
837
838 break;
839 }
840 case SVCHlpMsg::EnableDynamicIpConfig:
841 {
842 LogFlowFunc(("EnableDynamicIpConfig:\n"));
843
844 Guid guid;
845 vrc = aClient->read(guid);
846 if (RT_FAILURE(vrc)) break;
847
848 Utf8Str errMsg;
849 hrc = VBoxNetCfgWinEnableDynamicIpConfig((const GUID *)guid.raw());
850
851 if (hrc == S_OK)
852 {
853 /* write success followed by GUID */
854 vrc = aClient->write(SVCHlpMsg::OK);
855 if (RT_FAILURE(vrc)) break;
856 }
857 else
858 {
859 vrc = VERR_GENERAL_FAILURE;
860 /* write failure followed by error message */
861 if (errMsg.isEmpty())
862 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
863 vrc = aClient->write(SVCHlpMsg::Error);
864 if (RT_FAILURE(vrc)) break;
865 vrc = aClient->write(errMsg);
866 if (RT_FAILURE(vrc)) break;
867 }
868
869 break;
870 }
871 case SVCHlpMsg::DhcpRediscover:
872 {
873 LogFlowFunc(("DhcpRediscover:\n"));
874
875 Guid guid;
876 vrc = aClient->read(guid);
877 if (RT_FAILURE(vrc)) break;
878
879 Utf8Str errMsg;
880 hrc = VBoxNetCfgWinDhcpRediscover((const GUID *)guid.raw());
881
882 if (hrc == S_OK)
883 {
884 /* write success followed by GUID */
885 vrc = aClient->write(SVCHlpMsg::OK);
886 if (RT_FAILURE(vrc)) break;
887 }
888 else
889 {
890 vrc = VERR_GENERAL_FAILURE;
891 /* write failure followed by error message */
892 if (errMsg.isEmpty())
893 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
894 vrc = aClient->write(SVCHlpMsg::Error);
895 if (RT_FAILURE(vrc)) break;
896 vrc = aClient->write(errMsg);
897 if (RT_FAILURE(vrc)) break;
898 }
899
900 break;
901 }
902 default:
903 AssertMsgFailedBreakStmt(
904 ("Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode),
905 VERR_GENERAL_FAILURE);
906 }
907
908 LogFlowFunc(("vrc=%Rrc\n", vrc));
909 LogFlowFuncLeave();
910 return vrc;
911}
912
913/** @todo REMOVE. OBSOLETE NOW. */
914/**
915 * Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
916 * later OSes) and it has the UAC (User Account Control) feature enabled.
917 */
918static BOOL IsUACEnabled()
919{
920 LONG rc = 0;
921
922 OSVERSIONINFOEX info;
923 ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
924 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
925 rc = GetVersionEx((OSVERSIONINFO *) &info);
926 AssertReturn(rc != 0, FALSE);
927
928 LogFlowFunc(("dwMajorVersion=%d, dwMinorVersion=%d\n",
929 info.dwMajorVersion, info.dwMinorVersion));
930
931 /* we are interested only in Vista (and newer versions...). In all
932 * earlier versions UAC is not present. */
933 if (info.dwMajorVersion < 6)
934 return FALSE;
935
936 /* the default EnableLUA value is 1 (Enabled) */
937 DWORD dwEnableLUA = 1;
938
939 HKEY hKey;
940 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
941 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
942 0, KEY_QUERY_VALUE, &hKey);
943
944 Assert(rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND);
945 if (rc == ERROR_SUCCESS)
946 {
947
948 DWORD cbEnableLUA = sizeof(dwEnableLUA);
949 rc = RegQueryValueExA(hKey, "EnableLUA", NULL, NULL,
950 (LPBYTE) &dwEnableLUA, &cbEnableLUA);
951
952 RegCloseKey(hKey);
953
954 Assert(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND);
955 }
956
957 LogFlowFunc(("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA));
958
959 return dwEnableLUA == 1;
960}
961
962/* end */
963
964static int vboxNetWinAddComponent(std::list<ComObjPtr<HostNetworkInterface> > * pPist,
965 INetCfgComponent * pncc, HostNetworkInterfaceType enmType,
966 int iDefaultInterface)
967{
968 LPWSTR lpszName;
969 GUID IfGuid;
970 HRESULT hr;
971 int rc = VERR_GENERAL_FAILURE;
972
973 hr = pncc->GetDisplayName(&lpszName);
974 Assert(hr == S_OK);
975 if (hr == S_OK)
976 {
977 Bstr name(lpszName);
978
979 hr = pncc->GetInstanceGuid(&IfGuid);
980 Assert(hr == S_OK);
981 if (hr == S_OK)
982 {
983 Guid guidIfCopy(IfGuid);
984 NETIFINFO Info;
985 RT_ZERO(Info);
986 Info.Uuid = *guidIfCopy.raw();
987 rc = collectNetIfInfo(name, guidIfCopy, &Info, iDefaultInterface);
988 if (RT_FAILURE(rc))
989 LogRelFunc(("collectNetIfInfo() -> %Rrc\n", rc));
990 LogFunc(("adding %ls\n", lpszName));
991 /* create a new object and add it to the list */
992 ComObjPtr<HostNetworkInterface> iface;
993 iface.createObject();
994 /* remove the curly bracket at the end */
995 rc = iface->init(name, enmType, &Info);
996 if (SUCCEEDED(rc))
997 {
998 if (Info.fIsDefault)
999 pPist->push_front(iface);
1000 else
1001 pPist->push_back(iface);
1002 }
1003 else
1004 {
1005 LogRelFunc(("HostNetworkInterface::init() -> %Rrc\n", rc));
1006 AssertComRC(rc);
1007 }
1008 }
1009 else
1010 LogRelFunc(("failed to get device instance GUID (0x%x)\n", hr));
1011 CoTaskMemFree(lpszName);
1012 }
1013 else
1014 LogRelFunc(("failed to get device display name (0x%x)\n", hr));
1015
1016 return rc;
1017}
1018
1019#endif /* VBOX_WITH_NETFLT */
1020
1021
1022static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkInterface> > &list)
1023{
1024#ifndef VBOX_WITH_NETFLT
1025 /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
1026 return VERR_NOT_IMPLEMENTED;
1027#else /* # if defined VBOX_WITH_NETFLT */
1028 INetCfgComponent *pMpNcc;
1029 HRESULT hr;
1030 IEnumNetCfgComponent *pEnumComponent;
1031
1032 hr = pNc->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent);
1033 if (hr == S_OK)
1034 {
1035 while ((hr = pEnumComponent->Next(1, &pMpNcc, NULL)) == S_OK)
1036 {
1037 LPWSTR pwszName;
1038 ULONG uComponentStatus;
1039 hr = pMpNcc->GetDisplayName(&pwszName);
1040 if (hr == S_OK)
1041 LogFunc(("%ls\n", pwszName));
1042 else
1043 LogRelFunc(("failed to get device display name (0x%x)\n", hr));
1044 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
1045 if (hr == S_OK)
1046 {
1047 if (uComponentStatus == 0)
1048 {
1049 LPWSTR pId;
1050 hr = pMpNcc->GetId(&pId);
1051 Assert(hr == S_OK);
1052 if (hr == S_OK)
1053 {
1054 LogFunc(("id = %ls\n", pId));
1055 if (!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1056 {
1057 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly, -1);
1058 }
1059 CoTaskMemFree(pId);
1060 }
1061 else
1062 LogRelFunc(("failed to get device id (0x%x)\n", hr));
1063 }
1064 }
1065 else
1066 LogRelFunc(("failed to get device status (0x%x)\n", hr));
1067 pMpNcc->Release();
1068 }
1069 Assert(hr == S_OK || hr == S_FALSE);
1070
1071 pEnumComponent->Release();
1072 }
1073 else
1074 LogRelFunc(("EnumComponents error (0x%x)\n", hr));
1075#endif /* # if defined VBOX_WITH_NETFLT */
1076 return VINF_SUCCESS;
1077}
1078
1079int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *pInfo)
1080{
1081#ifndef VBOX_WITH_NETFLT
1082 return VERR_NOT_IMPLEMENTED;
1083#else
1084 Bstr name;
1085 HRESULT hr = pIf->COMGETTER(Name)(name.asOutParam());
1086 if (hr == S_OK)
1087 {
1088 Bstr IfGuid;
1089 hr = pIf->COMGETTER(Id)(IfGuid.asOutParam());
1090 Assert(hr == S_OK);
1091 if (hr == S_OK)
1092 {
1093 memset(pInfo, 0, sizeof(NETIFINFO));
1094 Guid guid(IfGuid);
1095 pInfo->Uuid = *(guid.raw());
1096
1097 return collectNetIfInfo(name, guid, pInfo, getDefaultInterfaceIndex());
1098 }
1099 }
1100 return VERR_GENERAL_FAILURE;
1101#endif
1102}
1103
1104int NetIfGetConfigByName(PNETIFINFO)
1105{
1106 return VERR_NOT_IMPLEMENTED;
1107}
1108
1109/**
1110 * Obtain the current state of the interface.
1111 *
1112 * @returns VBox status code.
1113 *
1114 * @param pcszIfName Interface name.
1115 * @param penmState Where to store the retrieved state.
1116 */
1117int NetIfGetState(const char *pcszIfName, NETIFSTATUS *penmState)
1118{
1119 RT_NOREF(pcszIfName, penmState);
1120 return VERR_NOT_IMPLEMENTED;
1121}
1122
1123/**
1124 * Retrieve the physical link speed in megabits per second. If the interface is
1125 * not up or otherwise unavailable the zero speed is returned.
1126 *
1127 * @returns VBox status code.
1128 *
1129 * @param pcszIfName Interface name.
1130 * @param puMbits Where to store the link speed.
1131 */
1132int NetIfGetLinkSpeed(const char *pcszIfName, uint32_t *puMbits)
1133{
1134 RT_NOREF(pcszIfName, puMbits);
1135 return VERR_NOT_IMPLEMENTED;
1136}
1137
1138int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox,
1139 IHostNetworkInterface **aHostNetworkInterface,
1140 IProgress **aProgress,
1141 const char *pszName)
1142{
1143 RT_NOREF(pszName);
1144#ifndef VBOX_WITH_NETFLT
1145 return VERR_NOT_IMPLEMENTED;
1146#else
1147 /* create a progress object */
1148 ComObjPtr<Progress> progress;
1149 progress.createObject();
1150
1151 ComPtr<IHost> host;
1152 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1153 if (SUCCEEDED(rc))
1154 {
1155 rc = progress->init(pVirtualBox, host,
1156 Bstr(_T("Creating host only network interface")).raw(),
1157 FALSE /* aCancelable */);
1158 if (SUCCEEDED(rc))
1159 {
1160 if (FAILED(rc)) return rc;
1161 progress.queryInterfaceTo(aProgress);
1162
1163 /* create a new uninitialized host interface object */
1164 ComObjPtr<HostNetworkInterface> iface;
1165 iface.createObject();
1166 iface.queryInterfaceTo(aHostNetworkInterface);
1167
1168 /* create the networkInterfaceHelperClient() argument */
1169 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1170
1171 d->msgCode = SVCHlpMsg::CreateHostOnlyNetworkInterface;
1172// d->name = aName;
1173 d->iface = iface;
1174 d->vBox = pVirtualBox;
1175
1176 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1177 netIfNetworkInterfaceHelperClient,
1178 static_cast<void *>(d),
1179 progress);
1180 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1181
1182 }
1183 }
1184
1185 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1186#endif
1187}
1188
1189int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId,
1190 IProgress **aProgress)
1191{
1192#ifndef VBOX_WITH_NETFLT
1193 return VERR_NOT_IMPLEMENTED;
1194#else
1195 /* create a progress object */
1196 ComObjPtr<Progress> progress;
1197 progress.createObject();
1198 ComPtr<IHost> host;
1199 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1200 if (SUCCEEDED(rc))
1201 {
1202 rc = progress->init(pVirtualBox, host,
1203 Bstr(_T("Removing host network interface")).raw(),
1204 FALSE /* aCancelable */);
1205 if (SUCCEEDED(rc))
1206 {
1207 if (FAILED(rc)) return rc;
1208 progress.queryInterfaceTo(aProgress);
1209
1210 /* create the networkInterfaceHelperClient() argument */
1211 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1212
1213 d->msgCode = SVCHlpMsg::RemoveHostOnlyNetworkInterface;
1214 d->guid = aId;
1215
1216 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1217 netIfNetworkInterfaceHelperClient,
1218 static_cast<void *>(d),
1219 progress);
1220 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1221
1222 }
1223 }
1224
1225 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1226#endif
1227}
1228
1229int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG ip, ULONG mask)
1230{
1231 RT_NOREF(aOldIp);
1232#ifndef VBOX_WITH_NETFLT
1233 return VERR_NOT_IMPLEMENTED;
1234#else
1235 Bstr guid;
1236 HRESULT rc = pIf->COMGETTER(Id)(guid.asOutParam());
1237 if (SUCCEEDED(rc))
1238 {
1239// ComPtr<VirtualBox> vBox;
1240// rc = pIf->getVirtualBox(vBox.asOutParam());
1241// if (SUCCEEDED(rc))
1242 {
1243 /* create a progress object */
1244 ComObjPtr<Progress> progress;
1245 progress.createObject();
1246// ComPtr<IHost> host;
1247// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1248// if (SUCCEEDED(rc))
1249 {
1250 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1251 Bstr("Enabling Dynamic Ip Configuration").raw(),
1252 FALSE /* aCancelable */);
1253 if (SUCCEEDED(rc))
1254 {
1255 if (FAILED(rc)) return rc;
1256// progress.queryInterfaceTo(aProgress);
1257
1258 /* create the networkInterfaceHelperClient() argument */
1259 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1260
1261 d->msgCode = SVCHlpMsg::EnableStaticIpConfig;
1262 d->guid = Guid(guid);
1263 d->iface = pIf;
1264 d->u.StaticIP.IPAddress = ip;
1265 d->u.StaticIP.IPNetMask = mask;
1266
1267 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1268 netIfNetworkInterfaceHelperClient,
1269 static_cast<void *>(d),
1270 progress);
1271 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1272
1273 if (SUCCEEDED(rc))
1274 {
1275 progress->WaitForCompletion(-1);
1276 }
1277 }
1278 }
1279 }
1280 }
1281
1282 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1283#endif
1284}
1285
1286int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address,
1287 IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1288{
1289 RT_NOREF(aOldIPV6Address);
1290#ifndef VBOX_WITH_NETFLT
1291 return VERR_NOT_IMPLEMENTED;
1292#else
1293 Bstr guid;
1294 HRESULT rc = pIf->COMGETTER(Id)(guid.asOutParam());
1295 if (SUCCEEDED(rc))
1296 {
1297// ComPtr<VirtualBox> vBox;
1298// rc = pIf->getVirtualBox(vBox.asOutParam());
1299// if (SUCCEEDED(rc))
1300 {
1301 /* create a progress object */
1302 ComObjPtr<Progress> progress;
1303 progress.createObject();
1304// ComPtr<IHost> host;
1305// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1306// if (SUCCEEDED(rc))
1307 {
1308 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1309 Bstr("Enabling Dynamic Ip Configuration").raw(),
1310 FALSE /* aCancelable */);
1311 if (SUCCEEDED(rc))
1312 {
1313 if (FAILED(rc)) return rc;
1314// progress.queryInterfaceTo(aProgress);
1315
1316 /* create the networkInterfaceHelperClient() argument */
1317 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1318
1319 d->msgCode = SVCHlpMsg::EnableStaticIpConfigV6;
1320 d->guid = guid;
1321 d->iface = pIf;
1322 d->u.StaticIPV6.IPV6Address = aIPV6Address;
1323 d->u.StaticIPV6.IPV6NetMaskLength = aIPV6MaskPrefixLength;
1324
1325 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1326 netIfNetworkInterfaceHelperClient,
1327 static_cast<void *>(d),
1328 progress);
1329 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1330
1331 if (SUCCEEDED(rc))
1332 {
1333 progress->WaitForCompletion(-1);
1334 }
1335 }
1336 }
1337 }
1338 }
1339
1340 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1341#endif
1342}
1343
1344int NetIfEnableDynamicIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf)
1345{
1346#ifndef VBOX_WITH_NETFLT
1347 return VERR_NOT_IMPLEMENTED;
1348#else
1349 HRESULT rc;
1350 Bstr guid;
1351 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1352 if (SUCCEEDED(rc))
1353 {
1354// ComPtr<VirtualBox> vBox;
1355// rc = pIf->getVirtualBox(vBox.asOutParam());
1356// if (SUCCEEDED(rc))
1357 {
1358 /* create a progress object */
1359 ComObjPtr<Progress> progress;
1360 progress.createObject();
1361// ComPtr<IHost> host;
1362// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1363// if (SUCCEEDED(rc))
1364 {
1365 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1366 Bstr("Enabling Dynamic Ip Configuration").raw(),
1367 FALSE /* aCancelable */);
1368 if (SUCCEEDED(rc))
1369 {
1370 if (FAILED(rc)) return rc;
1371// progress.queryInterfaceTo(aProgress);
1372
1373 /* create the networkInterfaceHelperClient() argument */
1374 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1375
1376 d->msgCode = SVCHlpMsg::EnableDynamicIpConfig;
1377 d->guid = guid;
1378 d->iface = pIf;
1379
1380 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1381 netIfNetworkInterfaceHelperClient,
1382 static_cast<void *>(d),
1383 progress);
1384 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1385
1386 if (SUCCEEDED(rc))
1387 {
1388 progress->WaitForCompletion(-1);
1389 }
1390 }
1391 }
1392 }
1393 }
1394
1395 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1396#endif
1397}
1398
1399int NetIfDhcpRediscover(VirtualBox *vBox, HostNetworkInterface * pIf)
1400{
1401#ifndef VBOX_WITH_NETFLT
1402 return VERR_NOT_IMPLEMENTED;
1403#else
1404 HRESULT rc;
1405 Bstr guid;
1406 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1407 if (SUCCEEDED(rc))
1408 {
1409// ComPtr<VirtualBox> vBox;
1410// rc = pIf->getVirtualBox(vBox.asOutParam());
1411// if (SUCCEEDED(rc))
1412 {
1413 /* create a progress object */
1414 ComObjPtr<Progress> progress;
1415 progress.createObject();
1416// ComPtr<IHost> host;
1417// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1418// if (SUCCEEDED(rc))
1419 {
1420 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1421 Bstr("Enabling Dynamic Ip Configuration").raw(),
1422 FALSE /* aCancelable */);
1423 if (SUCCEEDED(rc))
1424 {
1425 if (FAILED(rc)) return rc;
1426// progress.queryInterfaceTo(aProgress);
1427
1428 /* create the networkInterfaceHelperClient() argument */
1429 NetworkInterfaceHelperClientData* d = new NetworkInterfaceHelperClientData();
1430
1431 d->msgCode = SVCHlpMsg::DhcpRediscover;
1432 d->guid = guid;
1433 d->iface = pIf;
1434
1435 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1436 netIfNetworkInterfaceHelperClient,
1437 static_cast<void *>(d),
1438 progress);
1439 /* d is now owned by netIfNetworkInterfaceHelperClient(), no need to delete one here */
1440
1441 if (SUCCEEDED(rc))
1442 {
1443 progress->WaitForCompletion(-1);
1444 }
1445 }
1446 }
1447 }
1448 }
1449
1450 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1451#endif
1452}
1453
1454
1455#define netIfLog LogFunc
1456
1457struct BoundAdapter
1458{
1459 LPWSTR pName;
1460 LPWSTR pHwId;
1461 RTUUID guid;
1462 PIP_ADAPTER_ADDRESSES pAdapter;
1463 BOOL fWireless;
1464};
1465
1466static int netIfGetUnboundHostOnlyAdapters(INetCfg *pNetCfg, std::list<BoundAdapter> &adapters)
1467{
1468 INetCfgComponent *pMiniport;
1469 HRESULT hr;
1470 IEnumNetCfgComponent *pEnumComponent;
1471
1472 if ((hr = pNetCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent)) != S_OK)
1473 LogRelFunc(("failed to enumerate network adapter components (0x%x)\n", hr));
1474 else
1475 {
1476 while ((hr = pEnumComponent->Next(1, &pMiniport, NULL)) == S_OK)
1477 {
1478 GUID guid;
1479 ULONG uComponentStatus;
1480 struct BoundAdapter adapter;
1481 memset(&adapter, 0, sizeof(adapter));
1482 if ((hr = pMiniport->GetDisplayName(&adapter.pName)) != S_OK)
1483 LogRelFunc(("failed to get device display name (0x%x)\n", hr));
1484 else if ((hr = pMiniport->GetDeviceStatus(&uComponentStatus)) != S_OK)
1485 netIfLog(("failed to get device status (0x%x)\n", hr));
1486 else if (uComponentStatus != 0)
1487 netIfLog(("wrong device status (0x%x)\n", uComponentStatus));
1488 else if ((hr = pMiniport->GetId(&adapter.pHwId)) != S_OK)
1489 LogRelFunc(("failed to get device id (0x%x)\n", hr));
1490 else if (_wcsnicmp(adapter.pHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1491 netIfLog(("not host-only id = %ls, ignored\n", adapter.pHwId));
1492 else if ((hr = pMiniport->GetInstanceGuid(&guid)) != S_OK)
1493 LogRelFunc(("failed to get instance id (0x%x)\n", hr));
1494 else
1495 {
1496 adapter.guid = *(Guid(guid).raw());
1497 netIfLog(("guid=%RTuuid, name=%ls id = %ls\n", &adapter.guid, adapter.pName, adapter.pHwId));
1498 adapters.push_back(adapter);
1499 adapter.pName = adapter.pHwId = NULL; /* do not free, will be done later */
1500 }
1501 if (adapter.pHwId)
1502 CoTaskMemFree(adapter.pHwId);
1503 if (adapter.pName)
1504 CoTaskMemFree(adapter.pName);
1505 pMiniport->Release();
1506 }
1507 Assert(hr == S_OK || hr == S_FALSE);
1508
1509 pEnumComponent->Release();
1510 }
1511 netIfLog(("return\n"));
1512 return VINF_SUCCESS;
1513}
1514
1515#define DEVNAME_PREFIX L"\\\\.\\"
1516
1517static BOOL netIfIsWireless(INetCfgComponent *pAdapter)
1518{
1519 bool fWireless = false;
1520
1521 /* Construct a device name. */
1522 LPWSTR pwszBindName = NULL;
1523 HRESULT hrc = pAdapter->GetBindName(&pwszBindName);
1524 if (SUCCEEDED(hrc) && pwszBindName)
1525 {
1526 WCHAR wszFileName[MAX_PATH];
1527 int vrc = RTUtf16Copy(wszFileName, MAX_PATH, DEVNAME_PREFIX);
1528 if (RT_SUCCESS(vrc))
1529 vrc = RTUtf16Cat(wszFileName, MAX_PATH, pwszBindName);
1530 if (RT_SUCCESS(vrc))
1531 {
1532 /* open the device */
1533 HANDLE hDevice = CreateFileW(wszFileName,
1534 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
1535 NULL,
1536 OPEN_EXISTING,
1537 FILE_ATTRIBUTE_NORMAL,
1538 NULL);
1539 if (hDevice != INVALID_HANDLE_VALUE)
1540 {
1541 /* now issue the OID_GEN_PHYSICAL_MEDIUM query */
1542 DWORD Oid = OID_GEN_PHYSICAL_MEDIUM;
1543 NDIS_PHYSICAL_MEDIUM PhMedium = NdisPhysicalMediumUnspecified;
1544 DWORD cbResultIgn = 0;
1545 if (DeviceIoControl(hDevice,
1546 IOCTL_NDIS_QUERY_GLOBAL_STATS,
1547 &Oid,
1548 sizeof(Oid),
1549 &PhMedium,
1550 sizeof(PhMedium),
1551 &cbResultIgn,
1552 NULL))
1553 {
1554 /* that was simple, now examine PhMedium */
1555 fWireless = PhMedium == NdisPhysicalMediumWirelessWan
1556 || PhMedium == NdisPhysicalMediumWirelessLan
1557 || PhMedium == NdisPhysicalMediumNative802_11
1558 || PhMedium == NdisPhysicalMediumBluetooth;
1559 }
1560 else
1561 {
1562 DWORD rcWin = GetLastError();
1563 LogRel(("netIfIsWireless: DeviceIoControl to '%ls' failed with rcWin=%u (%#x) - ignoring\n",
1564 wszFileName, rcWin, rcWin));
1565 Assert(rcWin == ERROR_INVALID_PARAMETER || rcWin == ERROR_NOT_SUPPORTED || rcWin == ERROR_BAD_COMMAND);
1566 }
1567 CloseHandle(hDevice);
1568 }
1569 else
1570 {
1571 DWORD rcWin = GetLastError();
1572#if 0 /* bird: Triggers on each VBoxSVC startup so, disabled. Whoever want it, can enable using DEBUG_xxxx. */
1573 AssertLogRelMsgFailed(("netIfIsWireless: CreateFile on '%ls' failed with rcWin=%u (%#x) - ignoring\n",
1574 wszFileName, rcWin, rcWin));
1575#else
1576 LogRel(("netIfIsWireless: CreateFile on '%ls' failed with rcWin=%u (%#x) - ignoring\n",
1577 wszFileName, rcWin, rcWin));
1578#endif
1579 }
1580 }
1581 CoTaskMemFree(pwszBindName);
1582 }
1583 else
1584 LogRel(("netIfIsWireless: GetBindName failed hrc=%Rhrc\n", hrc));
1585
1586 return fWireless;
1587}
1588
1589static HRESULT netIfGetBoundAdapters(std::list<BoundAdapter> &boundAdapters)
1590{
1591 INetCfg *pNetCfg = NULL;
1592 INetCfgComponent *pFilter;
1593 LPWSTR lpszApp;
1594 HRESULT hr;
1595
1596 netIfLog(("building the list of interfaces\n"));
1597 /* we are using the INetCfg API for getting the list of miniports */
1598 hr = VBoxNetCfgWinQueryINetCfg(&pNetCfg, FALSE,
1599 VBOX_APP_NAME,
1600 10000,
1601 &lpszApp);
1602 Assert(hr == S_OK);
1603 if (hr != S_OK)
1604 {
1605 LogRelFunc(("failed to query INetCfg (0x%x)\n", hr));
1606 return hr;
1607 }
1608
1609 if ((hr = pNetCfg->FindComponent(L"oracle_VBoxNetLwf", &pFilter)) != S_OK
1610 /* fall back to NDIS5 miniport lookup */
1611 && (hr = pNetCfg->FindComponent(L"sun_VBoxNetFlt", &pFilter)))
1612 LogRelFunc(("could not find either 'oracle_VBoxNetLwf' or 'sun_VBoxNetFlt' components (0x%x)\n", hr));
1613 else
1614 {
1615 INetCfgComponentBindings *pFilterBindings;
1616 if ((pFilter->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pFilterBindings)) != S_OK)
1617 LogRelFunc(("failed to query INetCfgComponentBindings (0x%x)\n", hr));
1618 else
1619 {
1620 IEnumNetCfgBindingPath *pEnumBp;
1621 INetCfgBindingPath *pBp;
1622 if ((pFilterBindings->EnumBindingPaths(EBP_BELOW, &pEnumBp)) != S_OK)
1623 LogRelFunc(("failed to enumerate binding paths (0x%x)\n", hr));
1624 else
1625 {
1626 pEnumBp->Reset();
1627 while ((hr = pEnumBp->Next(1, &pBp, NULL)) == S_OK)
1628 {
1629 IEnumNetCfgBindingInterface *pEnumBi;
1630 INetCfgBindingInterface *pBi;
1631 if (pBp->IsEnabled() != S_OK)
1632 {
1633 /** @todo some id of disabled path could be useful. */
1634 netIfLog(("INetCfgBindingPath is disabled (0x%x)\n", hr));
1635 pBp->Release();
1636 continue;
1637 }
1638 if ((pBp->EnumBindingInterfaces(&pEnumBi)) != S_OK)
1639 LogRelFunc(("failed to enumerate binding interfaces (0x%x)\n", hr));
1640 else
1641 {
1642 hr = pEnumBi->Reset();
1643 while ((hr = pEnumBi->Next(1, &pBi, NULL)) == S_OK)
1644 {
1645 INetCfgComponent *pAdapter;
1646 if ((hr = pBi->GetLowerComponent(&pAdapter)) != S_OK)
1647 LogRelFunc(("failed to get lower component (0x%x)\n", hr));
1648 else
1649 {
1650 LPWSTR pwszName = NULL;
1651 if ((hr = pAdapter->GetDisplayName(&pwszName)) != S_OK)
1652 LogRelFunc(("failed to get display name (0x%x)\n", hr));
1653 else
1654 {
1655 ULONG uStatus;
1656 DWORD dwChars;
1657 if ((hr = pAdapter->GetDeviceStatus(&uStatus)) != S_OK)
1658 netIfLog(("%ls: failed to get device status (0x%x)\n",
1659 pwszName, hr));
1660 else if ((hr = pAdapter->GetCharacteristics(&dwChars)) != S_OK)
1661 netIfLog(("%ls: failed to get device characteristics (0x%x)\n",
1662 pwszName, hr));
1663 else if (uStatus != 0)
1664 netIfLog(("%ls: wrong status 0x%x\n",
1665 pwszName, uStatus));
1666 else if (dwChars & NCF_HIDDEN)
1667 netIfLog(("%ls: wrong characteristics 0x%x\n",
1668 pwszName, dwChars));
1669 else
1670 {
1671 GUID guid;
1672 LPWSTR pwszHwId = NULL;
1673 if ((hr = pAdapter->GetId(&pwszHwId)) != S_OK)
1674 LogRelFunc(("%ls: failed to get hardware id (0x%x)\n",
1675 pwszName, hr));
1676 else if (!_wcsnicmp(pwszHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1677 netIfLog(("host-only adapter %ls, ignored\n", pwszName));
1678 else if ((hr = pAdapter->GetInstanceGuid(&guid)) != S_OK)
1679 LogRelFunc(("%ls: failed to get instance GUID (0x%x)\n",
1680 pwszName, hr));
1681 else
1682 {
1683 struct BoundAdapter adapter;
1684 adapter.pName = pwszName;
1685 adapter.pHwId = pwszHwId;
1686 adapter.guid = *(Guid(guid).raw());
1687 adapter.pAdapter = NULL;
1688 adapter.fWireless = netIfIsWireless(pAdapter);
1689 netIfLog(("guid=%RTuuid, name=%ls, hwid=%ls, status=%x, chars=%x\n",
1690 &adapter.guid, pwszName, pwszHwId, uStatus, dwChars));
1691 boundAdapters.push_back(adapter);
1692 pwszName = pwszHwId = NULL; /* do not free, will be done later */
1693 }
1694 if (pwszHwId)
1695 CoTaskMemFree(pwszHwId);
1696 }
1697 if (pwszName)
1698 CoTaskMemFree(pwszName);
1699 }
1700
1701 pAdapter->Release();
1702 }
1703 pBi->Release();
1704 }
1705 pEnumBi->Release();
1706 }
1707 pBp->Release();
1708 }
1709 pEnumBp->Release();
1710 }
1711 pFilterBindings->Release();
1712 }
1713 pFilter->Release();
1714 }
1715 /* Host-only adapters are not necessarily bound, add them separately. */
1716 netIfGetUnboundHostOnlyAdapters(pNetCfg, boundAdapters);
1717 VBoxNetCfgWinReleaseINetCfg(pNetCfg, FALSE);
1718
1719 return S_OK;
1720}
1721
1722#if 0
1723static HRESULT netIfGetBoundAdaptersFallback(std::list<BoundAdapter> &boundAdapters)
1724{
1725 return CO_E_NOT_SUPPORTED;
1726}
1727#endif
1728
1729/**
1730 * Walk through the list of adpater addresses and extract the required
1731 * information. XP and older don't not have the OnLinkPrefixLength field.
1732 */
1733static void netIfFillInfoWithAddressesXp(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
1734{
1735 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
1736 bool fIPFound = false;
1737 bool fIPv6Found = false;
1738 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
1739 {
1740 switch (pAddr->Address.lpSockaddr->sa_family)
1741 {
1742 case AF_INET:
1743 if (!fIPFound)
1744 {
1745 fIPFound = true;
1746 memcpy(&pInfo->IPAddress,
1747 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1748 sizeof(pInfo->IPAddress));
1749 }
1750 break;
1751 case AF_INET6:
1752 if (!fIPv6Found)
1753 {
1754 fIPv6Found = true;
1755 memcpy(&pInfo->IPv6Address,
1756 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
1757 sizeof(pInfo->IPv6Address));
1758 }
1759 break;
1760 }
1761 }
1762 PIP_ADAPTER_PREFIX pPrefix;
1763 ULONG uPrefixLenV4 = 0;
1764 ULONG uPrefixLenV6 = 0;
1765 for (pPrefix = pAdapter->FirstPrefix; pPrefix && !(uPrefixLenV4 && uPrefixLenV6); pPrefix = pPrefix->Next)
1766 {
1767 switch (pPrefix->Address.lpSockaddr->sa_family)
1768 {
1769 case AF_INET:
1770 if (!uPrefixLenV4)
1771 {
1772 ULONG ip = ((PSOCKADDR_IN)(pPrefix->Address.lpSockaddr))->sin_addr.s_addr;
1773 netIfLog(("prefix=%RTnaipv4 len=%u\n", ip, pPrefix->PrefixLength));
1774 if ( pPrefix->PrefixLength < sizeof(pInfo->IPNetMask) * 8
1775 && pPrefix->PrefixLength > 0
1776 && (ip & 0xF0) < 224)
1777 {
1778 uPrefixLenV4 = pPrefix->PrefixLength;
1779 RTNetPrefixToMaskIPv4(pPrefix->PrefixLength, &pInfo->IPNetMask);
1780 }
1781 else
1782 netIfLog(("Unexpected IPv4 prefix length of %d\n",
1783 pPrefix->PrefixLength));
1784 }
1785 break;
1786 case AF_INET6:
1787 if (!uPrefixLenV6)
1788 {
1789 PBYTE ipv6 = ((PSOCKADDR_IN6)(pPrefix->Address.lpSockaddr))->sin6_addr.s6_addr;
1790 netIfLog(("prefix=%RTnaipv6 len=%u\n", ipv6, pPrefix->PrefixLength));
1791 if ( pPrefix->PrefixLength < sizeof(pInfo->IPv6NetMask) * 8
1792 && pPrefix->PrefixLength > 0
1793 && ipv6[0] != 0xFF)
1794 {
1795 uPrefixLenV6 = pPrefix->PrefixLength;
1796 RTNetPrefixToMaskIPv6(pPrefix->PrefixLength, &pInfo->IPv6NetMask);
1797 }
1798 else
1799 netIfLog(("Unexpected IPv6 prefix length of %d\n", pPrefix->PrefixLength));
1800 }
1801 break;
1802 }
1803 }
1804 netIfLog(("%RTnaipv4/%u\n", pInfo->IPAddress, uPrefixLenV4));
1805 netIfLog(("%RTnaipv6/%u\n", &pInfo->IPv6Address, uPrefixLenV6));
1806}
1807
1808/**
1809 * Walk through the list of adpater addresses and extract the required
1810 * information. XP and older don't not have the OnLinkPrefixLength field.
1811 */
1812static void netIfFillInfoWithAddressesVista(PNETIFINFO pInfo, PIP_ADAPTER_ADDRESSES pAdapter)
1813{
1814 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
1815
1816 if (sizeof(pInfo->MACAddress) != pAdapter->PhysicalAddressLength)
1817 netIfLog(("Unexpected physical address length: %u\n", pAdapter->PhysicalAddressLength));
1818 else
1819 memcpy(pInfo->MACAddress.au8, pAdapter->PhysicalAddress, sizeof(pInfo->MACAddress));
1820
1821 bool fIPFound = false;
1822 bool fIPv6Found = false;
1823 for (pAddr = pAdapter->FirstUnicastAddress; pAddr; pAddr = pAddr->Next)
1824 {
1825 PIP_ADAPTER_UNICAST_ADDRESS_LH pAddrLh = (PIP_ADAPTER_UNICAST_ADDRESS_LH)pAddr;
1826 switch (pAddrLh->Address.lpSockaddr->sa_family)
1827 {
1828 case AF_INET:
1829 if (!fIPFound)
1830 {
1831 fIPFound = true;
1832 memcpy(&pInfo->IPAddress,
1833 &((struct sockaddr_in *)pAddrLh->Address.lpSockaddr)->sin_addr.s_addr,
1834 sizeof(pInfo->IPAddress));
1835 if (pAddrLh->OnLinkPrefixLength > 32)
1836 netIfLog(("Invalid IPv4 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
1837 else
1838 RTNetPrefixToMaskIPv4(pAddrLh->OnLinkPrefixLength, &pInfo->IPNetMask);
1839 }
1840 break;
1841 case AF_INET6:
1842 if (!fIPv6Found)
1843 {
1844 fIPv6Found = true;
1845 memcpy(&pInfo->IPv6Address,
1846 ((struct sockaddr_in6 *)pAddrLh->Address.lpSockaddr)->sin6_addr.s6_addr,
1847 sizeof(pInfo->IPv6Address));
1848 if (pAddrLh->OnLinkPrefixLength > 128)
1849 netIfLog(("Invalid IPv6 prefix length of %d\n", pAddrLh->OnLinkPrefixLength));
1850 else
1851 RTNetPrefixToMaskIPv6(pAddrLh->OnLinkPrefixLength, &pInfo->IPv6NetMask);
1852 }
1853 break;
1854 }
1855 }
1856
1857 if (fIPFound)
1858 {
1859 int iPrefixIPv4 = -1;
1860 RTNetMaskToPrefixIPv4(&pInfo->IPNetMask, &iPrefixIPv4);
1861 netIfLog(("%RTnaipv4/%u\n", pInfo->IPAddress, iPrefixIPv4));
1862 }
1863 if (fIPv6Found)
1864 {
1865 int iPrefixIPv6 = -1;
1866 RTNetMaskToPrefixIPv6(&pInfo->IPv6NetMask, &iPrefixIPv6);
1867 netIfLog(("%RTnaipv6/%u\n", &pInfo->IPv6Address, iPrefixIPv6));
1868 }
1869}
1870
1871#if (NTDDI_VERSION >= NTDDI_VISTA)
1872#define NETIF_GAA_FLAGS GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
1873#else /* (NTDDI_VERSION < NTDDI_VISTA) */
1874#define NETIF_GAA_FLAGS GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
1875#endif /* (NTDDI_VERSION < NTDDI_VISTA) */
1876
1877int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
1878{
1879 HRESULT hr = S_OK;
1880 int iDefault = getDefaultInterfaceIndex();
1881 /* MSDN recommends to pre-allocate a 15KB buffer. */
1882 ULONG uBufLen = 15 * 1024;
1883 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1884 if (!pAddresses)
1885 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1886 DWORD dwRc = GetAdaptersAddresses(AF_UNSPEC, NETIF_GAA_FLAGS, NULL, pAddresses, &uBufLen);
1887 for (int tries = 0; tries < 3 && dwRc == ERROR_BUFFER_OVERFLOW; ++tries)
1888 {
1889 /* Get more memory and try again. */
1890 RTMemFree(pAddresses);
1891 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1892 if (!pAddresses)
1893 return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
1894 dwRc = GetAdaptersAddresses(AF_UNSPEC, NETIF_GAA_FLAGS, NULL, pAddresses, &uBufLen);
1895 }
1896 if (dwRc != NO_ERROR)
1897 {
1898 LogRelFunc(("GetAdaptersAddresses failed (0x%x)\n", dwRc));
1899 hr = HRESULT_FROM_WIN32(dwRc);
1900 }
1901 else
1902 {
1903 std::list<BoundAdapter> boundAdapters;
1904 HRESULT hr = netIfGetBoundAdapters(boundAdapters);
1905#if 0
1906 if (hr != S_OK)
1907 hr = netIfGetBoundAdaptersFallback(boundAdapters);
1908#endif
1909 if (hr != S_OK)
1910 LogRelFunc(("netIfGetBoundAdapters failed (0x%x)\n", hr));
1911 else
1912 {
1913 PIP_ADAPTER_ADDRESSES pAdapter;
1914
1915 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1916 {
1917 char *pszUuid = RTStrDup(pAdapter->AdapterName);
1918 if (!pszUuid)
1919 {
1920 LogRelFunc(("out of memory\n"));
1921 break;
1922 }
1923 size_t len = strlen(pszUuid) - 1;
1924 if (pszUuid[0] != '{' || pszUuid[len] != '}')
1925 LogRelFunc(("ignoring invalid GUID %s\n", pAdapter->AdapterName));
1926 else
1927 {
1928 std::list<BoundAdapter>::iterator it;
1929 pszUuid[len] = 0;
1930 for (it = boundAdapters.begin(); it != boundAdapters.end(); ++it)
1931 {
1932 if (!RTUuidCompareStr(&(*it).guid, pszUuid + 1))
1933 {
1934 (*it).pAdapter = pAdapter;
1935 break;
1936 }
1937 }
1938 }
1939 RTStrFree(pszUuid);
1940 }
1941 std::list<BoundAdapter>::iterator it;
1942 for (it = boundAdapters.begin(); it != boundAdapters.end(); ++it)
1943 {
1944 NETIFINFO info;
1945 memset(&info, 0, sizeof(info));
1946 info.Uuid = (*it).guid;
1947 info.enmMediumType = NETIF_T_ETHERNET;
1948 pAdapter = (*it).pAdapter;
1949 if (pAdapter)
1950 {
1951 info.enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
1952 info.fIsDefault = (pAdapter->IfIndex == (DWORD)iDefault);
1953 info.fDhcpEnabled = pAdapter->Flags & IP_ADAPTER_DHCP_ENABLED;
1954 OSVERSIONINFOEX OSInfoEx;
1955 RT_ZERO(OSInfoEx);
1956 OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
1957 if ( GetVersionEx((LPOSVERSIONINFO)&OSInfoEx)
1958 && OSInfoEx.dwMajorVersion < 6)
1959 netIfFillInfoWithAddressesXp(&info, pAdapter);
1960 else
1961 netIfFillInfoWithAddressesVista(&info, pAdapter);
1962 }
1963 else
1964 info.enmStatus = NETIF_S_DOWN;
1965 /* create a new object and add it to the list */
1966 ComObjPtr<HostNetworkInterface> iface;
1967 iface.createObject();
1968 HostNetworkInterfaceType enmType =
1969 _wcsnicmp((*it).pHwId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2) ?
1970 HostNetworkInterfaceType_Bridged : HostNetworkInterfaceType_HostOnly;
1971 netIfLog(("Adding %ls as %s\n", (*it).pName,
1972 enmType == HostNetworkInterfaceType_Bridged ? "bridged" :
1973 enmType == HostNetworkInterfaceType_HostOnly ? "host-only" : "unknown"));
1974 int rc = iface->init((*it).pName, enmType, &info);
1975 if (FAILED(rc))
1976 LogRelFunc(("HostNetworkInterface::init() -> %Rrc\n", rc));
1977 else
1978 {
1979 if (info.fIsDefault)
1980 list.push_front(iface);
1981 else
1982 list.push_back(iface);
1983 }
1984 if ((*it).pHwId)
1985 CoTaskMemFree((*it).pHwId);
1986 if ((*it).pName)
1987 CoTaskMemFree((*it).pName);
1988 }
1989 }
1990 }
1991 RTMemFree(pAddresses);
1992
1993 return hr;
1994}
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