VirtualBox

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

Last change on this file since 57554 was 57554, checked in by vboxsync, 9 years ago

Main/Network: alternative implementation of NetIfList using GetAdaptersAddresses instead of INetCfg (#7993)

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