VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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