VirtualBox

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

Last change on this file since 77438 was 77438, checked in by vboxsync, 6 years ago

Main/src-server/win/NetIf-win.cpp: fix compile issue introduced in prev change

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