VirtualBox

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

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

NetAdp/win: Delayed renaming of connections, address generation fix, creation issues fixed (#7973)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.6 KB
Line 
1/* $Id: NetIf-win.cpp 58794 2015-11-20 13:14:13Z 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;
341 d->iface->setError(E_FAIL, errMsg.c_str());
342 endLoop = true;
343 break;
344 }
345 default:
346 {
347 endLoop = true;
348 rc = E_FAIL;//TODO: ComAssertMsgFailedBreak((
349 //"Invalid message code %d (%08lX)\n",
350 //reply, reply),
351 //rc = E_FAIL);
352 }
353 }
354 }
355
356 break;
357 }
358 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
359 {
360 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
361 LogFlowFunc(("Network connection GUID = {%RTuuid}\n", d->guid.raw()));
362
363 /* write message and parameters */
364 vrc = aClient->write(d->msgCode);
365 if (RT_FAILURE(vrc)) break;
366 vrc = aClient->write(d->guid);
367 if (RT_FAILURE(vrc)) break;
368
369 /* wait for a reply */
370 bool endLoop = false;
371 while (!endLoop)
372 {
373 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
374
375 vrc = aClient->read(reply);
376 if (RT_FAILURE(vrc)) break;
377
378 switch (reply)
379 {
380 case SVCHlpMsg::OK:
381 {
382 /* no parameters */
383 rc = S_OK;
384 endLoop = true;
385 break;
386 }
387 case SVCHlpMsg::Error:
388 {
389 /* read the error message */
390 Utf8Str errMsg;
391 vrc = aClient->read(errMsg);
392 if (RT_FAILURE(vrc)) break;
393
394 rc = E_FAIL;
395 d->iface->setError(E_FAIL, errMsg.c_str());
396 endLoop = true;
397 break;
398 }
399 default:
400 {
401 endLoop = true;
402 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak((
403 //"Invalid message code %d (%08lX)\n",
404 //reply, reply),
405 //rc = E_FAIL);
406 }
407 }
408 }
409
410 break;
411 }
412 case SVCHlpMsg::EnableDynamicIpConfig: /* see usage in code */
413 {
414 LogFlowFunc(("EnableDynamicIpConfig:\n"));
415 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
416
417 /* write message and parameters */
418 vrc = aClient->write(d->msgCode);
419 if (RT_FAILURE(vrc)) break;
420 vrc = aClient->write(d->guid);
421 if (RT_FAILURE(vrc)) break;
422
423 /* wait for a reply */
424 bool endLoop = false;
425 while (!endLoop)
426 {
427 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
428
429 vrc = aClient->read(reply);
430 if (RT_FAILURE(vrc)) break;
431
432 switch (reply)
433 {
434 case SVCHlpMsg::OK:
435 {
436 /* no parameters */
437 rc = d->iface->updateConfig();
438 endLoop = true;
439 break;
440 }
441 case SVCHlpMsg::Error:
442 {
443 /* read the error message */
444 Utf8Str errMsg;
445 vrc = aClient->read(errMsg);
446 if (RT_FAILURE(vrc)) break;
447
448 rc = E_FAIL;
449 d->iface->setError(E_FAIL, errMsg.c_str());
450 endLoop = true;
451 break;
452 }
453 default:
454 {
455 endLoop = true;
456 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak((
457 //"Invalid message code %d (%08lX)\n",
458 //reply, reply),
459 //rc = E_FAIL);
460 }
461 }
462 }
463
464 break;
465 }
466 case SVCHlpMsg::EnableStaticIpConfig: /* see usage in code */
467 {
468 LogFlowFunc(("EnableStaticIpConfig:\n"));
469 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
470
471 /* write message and parameters */
472 vrc = aClient->write(d->msgCode);
473 if (RT_FAILURE(vrc)) break;
474 vrc = aClient->write(d->guid);
475 if (RT_FAILURE(vrc)) break;
476 vrc = aClient->write(d->u.StaticIP.IPAddress);
477 if (RT_FAILURE(vrc)) break;
478 vrc = aClient->write(d->u.StaticIP.IPNetMask);
479 if (RT_FAILURE(vrc)) break;
480
481 /* wait for a reply */
482 bool endLoop = false;
483 while (!endLoop)
484 {
485 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
486
487 vrc = aClient->read(reply);
488 if (RT_FAILURE(vrc)) break;
489
490 switch (reply)
491 {
492 case SVCHlpMsg::OK:
493 {
494 /* no parameters */
495 rc = d->iface->updateConfig();
496 endLoop = true;
497 break;
498 }
499 case SVCHlpMsg::Error:
500 {
501 /* read the error message */
502 Utf8Str errMsg;
503 vrc = aClient->read(errMsg);
504 if (RT_FAILURE(vrc)) break;
505
506 rc = E_FAIL;
507 d->iface->setError(E_FAIL, errMsg.c_str());
508 endLoop = true;
509 break;
510 }
511 default:
512 {
513 endLoop = true;
514 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak((
515 //"Invalid message code %d (%08lX)\n",
516 //reply, reply),
517 //rc = E_FAIL);
518 }
519 }
520 }
521
522 break;
523 }
524 case SVCHlpMsg::EnableStaticIpConfigV6: /* see usage in code */
525 {
526 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
527 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
528
529 /* write message and parameters */
530 vrc = aClient->write(d->msgCode);
531 if (RT_FAILURE(vrc)) break;
532 vrc = aClient->write(d->guid);
533 if (RT_FAILURE(vrc)) break;
534 vrc = aClient->write(Utf8Str(d->u.StaticIPV6.IPV6Address));
535 if (RT_FAILURE(vrc)) break;
536 vrc = aClient->write(d->u.StaticIPV6.IPV6NetMaskLength);
537 if (RT_FAILURE(vrc)) break;
538
539 /* wait for a reply */
540 bool endLoop = false;
541 while (!endLoop)
542 {
543 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
544
545 vrc = aClient->read(reply);
546 if (RT_FAILURE(vrc)) break;
547
548 switch (reply)
549 {
550 case SVCHlpMsg::OK:
551 {
552 /* no parameters */
553 rc = d->iface->updateConfig();
554 endLoop = true;
555 break;
556 }
557 case SVCHlpMsg::Error:
558 {
559 /* read the error message */
560 Utf8Str errMsg;
561 vrc = aClient->read(errMsg);
562 if (RT_FAILURE(vrc)) break;
563
564 rc = E_FAIL;
565 d->iface->setError(E_FAIL, errMsg.c_str());
566 endLoop = true;
567 break;
568 }
569 default:
570 {
571 endLoop = true;
572 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak((
573 //"Invalid message code %d (%08lX)\n",
574 //reply, reply),
575 //rc = E_FAIL);
576 }
577 }
578 }
579
580 break;
581 }
582 case SVCHlpMsg::DhcpRediscover: /* see usage in code */
583 {
584 LogFlowFunc(("DhcpRediscover:\n"));
585 LogFlowFunc(("Network connection name = '%ls'\n", d->name.raw()));
586
587 /* write message and parameters */
588 vrc = aClient->write(d->msgCode);
589 if (RT_FAILURE(vrc)) break;
590 vrc = aClient->write(d->guid);
591 if (RT_FAILURE(vrc)) break;
592
593 /* wait for a reply */
594 bool endLoop = false;
595 while (!endLoop)
596 {
597 SVCHlpMsg::Code reply = SVCHlpMsg::Null;
598
599 vrc = aClient->read(reply);
600 if (RT_FAILURE(vrc)) break;
601
602 switch (reply)
603 {
604 case SVCHlpMsg::OK:
605 {
606 /* no parameters */
607 rc = d->iface->updateConfig();
608 endLoop = true;
609 break;
610 }
611 case SVCHlpMsg::Error:
612 {
613 /* read the error message */
614 Utf8Str errMsg;
615 vrc = aClient->read(errMsg);
616 if (RT_FAILURE(vrc)) break;
617
618 rc = E_FAIL;
619 d->iface->setError(E_FAIL, errMsg.c_str());
620 endLoop = true;
621 break;
622 }
623 default:
624 {
625 endLoop = true;
626 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak((
627 //"Invalid message code %d (%08lX)\n",
628 //reply, reply),
629 //rc = E_FAIL);
630 }
631 }
632 }
633
634 break;
635 }
636 default:
637 rc = E_FAIL; // TODO: ComAssertMsgFailedBreak((
638// "Invalid message code %d (%08lX)\n",
639// d->msgCode, d->msgCode),
640// rc = E_FAIL);
641 }
642
643 if (aVrc)
644 *aVrc = vrc;
645
646 LogFlowFunc(("rc=0x%08X, vrc=%Rrc\n", rc, vrc));
647 LogFlowFuncLeave();
648 return rc;
649}
650
651
652int netIfNetworkInterfaceHelperServer(SVCHlpClient *aClient,
653 SVCHlpMsg::Code aMsgCode)
654{
655 LogFlowFuncEnter();
656 LogFlowFunc(("aClient={%p}, aMsgCode=%d\n", aClient, aMsgCode));
657
658 AssertReturn(aClient, VERR_INVALID_POINTER);
659
660 int vrc = VINF_SUCCESS;
661 HRESULT hrc;
662
663 switch (aMsgCode)
664 {
665 case SVCHlpMsg::CreateHostOnlyNetworkInterface:
666 {
667 LogFlowFunc(("CreateHostOnlyNetworkInterface:\n"));
668
669// Utf8Str name;
670// vrc = aClient->read(name);
671// if (RT_FAILURE(vrc)) break;
672
673 Guid guid;
674 Utf8Str errMsg;
675 Bstr name;
676 Bstr bstrErr;
677
678#ifdef VBOXNETCFG_DELAYEDRENAME
679 Bstr devId;
680 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), devId.asOutParam(),
681 bstrErr.asOutParam());
682#else /* !VBOXNETCFG_DELAYEDRENAME */
683 hrc = VBoxNetCfgWinCreateHostOnlyNetworkInterface(NULL, false, guid.asOutParam(), name.asOutParam(),
684 bstrErr.asOutParam());
685#endif /* !VBOXNETCFG_DELAYEDRENAME */
686
687 if (hrc == S_OK)
688 {
689 ULONG ip, mask;
690 hrc = VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(&ip, &mask);
691 if (hrc == S_OK)
692 {
693 /* ip returned by VBoxNetCfgWinGenHostOnlyNetworkNetworkIp is a network ip,
694 * i.e. 192.168.xxx.0, assign 192.168.xxx.1 for the hostonly adapter */
695 ip = ip | (1 << 24);
696 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID*)guid.raw(), ip, mask);
697 if (hrc != S_OK)
698 LogRel(("VBoxNetCfgWinEnableStaticIpConfig failed (0x%x)\n", hrc));
699 }
700 else
701 LogRel(("VBoxNetCfgWinGenHostOnlyNetworkNetworkIp failed (0x%x)\n", hrc));
702#ifdef VBOXNETCFG_DELAYEDRENAME
703 hrc = VBoxNetCfgWinRenameHostOnlyConnection((const GUID*)guid.raw(), devId.raw(), name.asOutParam());
704 if (hrc != S_OK)
705 LogRel(("VBoxNetCfgWinRenameHostOnlyConnection failed, error = 0x%x", hrc));
706#endif /* VBOXNETCFG_DELAYEDRENAME */
707 /* write success followed by GUID */
708 vrc = aClient->write(SVCHlpMsg::CreateHostOnlyNetworkInterface_OK);
709 if (RT_FAILURE(vrc)) break;
710 vrc = aClient->write(Utf8Str(name));
711 if (RT_FAILURE(vrc)) break;
712 vrc = aClient->write(guid);
713 if (RT_FAILURE(vrc)) break;
714 }
715 else
716 {
717 vrc = VERR_GENERAL_FAILURE;
718 errMsg = Utf8Str(bstrErr);
719 /* write failure followed by error message */
720 if (errMsg.isEmpty())
721 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
722 vrc = aClient->write(SVCHlpMsg::Error);
723 if (RT_FAILURE(vrc)) break;
724 vrc = aClient->write(errMsg);
725 if (RT_FAILURE(vrc)) break;
726 }
727
728 break;
729 }
730 case SVCHlpMsg::RemoveHostOnlyNetworkInterface:
731 {
732 LogFlowFunc(("RemoveHostOnlyNetworkInterface:\n"));
733
734 Guid guid;
735 Bstr bstrErr;
736
737 vrc = aClient->read(guid);
738 if (RT_FAILURE(vrc)) break;
739
740 Utf8Str errMsg;
741 hrc = VBoxNetCfgWinRemoveHostOnlyNetworkInterface((const GUID*)guid.raw(), bstrErr.asOutParam());
742
743 if (hrc == S_OK)
744 {
745 /* write parameter-less success */
746 vrc = aClient->write(SVCHlpMsg::OK);
747 if (RT_FAILURE(vrc)) break;
748 }
749 else
750 {
751 vrc = VERR_GENERAL_FAILURE;
752 errMsg = Utf8Str(bstrErr);
753 /* write failure followed by error message */
754 if (errMsg.isEmpty())
755 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
756 vrc = aClient->write(SVCHlpMsg::Error);
757 if (RT_FAILURE(vrc)) break;
758 vrc = aClient->write(errMsg);
759 if (RT_FAILURE(vrc)) break;
760 }
761
762 break;
763 }
764 case SVCHlpMsg::EnableStaticIpConfigV6:
765 {
766 LogFlowFunc(("EnableStaticIpConfigV6:\n"));
767
768 Guid guid;
769 Utf8Str ipV6;
770 ULONG maskLengthV6;
771 vrc = aClient->read(guid);
772 if (RT_FAILURE(vrc)) break;
773 vrc = aClient->read(ipV6);
774 if (RT_FAILURE(vrc)) break;
775 vrc = aClient->read(maskLengthV6);
776 if (RT_FAILURE(vrc)) break;
777
778 Utf8Str errMsg;
779 vrc = VERR_NOT_IMPLEMENTED;
780
781 if (RT_SUCCESS(vrc))
782 {
783 /* write success followed by GUID */
784 vrc = aClient->write(SVCHlpMsg::OK);
785 if (RT_FAILURE(vrc)) break;
786 }
787 else
788 {
789 /* write failure followed by error message */
790 if (errMsg.isEmpty())
791 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
792 vrc = aClient->write(SVCHlpMsg::Error);
793 if (RT_FAILURE(vrc)) break;
794 vrc = aClient->write(errMsg);
795 if (RT_FAILURE(vrc)) break;
796 }
797
798 break;
799 }
800 case SVCHlpMsg::EnableStaticIpConfig:
801 {
802 LogFlowFunc(("EnableStaticIpConfig:\n"));
803
804 Guid guid;
805 ULONG ip, mask;
806 vrc = aClient->read(guid);
807 if (RT_FAILURE(vrc)) break;
808 vrc = aClient->read(ip);
809 if (RT_FAILURE(vrc)) break;
810 vrc = aClient->read(mask);
811 if (RT_FAILURE(vrc)) break;
812
813 Utf8Str errMsg;
814 hrc = VBoxNetCfgWinEnableStaticIpConfig((const GUID *)guid.raw(), ip, mask);
815
816 if (hrc == S_OK)
817 {
818 /* write success followed by GUID */
819 vrc = aClient->write(SVCHlpMsg::OK);
820 if (RT_FAILURE(vrc)) break;
821 }
822 else
823 {
824 vrc = VERR_GENERAL_FAILURE;
825 /* write failure followed by error message */
826 if (errMsg.isEmpty())
827 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
828 vrc = aClient->write(SVCHlpMsg::Error);
829 if (RT_FAILURE(vrc)) break;
830 vrc = aClient->write(errMsg);
831 if (RT_FAILURE(vrc)) break;
832 }
833
834 break;
835 }
836 case SVCHlpMsg::EnableDynamicIpConfig:
837 {
838 LogFlowFunc(("EnableDynamicIpConfig:\n"));
839
840 Guid guid;
841 vrc = aClient->read(guid);
842 if (RT_FAILURE(vrc)) break;
843
844 Utf8Str errMsg;
845 hrc = VBoxNetCfgWinEnableDynamicIpConfig((const GUID *)guid.raw());
846
847 if (hrc == S_OK)
848 {
849 /* write success followed by GUID */
850 vrc = aClient->write(SVCHlpMsg::OK);
851 if (RT_FAILURE(vrc)) break;
852 }
853 else
854 {
855 vrc = VERR_GENERAL_FAILURE;
856 /* write failure followed by error message */
857 if (errMsg.isEmpty())
858 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
859 vrc = aClient->write(SVCHlpMsg::Error);
860 if (RT_FAILURE(vrc)) break;
861 vrc = aClient->write(errMsg);
862 if (RT_FAILURE(vrc)) break;
863 }
864
865 break;
866 }
867 case SVCHlpMsg::DhcpRediscover:
868 {
869 LogFlowFunc(("DhcpRediscover:\n"));
870
871 Guid guid;
872 vrc = aClient->read(guid);
873 if (RT_FAILURE(vrc)) break;
874
875 Utf8Str errMsg;
876 hrc = VBoxNetCfgWinDhcpRediscover((const GUID *)guid.raw());
877
878 if (hrc == S_OK)
879 {
880 /* write success followed by GUID */
881 vrc = aClient->write(SVCHlpMsg::OK);
882 if (RT_FAILURE(vrc)) break;
883 }
884 else
885 {
886 vrc = VERR_GENERAL_FAILURE;
887 /* write failure followed by error message */
888 if (errMsg.isEmpty())
889 errMsg = Utf8StrFmt("Unspecified error (%Rrc)", vrc);
890 vrc = aClient->write(SVCHlpMsg::Error);
891 if (RT_FAILURE(vrc)) break;
892 vrc = aClient->write(errMsg);
893 if (RT_FAILURE(vrc)) break;
894 }
895
896 break;
897 }
898 default:
899 AssertMsgFailedBreakStmt(
900 ("Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode),
901 VERR_GENERAL_FAILURE);
902 }
903
904 LogFlowFunc(("vrc=%Rrc\n", vrc));
905 LogFlowFuncLeave();
906 return vrc;
907}
908
909/** @todo REMOVE. OBSOLETE NOW. */
910/**
911 * Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
912 * later OSes) and it has the UAC (User Account Control) feature enabled.
913 */
914static BOOL IsUACEnabled()
915{
916 LONG rc = 0;
917
918 OSVERSIONINFOEX info;
919 ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
920 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
921 rc = GetVersionEx((OSVERSIONINFO *) &info);
922 AssertReturn(rc != 0, FALSE);
923
924 LogFlowFunc(("dwMajorVersion=%d, dwMinorVersion=%d\n",
925 info.dwMajorVersion, info.dwMinorVersion));
926
927 /* we are interested only in Vista (and newer versions...). In all
928 * earlier versions UAC is not present. */
929 if (info.dwMajorVersion < 6)
930 return FALSE;
931
932 /* the default EnableLUA value is 1 (Enabled) */
933 DWORD dwEnableLUA = 1;
934
935 HKEY hKey;
936 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
937 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
938 0, KEY_QUERY_VALUE, &hKey);
939
940 Assert(rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND);
941 if (rc == ERROR_SUCCESS)
942 {
943
944 DWORD cbEnableLUA = sizeof(dwEnableLUA);
945 rc = RegQueryValueExA(hKey, "EnableLUA", NULL, NULL,
946 (LPBYTE) &dwEnableLUA, &cbEnableLUA);
947
948 RegCloseKey(hKey);
949
950 Assert(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND);
951 }
952
953 LogFlowFunc(("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA));
954
955 return dwEnableLUA == 1;
956}
957
958/* end */
959
960static int vboxNetWinAddComponent(std::list<ComObjPtr<HostNetworkInterface> > * pPist,
961 INetCfgComponent * pncc, HostNetworkInterfaceType enmType,
962 int iDefaultInterface)
963{
964 LPWSTR lpszName;
965 GUID IfGuid;
966 HRESULT hr;
967 int rc = VERR_GENERAL_FAILURE;
968
969 hr = pncc->GetDisplayName(&lpszName);
970 Assert(hr == S_OK);
971 if (hr == S_OK)
972 {
973 Bstr name(lpszName);
974
975 hr = pncc->GetInstanceGuid(&IfGuid);
976 Assert(hr == S_OK);
977 if (hr == S_OK)
978 {
979 NETIFINFO Info;
980 RT_ZERO(Info);
981 Info.Uuid = *(Guid(IfGuid).raw());
982 rc = collectNetIfInfo(name, Guid(IfGuid), &Info, iDefaultInterface);
983 if (RT_FAILURE(rc))
984 {
985 LogRel(("vboxNetWinAddComponent: collectNetIfInfo() -> %Rrc\n", rc));
986 }
987 Log(("vboxNetWinAddComponent: adding %ls\n", lpszName));
988 /* create a new object and add it to the list */
989 ComObjPtr<HostNetworkInterface> iface;
990 iface.createObject();
991 /* remove the curly bracket at the end */
992 rc = iface->init(name, enmType, &Info);
993 if (SUCCEEDED(rc))
994 {
995 if (Info.bIsDefault)
996 pPist->push_front(iface);
997 else
998 pPist->push_back(iface);
999 }
1000 else
1001 {
1002 LogRel(("vboxNetWinAddComponent: HostNetworkInterface::init() -> %Rrc\n", rc));
1003 Assert(0);
1004 }
1005 }
1006 else
1007 LogRel(("vboxNetWinAddComponent: failed to get device instance GUID (0x%x)\n", hr));
1008 CoTaskMemFree(lpszName);
1009 }
1010 else
1011 LogRel(("vboxNetWinAddComponent: failed to get device display name (0x%x)\n", hr));
1012
1013 return rc;
1014}
1015
1016#endif /* VBOX_WITH_NETFLT */
1017
1018
1019static int netIfListHostAdapters(INetCfg *pNc, std::list<ComObjPtr<HostNetworkInterface> > &list)
1020{
1021#ifndef VBOX_WITH_NETFLT
1022 /* VBoxNetAdp is available only when VBOX_WITH_NETFLT is enabled */
1023 return VERR_NOT_IMPLEMENTED;
1024#else /* # if defined VBOX_WITH_NETFLT */
1025 INetCfgComponent *pMpNcc;
1026 HRESULT hr;
1027 IEnumNetCfgComponent *pEnumComponent;
1028
1029 hr = pNc->EnumComponents(&GUID_DEVCLASS_NET, &pEnumComponent);
1030 if (hr == S_OK)
1031 {
1032 while ((hr = pEnumComponent->Next(1, &pMpNcc, NULL)) == S_OK)
1033 {
1034 LPWSTR pwszName;
1035 ULONG uComponentStatus;
1036 hr = pMpNcc->GetDisplayName(&pwszName);
1037 if (hr == S_OK)
1038 Log(("netIfListHostAdapters: %ls\n", pwszName));
1039 else
1040 LogRel(("netIfListHostAdapters: failed to get device display name (0x%x)\n", hr));
1041 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
1042 if (hr == S_OK)
1043 {
1044 if (uComponentStatus == 0)
1045 {
1046 LPWSTR pId;
1047 hr = pMpNcc->GetId(&pId);
1048 Assert(hr == S_OK);
1049 if (hr == S_OK)
1050 {
1051 Log(("netIfListHostAdapters: id = %ls\n", pId));
1052 if (!_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1053 {
1054 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_HostOnly, -1);
1055 }
1056 CoTaskMemFree(pId);
1057 }
1058 else
1059 LogRel(("netIfListHostAdapters: failed to get device id (0x%x)\n", hr));
1060 }
1061 }
1062 else
1063 LogRel(("netIfListHostAdapters: failed to get device status (0x%x)\n", hr));
1064 pMpNcc->Release();
1065 }
1066 Assert(hr == S_OK || hr == S_FALSE);
1067
1068 pEnumComponent->Release();
1069 }
1070 else
1071 LogRel(("netIfListHostAdapters: EnumComponents error (0x%x)\n", hr));
1072#endif /* # if defined VBOX_WITH_NETFLT */
1073 return VINF_SUCCESS;
1074}
1075
1076int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *pInfo)
1077{
1078#ifndef VBOX_WITH_NETFLT
1079 return VERR_NOT_IMPLEMENTED;
1080#else
1081 Bstr name;
1082 HRESULT hr = pIf->COMGETTER(Name)(name.asOutParam());
1083 if (hr == S_OK)
1084 {
1085 Bstr IfGuid;
1086 hr = pIf->COMGETTER(Id)(IfGuid.asOutParam());
1087 Assert(hr == S_OK);
1088 if (hr == S_OK)
1089 {
1090 memset(pInfo, 0, sizeof(NETIFINFO));
1091 Guid guid(IfGuid);
1092 pInfo->Uuid = *(guid.raw());
1093
1094 return collectNetIfInfo(name, guid, pInfo, getDefaultInterfaceIndex());
1095 }
1096 }
1097 return VERR_GENERAL_FAILURE;
1098#endif
1099}
1100
1101int NetIfGetConfigByName(PNETIFINFO)
1102{
1103 return VERR_NOT_IMPLEMENTED;
1104}
1105
1106/**
1107 * Obtain the current state of the interface.
1108 *
1109 * @returns VBox status code.
1110 *
1111 * @param pcszIfName Interface name.
1112 * @param penmState Where to store the retrieved state.
1113 */
1114int NetIfGetState(const char *pcszIfName, NETIFSTATUS *penmState)
1115{
1116 return VERR_NOT_IMPLEMENTED;
1117}
1118
1119/**
1120 * Retrieve the physical link speed in megabits per second. If the interface is
1121 * not up or otherwise unavailable the zero speed is returned.
1122 *
1123 * @returns VBox status code.
1124 *
1125 * @param pcszIfName Interface name.
1126 * @param puMbits Where to store the link speed.
1127 */
1128int NetIfGetLinkSpeed(const char * /*pcszIfName*/, uint32_t * /*puMbits*/)
1129{
1130 return VERR_NOT_IMPLEMENTED;
1131}
1132
1133int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox,
1134 IHostNetworkInterface **aHostNetworkInterface,
1135 IProgress **aProgress,
1136 const char *pcszName)
1137{
1138#ifndef VBOX_WITH_NETFLT
1139 return VERR_NOT_IMPLEMENTED;
1140#else
1141 /* create a progress object */
1142 ComObjPtr<Progress> progress;
1143 progress.createObject();
1144
1145 ComPtr<IHost> host;
1146 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1147 if (SUCCEEDED(rc))
1148 {
1149 rc = progress->init(pVirtualBox, host,
1150 Bstr(_T("Creating host only network interface")).raw(),
1151 FALSE /* aCancelable */);
1152 if (SUCCEEDED(rc))
1153 {
1154 if (FAILED(rc)) return rc;
1155 progress.queryInterfaceTo(aProgress);
1156
1157 /* create a new uninitialized host interface object */
1158 ComObjPtr<HostNetworkInterface> iface;
1159 iface.createObject();
1160 iface.queryInterfaceTo(aHostNetworkInterface);
1161
1162 /* create the networkInterfaceHelperClient() argument */
1163 std::auto_ptr<NetworkInterfaceHelperClientData>
1164 d(new NetworkInterfaceHelperClientData());
1165 AssertReturn(d.get(), E_OUTOFMEMORY);
1166
1167 d->msgCode = SVCHlpMsg::CreateHostOnlyNetworkInterface;
1168// d->name = aName;
1169 d->iface = iface;
1170 d->vBox = pVirtualBox;
1171
1172 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1173 netIfNetworkInterfaceHelperClient,
1174 static_cast<void *>(d.get()),
1175 progress);
1176 if (SUCCEEDED(rc))
1177 {
1178 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1179 d.release();
1180 }
1181 }
1182 }
1183
1184 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1185#endif
1186}
1187
1188int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId,
1189 IProgress **aProgress)
1190{
1191#ifndef VBOX_WITH_NETFLT
1192 return VERR_NOT_IMPLEMENTED;
1193#else
1194 /* create a progress object */
1195 ComObjPtr<Progress> progress;
1196 progress.createObject();
1197 ComPtr<IHost> host;
1198 HRESULT rc = pVirtualBox->COMGETTER(Host)(host.asOutParam());
1199 if (SUCCEEDED(rc))
1200 {
1201 rc = progress->init(pVirtualBox, host,
1202 Bstr(_T("Removing host network interface")).raw(),
1203 FALSE /* aCancelable */);
1204 if (SUCCEEDED(rc))
1205 {
1206 if (FAILED(rc)) return rc;
1207 progress.queryInterfaceTo(aProgress);
1208
1209 /* create the networkInterfaceHelperClient() argument */
1210 std::auto_ptr<NetworkInterfaceHelperClientData>
1211 d(new NetworkInterfaceHelperClientData());
1212 AssertReturn(d.get(), E_OUTOFMEMORY);
1213
1214 d->msgCode = SVCHlpMsg::RemoveHostOnlyNetworkInterface;
1215 d->guid = aId;
1216
1217 rc = pVirtualBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1218 netIfNetworkInterfaceHelperClient,
1219 static_cast<void *>(d.get()),
1220 progress);
1221
1222 if (SUCCEEDED(rc))
1223 {
1224 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1225 d.release();
1226 }
1227 }
1228 }
1229
1230 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1231#endif
1232}
1233
1234int NetIfEnableStaticIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG ip, ULONG mask)
1235{
1236#ifndef VBOX_WITH_NETFLT
1237 return VERR_NOT_IMPLEMENTED;
1238#else
1239 HRESULT rc;
1240 Bstr guid;
1241 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1242 if (SUCCEEDED(rc))
1243 {
1244// ComPtr<VirtualBox> vBox;
1245// rc = pIf->getVirtualBox(vBox.asOutParam());
1246// if (SUCCEEDED(rc))
1247 {
1248 /* create a progress object */
1249 ComObjPtr<Progress> progress;
1250 progress.createObject();
1251// ComPtr<IHost> host;
1252// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1253// if (SUCCEEDED(rc))
1254 {
1255 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1256 Bstr("Enabling Dynamic Ip Configuration").raw(),
1257 FALSE /* aCancelable */);
1258 if (SUCCEEDED(rc))
1259 {
1260 if (FAILED(rc)) return rc;
1261// progress.queryInterfaceTo(aProgress);
1262
1263 /* create the networkInterfaceHelperClient() argument */
1264 std::auto_ptr<NetworkInterfaceHelperClientData>
1265 d(new NetworkInterfaceHelperClientData());
1266 AssertReturn(d.get(), E_OUTOFMEMORY);
1267
1268 d->msgCode = SVCHlpMsg::EnableStaticIpConfig;
1269 d->guid = Guid(guid);
1270 d->iface = pIf;
1271 d->u.StaticIP.IPAddress = ip;
1272 d->u.StaticIP.IPNetMask = mask;
1273
1274 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1275 netIfNetworkInterfaceHelperClient,
1276 static_cast<void *>(d.get()),
1277 progress);
1278
1279 if (SUCCEEDED(rc))
1280 {
1281 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1282 d.release();
1283
1284 progress->WaitForCompletion(-1);
1285 }
1286 }
1287 }
1288 }
1289 }
1290
1291 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1292#endif
1293}
1294
1295int NetIfEnableStaticIpConfigV6(VirtualBox *vBox, HostNetworkInterface * pIf, IN_BSTR aOldIPV6Address,
1296 IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
1297{
1298#ifndef VBOX_WITH_NETFLT
1299 return VERR_NOT_IMPLEMENTED;
1300#else
1301 HRESULT rc;
1302 Bstr guid;
1303 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1304 if (SUCCEEDED(rc))
1305 {
1306// ComPtr<VirtualBox> vBox;
1307// rc = pIf->getVirtualBox(vBox.asOutParam());
1308// if (SUCCEEDED(rc))
1309 {
1310 /* create a progress object */
1311 ComObjPtr<Progress> progress;
1312 progress.createObject();
1313// ComPtr<IHost> host;
1314// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1315// if (SUCCEEDED(rc))
1316 {
1317 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1318 Bstr("Enabling Dynamic Ip Configuration").raw(),
1319 FALSE /* aCancelable */);
1320 if (SUCCEEDED(rc))
1321 {
1322 if (FAILED(rc)) return rc;
1323// progress.queryInterfaceTo(aProgress);
1324
1325 /* create the networkInterfaceHelperClient() argument */
1326 std::auto_ptr<NetworkInterfaceHelperClientData>
1327 d(new NetworkInterfaceHelperClientData());
1328 AssertReturn(d.get(), E_OUTOFMEMORY);
1329
1330 d->msgCode = SVCHlpMsg::EnableStaticIpConfigV6;
1331 d->guid = guid;
1332 d->iface = pIf;
1333 d->u.StaticIPV6.IPV6Address = aIPV6Address;
1334 d->u.StaticIPV6.IPV6NetMaskLength = aIPV6MaskPrefixLength;
1335
1336 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1337 netIfNetworkInterfaceHelperClient,
1338 static_cast<void *>(d.get()),
1339 progress);
1340
1341 if (SUCCEEDED(rc))
1342 {
1343 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1344 d.release();
1345
1346 progress->WaitForCompletion(-1);
1347 }
1348 }
1349 }
1350 }
1351 }
1352
1353 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1354#endif
1355}
1356
1357int NetIfEnableDynamicIpConfig(VirtualBox *vBox, HostNetworkInterface * pIf)
1358{
1359#ifndef VBOX_WITH_NETFLT
1360 return VERR_NOT_IMPLEMENTED;
1361#else
1362 HRESULT rc;
1363 Bstr guid;
1364 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1365 if (SUCCEEDED(rc))
1366 {
1367// ComPtr<VirtualBox> vBox;
1368// rc = pIf->getVirtualBox(vBox.asOutParam());
1369// if (SUCCEEDED(rc))
1370 {
1371 /* create a progress object */
1372 ComObjPtr<Progress> progress;
1373 progress.createObject();
1374// ComPtr<IHost> host;
1375// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1376// if (SUCCEEDED(rc))
1377 {
1378 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1379 Bstr("Enabling Dynamic Ip Configuration").raw(),
1380 FALSE /* aCancelable */);
1381 if (SUCCEEDED(rc))
1382 {
1383 if (FAILED(rc)) return rc;
1384// progress.queryInterfaceTo(aProgress);
1385
1386 /* create the networkInterfaceHelperClient() argument */
1387 std::auto_ptr<NetworkInterfaceHelperClientData>
1388 d(new NetworkInterfaceHelperClientData());
1389 AssertReturn(d.get(), E_OUTOFMEMORY);
1390
1391 d->msgCode = SVCHlpMsg::EnableDynamicIpConfig;
1392 d->guid = guid;
1393 d->iface = pIf;
1394
1395 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1396 netIfNetworkInterfaceHelperClient,
1397 static_cast<void *>(d.get()),
1398 progress);
1399
1400 if (SUCCEEDED(rc))
1401 {
1402 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1403 d.release();
1404
1405 progress->WaitForCompletion(-1);
1406 }
1407 }
1408 }
1409 }
1410 }
1411
1412 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1413#endif
1414}
1415
1416int NetIfDhcpRediscover(VirtualBox *vBox, HostNetworkInterface * pIf)
1417{
1418#ifndef VBOX_WITH_NETFLT
1419 return VERR_NOT_IMPLEMENTED;
1420#else
1421 HRESULT rc;
1422 Bstr guid;
1423 rc = pIf->COMGETTER(Id)(guid.asOutParam());
1424 if (SUCCEEDED(rc))
1425 {
1426// ComPtr<VirtualBox> vBox;
1427// rc = pIf->getVirtualBox(vBox.asOutParam());
1428// if (SUCCEEDED(rc))
1429 {
1430 /* create a progress object */
1431 ComObjPtr<Progress> progress;
1432 progress.createObject();
1433// ComPtr<IHost> host;
1434// HRESULT rc = vBox->COMGETTER(Host)(host.asOutParam());
1435// if (SUCCEEDED(rc))
1436 {
1437 rc = progress->init(vBox, (IHostNetworkInterface*)pIf,
1438 Bstr("Enabling Dynamic Ip Configuration").raw(),
1439 FALSE /* aCancelable */);
1440 if (SUCCEEDED(rc))
1441 {
1442 if (FAILED(rc)) return rc;
1443// progress.queryInterfaceTo(aProgress);
1444
1445 /* create the networkInterfaceHelperClient() argument */
1446 std::auto_ptr<NetworkInterfaceHelperClientData>
1447 d(new NetworkInterfaceHelperClientData());
1448 AssertReturn(d.get(), E_OUTOFMEMORY);
1449
1450 d->msgCode = SVCHlpMsg::DhcpRediscover;
1451 d->guid = guid;
1452 d->iface = pIf;
1453
1454 rc = vBox->i_startSVCHelperClient(IsUACEnabled() == TRUE /* aPrivileged */,
1455 netIfNetworkInterfaceHelperClient,
1456 static_cast<void *>(d.get()),
1457 progress);
1458
1459 if (SUCCEEDED(rc))
1460 {
1461 /* d is now owned by netIfNetworkInterfaceHelperClient(), so release it */
1462 d.release();
1463
1464 progress->WaitForCompletion(-1);
1465 }
1466 }
1467 }
1468 }
1469 }
1470
1471 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
1472#endif
1473}
1474
1475#ifndef NETIF_WITHOUT_NETCFG
1476int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
1477{
1478#ifndef VBOX_WITH_NETFLT
1479 return VERR_NOT_IMPLEMENTED;
1480#else /* # if defined VBOX_WITH_NETFLT */
1481 INetCfg *pNc = NULL;
1482 INetCfgComponent *pMpNcc;
1483 INetCfgComponent *pTcpIpNcc;
1484 LPWSTR lpszApp;
1485 HRESULT hr;
1486 IEnumNetCfgBindingPath *pEnumBp;
1487 INetCfgBindingPath *pBp;
1488 IEnumNetCfgBindingInterface *pEnumBi;
1489 INetCfgBindingInterface *pBi;
1490 int iDefault = getDefaultInterfaceIndex();
1491
1492 Log(("NetIfList: building the list of interfaces\n"));
1493 /* we are using the INetCfg API for getting the list of miniports */
1494 hr = VBoxNetCfgWinQueryINetCfg(&pNc, FALSE,
1495 VBOX_APP_NAME,
1496 10000,
1497 &lpszApp);
1498 Assert(hr == S_OK);
1499 if (hr != S_OK)
1500 {
1501 if (pNc)
1502 pNc->Release();
1503 pNc = NULL;
1504 LogRel(("NetIfList: failed to acquire INetCfg interface (0x%x), trying CoCreateInstance...\n", hr));
1505 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (PVOID*)&pNc);
1506 if (SUCCEEDED(hr))
1507 {
1508 hr = pNc->Initialize(NULL);
1509 if (FAILED(hr))
1510 {
1511 LogRel(("NetIfList: INetCfg::Initialize failed with 0x%x\n", hr));
1512 if (pNc)
1513 pNc->Release();
1514 pNc = NULL;
1515 }
1516 }
1517 else
1518 LogRel(("NetIfList: CoCreateInstance failed with 0x%x\n", hr));
1519 }
1520
1521 if (hr == S_OK)
1522 {
1523# ifdef VBOX_NETFLT_ONDEMAND_BIND
1524 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
1525 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
1526# else
1527 /* for the filter-based approach we get all miniports our filter (oracle_VBoxNetLwf)is bound to */
1528 hr = pNc->FindComponent(L"oracle_VBoxNetLwf", &pTcpIpNcc);
1529 if (hr != S_OK)
1530 {
1531 LogRel(("NetIfList: could not find VBoxNetLwf component (error 0x%x), trying VBoxNetFlt instead\n", hr));
1532 /* fall back to NDIS5 miniport lookup (sun_VBoxNetFlt) */
1533 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
1534 }
1535# ifndef VBOX_WITH_HARDENING
1536 if (hr != S_OK)
1537 {
1538 /* TODO: try to install the netflt from here */
1539 }
1540# endif
1541
1542# endif
1543
1544 if (hr == S_OK)
1545 {
1546 INetCfgComponentBindings *pBindings;
1547 hr = pTcpIpNcc->QueryInterface(IID_INetCfgComponentBindings, (PVOID*)&pBindings);
1548 Assert(hr == S_OK);
1549 if (hr == S_OK)
1550 {
1551 hr = pBindings->EnumBindingPaths(EBP_BELOW, &pEnumBp);
1552 Assert(hr == S_OK);
1553 if (hr == S_OK)
1554 {
1555 hr = pEnumBp->Reset();
1556 Assert(hr == S_OK);
1557 if (hr == S_OK)
1558 {
1559 while ((hr = pEnumBp->Next(1, &pBp, NULL)) == S_OK)
1560 {
1561 Log(("NetIfList: fetched INetCfgBindingPath interface\n"));
1562 /* S_OK == enabled, S_FALSE == disabled */
1563 if (pBp->IsEnabled() == S_OK)
1564 {
1565 hr = pBp->EnumBindingInterfaces(&pEnumBi);
1566 Assert(hr == S_OK);
1567 if (hr == S_OK)
1568 {
1569 hr = pEnumBi->Reset();
1570 Assert(hr == S_OK);
1571 if (hr == S_OK)
1572 {
1573 while ((hr = pEnumBi->Next(1, &pBi, NULL)) == S_OK)
1574 {
1575 Log(("NetIfList: fetched INetCfgBindingInterface interface\n"));
1576 hr = pBi->GetLowerComponent(&pMpNcc);
1577 Assert(hr == S_OK);
1578 if (hr == S_OK)
1579 {
1580 LPWSTR pwszName;
1581 ULONG uComponentStatus;
1582 hr = pMpNcc->GetDisplayName(&pwszName);
1583 if (hr == S_OK)
1584 Log(("NetIfList: got %ls\n", pwszName));
1585 else
1586 LogRel(("NetIfList: failed to get device display name (0x%x)\n", hr));
1587 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
1588 if (hr == S_OK)
1589 {
1590 if (uComponentStatus == 0)
1591 {
1592 LPWSTR pId;
1593 hr = pMpNcc->GetId(&pId);
1594 Assert(hr == S_OK);
1595 if (hr == S_OK)
1596 {
1597 Log(("NetIfList: fetched network adapter id: %.80ls\n", pId));
1598 /*
1599 * Host-only interfaces are ignored here and included into the list
1600 * later in netIfListHostAdapters()
1601 */
1602 if (_wcsnicmp(pId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1603 {
1604 vboxNetWinAddComponent(&list, pMpNcc, HostNetworkInterfaceType_Bridged,
1605 iDefault);
1606 }
1607 CoTaskMemFree(pId);
1608 }
1609 else
1610 LogRel(("NetIfList: failed to get device id (0x%x)\n", hr));
1611 }
1612 else
1613 LogRel(("NetIfList: wrong device status (0x%x)\n", uComponentStatus));
1614 }
1615 else
1616 LogRel(("NetIfList: failed to get device status (0x%x)\n", hr));
1617 pMpNcc->Release();
1618 }
1619 else
1620 LogRel(("NetIfList: failed to get lower component (0x%x)\n", hr));
1621 pBi->Release();
1622 }
1623 Assert(hr == S_OK || hr == S_FALSE);
1624 }
1625 else
1626 LogRel(("NetIfList: IEnumNetCfgBindingInterface::Reset failed (0x%x)\n", hr));
1627 pEnumBi->Release();
1628 }
1629 else
1630 LogRel(("NetIfList: failed to enumerate binding interfaces (0x%x)\n", hr));
1631 }
1632 else
1633 LogRel(("NetIfList: INetCfgBindingPath is disabled\n"));
1634 pBp->Release();
1635 }
1636 Assert(hr == S_OK || hr == S_FALSE);
1637 }
1638 else
1639 LogRel(("NetIfList: IEnumNetCfgBindingPath::Reset failed (0x%x)\n", hr));
1640 pEnumBp->Release();
1641 }
1642 else
1643 LogRel(("NetIfList: EnumBindingPaths failed (0x%x)\n", hr));
1644 pBindings->Release();
1645 }
1646 else
1647 LogRel(("NetIfList: failed to acquire INetCfgComponentBindings interface\n"));
1648 pTcpIpNcc->Release();
1649 }
1650 else
1651 {
1652 LogRel(("failed to get the oracle_VBoxNetLwf(sun_VBoxNetFlt) component, error (0x%x)\n", hr));
1653 }
1654
1655 /* Add host-only adapters to the list */
1656 netIfListHostAdapters(pNc, list);
1657
1658 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
1659 }
1660
1661 return VINF_SUCCESS;
1662#endif /* # if defined VBOX_WITH_NETFLT */
1663}
1664
1665#else /* !NETIF_WITHOUT_NETCFG */
1666
1667static void getTypeAndName(PIP_ADAPTER_ADDRESSES pAdapter, HostNetworkInterfaceType *enmType, PWCHAR pwszName, int cbName)
1668{
1669 /* In case we fail to get the right values we initialize them with best-effort defaults. */
1670 *enmType = wcsncmp(pAdapter->Description, L"VirtualBox", 10) == 0
1671 ? HostNetworkInterfaceType_HostOnly
1672 : HostNetworkInterfaceType_Bridged;
1673 wcscpy_s(pwszName, cbName / sizeof(*pwszName), pAdapter->Description);
1674
1675 char szKeyName[256];
1676 sprintf_s(szKeyName, sizeof(szKeyName),
1677 "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
1678 pAdapter->AdapterName);
1679 HKEY hkeyConnection;
1680 LONG status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hkeyConnection);
1681 if (status != ERROR_SUCCESS)
1682 {
1683 LogRel(("NetIf: Failed to find connection key in registry for %ls at %s\n",
1684 pAdapter->Description, szKeyName));
1685 }
1686 else
1687 {
1688 WCHAR wszId[256];
1689 DWORD dwLen = sizeof(wszId);
1690 status = RegQueryValueExW(hkeyConnection, L"PnPInstanceID", NULL, NULL, (LPBYTE)wszId, &dwLen);
1691 if (status != ERROR_SUCCESS)
1692 {
1693 LogRel(("NetIf: Failed to get PnPInstanceID from registry for %ls\n", pAdapter->Description));
1694 }
1695 else
1696 {
1697 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_NET, NULL);
1698 if (hDevInfo != INVALID_HANDLE_VALUE)
1699 {
1700 SP_DEVINFO_DATA DevInfoData;
1701
1702 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1703 if (SetupDiOpenDeviceInfo(hDevInfo, wszId, NULL, 0, &DevInfoData))
1704 {
1705 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &DevInfoData,
1706 SPDRP_HARDWAREID, NULL,
1707 (PBYTE)wszId, sizeof(wszId), NULL))
1708 {
1709 /*
1710 * We do not care for multiple strings that may have been
1711 * returned since our host-only adapter has a single id.
1712 */
1713 if (_wcsnicmp(wszId, L"sun_VBoxNetAdp", sizeof(L"sun_VBoxNetAdp")/2))
1714 *enmType = HostNetworkInterfaceType_Bridged;
1715 else
1716 *enmType = HostNetworkInterfaceType_HostOnly;
1717 }
1718 SetupDiGetDeviceRegistryPropertyW(hDevInfo, &DevInfoData,
1719 SPDRP_FRIENDLYNAME, NULL,
1720 (PBYTE)pwszName, cbName, NULL);
1721 }
1722 SetupDiDestroyDeviceInfoList(hDevInfo);
1723 }
1724 LogRel(("PnP ID: %ls\n", wszId));
1725 }
1726 RegCloseKey(hkeyConnection);
1727 }
1728}
1729
1730int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
1731{
1732 DWORD dwRc;
1733 int rc = VINF_SUCCESS;
1734 int iDefault = getDefaultInterfaceIndex();
1735 /*
1736 * Most of the hosts probably have less than 10 adapters,
1737 * so we'll mostly succeed from the first attempt.
1738 */
1739 ULONG uBufLen = sizeof(IP_ADAPTER_ADDRESSES) * 10;
1740 PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1741 if (!pAddresses)
1742 return VERR_NO_MEMORY;
1743 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1744 if (dwRc == ERROR_BUFFER_OVERFLOW)
1745 {
1746 /* Impressive! More than 10 adapters! Get more memory and try again. */
1747 RTMemFree(pAddresses);
1748 pAddresses = (PIP_ADAPTER_ADDRESSES)RTMemAlloc(uBufLen);
1749 if (!pAddresses)
1750 return VERR_NO_MEMORY;
1751 dwRc = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &uBufLen);
1752 }
1753 if (dwRc == NO_ERROR)
1754 {
1755 PIP_ADAPTER_ADDRESSES pAdapter;
1756 for (pAdapter = pAddresses; pAdapter; pAdapter = pAdapter->Next)
1757 {
1758 Log(("Enumerating %s\n", pAdapter->AdapterName));
1759 /* Vista+ systems introduced separate type for wireless adapters */
1760 if (pAdapter->IfType != IF_TYPE_ETHERNET_CSMACD && pAdapter->IfType != IF_TYPE_IEEE80211)
1761 {
1762 LogRel(("Skipped non-Ethernet '%ls'\n", pAdapter->FriendlyName));
1763 continue;
1764 }
1765
1766 NETIFINFO Info;
1767 RT_ZERO(Info);
1768
1769 if (pAdapter->AdapterName[0] == '{')
1770 {
1771 bool fIPv4Found, fIPv6Found;
1772 PIP_ADAPTER_UNICAST_ADDRESS pAddr;
1773 fIPv4Found = fIPv6Found = false;
1774 for (pAddr = pAdapter->FirstUnicastAddress;
1775 pAddr && !(fIPv4Found && fIPv6Found);
1776 pAddr = pAddr->Next)
1777 {
1778 switch (pAddr->Address.lpSockaddr->sa_family)
1779 {
1780 case AF_INET:
1781 if (!fIPv4Found)
1782 {
1783 fIPv4Found = true;
1784 memcpy(&Info.IPAddress,
1785 &((struct sockaddr_in *)pAddr->Address.lpSockaddr)->sin_addr.s_addr,
1786 sizeof(Info.IPAddress));
1787 }
1788 break;
1789 case AF_INET6:
1790 if (!fIPv6Found)
1791 {
1792 fIPv6Found = true;
1793 memcpy(&Info.IPv6Address,
1794 ((struct sockaddr_in6 *)pAddr->Address.lpSockaddr)->sin6_addr.s6_addr,
1795 sizeof(Info.IPv6Address));
1796 }
1797 break;
1798 }
1799 }
1800 PIP_ADAPTER_PREFIX pPrefix;
1801 fIPv4Found = fIPv6Found = false;
1802 for (pPrefix = pAdapter->FirstPrefix;
1803 pPrefix && !(fIPv4Found && fIPv6Found);
1804 pPrefix = pPrefix->Next)
1805 {
1806 switch (pPrefix->Address.lpSockaddr->sa_family)
1807 {
1808 case AF_INET:
1809 if (!fIPv4Found)
1810 {
1811 if (pPrefix->PrefixLength <= sizeof(Info.IPNetMask) * 8)
1812 {
1813 fIPv4Found = true;
1814 ASMBitSetRange(&Info.IPNetMask, 0, pPrefix->PrefixLength);
1815 }
1816 else
1817 LogRel(("NetIfList: Unexpected IPv4 prefix length of %d\n",
1818 pPrefix->PrefixLength));
1819 }
1820 break;
1821 case AF_INET6:
1822 if (!fIPv6Found)
1823 {
1824 if (pPrefix->PrefixLength <= sizeof(Info.IPv6NetMask) * 8)
1825 {
1826 fIPv6Found = true;
1827 ASMBitSetRange(&Info.IPv6NetMask, 0, pPrefix->PrefixLength);
1828 }
1829 else
1830 LogRel(("NetIfList: Unexpected IPv6 prefix length of %d\n",
1831 pPrefix->PrefixLength));
1832 }
1833 break;
1834 }
1835 }
1836 if (sizeof(Info.MACAddress) != pAdapter->PhysicalAddressLength)
1837 LogRel(("NetIfList: Unexpected physical address length: %u\n",
1838 pAdapter->PhysicalAddressLength));
1839 else
1840 memcpy(Info.MACAddress.au8, pAdapter->PhysicalAddress, sizeof(Info.MACAddress));
1841 Info.enmMediumType = NETIF_T_ETHERNET;
1842 Info.enmStatus = pAdapter->OperStatus == IfOperStatusUp ? NETIF_S_UP : NETIF_S_DOWN;
1843 Info.bDhcpEnabled = !!(pAdapter->Flags & IP_ADAPTER_DHCP_ENABLED);
1844 Info.bIsDefault = (pAdapter->IfIndex == iDefault);
1845
1846 HostNetworkInterfaceType enmType;
1847 WCHAR wszName[256];
1848 /* Try to get name and type via Setup API */
1849 getTypeAndName(pAdapter, &enmType, wszName, sizeof(wszName));
1850
1851 char *pszUuid = pAdapter->AdapterName + 1;
1852 size_t len = strlen(pszUuid) - 1;
1853 if (pszUuid[len] != '}')
1854 {
1855 LogRel(("%s is not a valid UUID!\n", pAdapter->AdapterName));
1856 continue;
1857 }
1858 pszUuid[len] = 0;
1859 rc = RTUuidFromStr(&Info.Uuid, pszUuid);
1860 if (RT_FAILURE(rc))
1861 {
1862 LogRel(("NetIfList: Failed to convert %s to UUID (%Rrc)\n", pszUuid, rc));
1863 continue;
1864 }
1865 LogRel(("Adding %ls as %s\n", pAdapter->Description,
1866 enmType == HostNetworkInterfaceType_Bridged ? "bridged" :
1867 enmType == HostNetworkInterfaceType_HostOnly ? "host-only" : "unknown"));
1868 /* create a new object and add it to the list */
1869 ComObjPtr<HostNetworkInterface> iface;
1870 iface.createObject();
1871 /* remove the curly bracket at the end */
1872 rc = iface->init(wszName, enmType, &Info);
1873 if (SUCCEEDED(rc))
1874 {
1875 if (Info.bIsDefault)
1876 list.push_front(iface);
1877 else
1878 list.push_back(iface);
1879 }
1880 else
1881 {
1882 LogRel(("NetIfList: HostNetworkInterface::init() -> %Rrc\n", rc));
1883 Assert(0);
1884 }
1885 }
1886 }
1887 }
1888
1889 RTMemFree(pAddresses);
1890
1891 return VINF_SUCCESS;
1892}
1893#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