VirtualBox

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

Last change on this file since 98351 was 98295, checked in by vboxsync, 23 months ago

Main/src-server: hr -> hrc. bugref:10223

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