VirtualBox

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

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

Main/NetIf-win.cpp: s/vBox/p[tr]VBox/g

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