VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp@ 98068

Last change on this file since 98068 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.9 KB
Line 
1/* $Id: HostNetworkInterfaceImpl.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2022 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#define LOG_GROUP LOG_GROUP_MAIN_HOSTNETWORKINTERFACE
29#include "HostNetworkInterfaceImpl.h"
30#include "AutoCaller.h"
31#include "netif.h"
32#ifdef VBOX_WITH_RESOURCE_USAGE_API
33# include "Performance.h"
34# include "PerformanceImpl.h"
35#endif
36#include "LoggingNew.h"
37
38#include <iprt/cpp/utils.h>
39
40#ifdef RT_OS_FREEBSD
41# include <netinet/in.h> /* INADDR_NONE */
42#endif /* RT_OS_FREEBSD */
43
44#include "VirtualBoxImpl.h"
45
46// constructor / destructor
47/////////////////////////////////////////////////////////////////////////////
48
49HostNetworkInterface::HostNetworkInterface()
50 : mVirtualBox(NULL)
51{
52}
53
54HostNetworkInterface::~HostNetworkInterface()
55{
56}
57
58HRESULT HostNetworkInterface::FinalConstruct()
59{
60 return BaseFinalConstruct();
61}
62
63void HostNetworkInterface::FinalRelease()
64{
65 uninit();
66 BaseFinalRelease();
67}
68
69// public initializer/uninitializer for internal purposes only
70/////////////////////////////////////////////////////////////////////////////
71
72/**
73 * Initializes the host object.
74 *
75 * @returns COM result indicator
76 * @param aInterfaceName name of the network interface
77 * @param aShortName short name of the network interface
78 * @param aGuid GUID of the host network interface
79 * @param ifType interface type
80 */
81HRESULT HostNetworkInterface::init(Utf8Str aInterfaceName, Utf8Str aShortName, Guid aGuid, HostNetworkInterfaceType_T ifType)
82{
83 LogFlowThisFunc(("aInterfaceName={%s}, aGuid={%s}\n",
84 aInterfaceName.c_str(), aGuid.toString().c_str()));
85
86 ComAssertRet(!aInterfaceName.isEmpty(), E_INVALIDARG);
87 ComAssertRet(aGuid.isValid(), E_INVALIDARG);
88
89 /* Enclose the state transition NotReady->InInit->Ready */
90 AutoInitSpan autoInitSpan(this);
91 AssertReturn(autoInitSpan.isOk(), E_FAIL);
92
93 unconst(mInterfaceName) = aInterfaceName;
94#ifdef VBOX_WITH_HOSTNETIF_API
95 unconst(mNetworkName) = i_composeNetworkName(aShortName);
96#endif
97 unconst(mShortName) = aShortName;
98 unconst(mGuid) = aGuid;
99 mIfType = ifType;
100
101 /* Confirm a successful initialization */
102 autoInitSpan.setSucceeded();
103
104 return S_OK;
105}
106
107#ifdef VBOX_WITH_RESOURCE_USAGE_API
108
109void HostNetworkInterface::i_registerMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr)
110{
111 LogFlowThisFunc(("mShortName={%s}, mInterfaceName={%s}, mGuid={%s}, mSpeedMbits=%u\n",
112 mShortName.c_str(), mInterfaceName.c_str(), mGuid.toString().c_str(), m.speedMbits));
113 pm::CollectorHAL *hal = aCollector->getHAL();
114 /* Create sub metrics */
115 Utf8StrFmt strName("Net/%s", mShortName.c_str());
116 pm::SubMetric *networkLoadRx = new pm::SubMetric(strName + "/Load/Rx",
117 "Percentage of network interface receive bandwidth used.");
118 pm::SubMetric *networkLoadTx = new pm::SubMetric(strName + "/Load/Tx",
119 "Percentage of network interface transmit bandwidth used.");
120 pm::SubMetric *networkLinkSpeed = new pm::SubMetric(strName + "/LinkSpeed",
121 "Physical link speed.");
122
123 /* Create and register base metrics */
124 pm::BaseMetric *networkSpeed = new pm::HostNetworkSpeed(hal, objptr, strName + "/LinkSpeed",
125 Utf8Str(mShortName), Utf8Str(mInterfaceName),
126 m.speedMbits, networkLinkSpeed);
127 aCollector->registerBaseMetric(networkSpeed);
128 pm::BaseMetric *networkLoad = new pm::HostNetworkLoadRaw(hal, objptr, strName + "/Load",
129 Utf8Str(mShortName), Utf8Str(mInterfaceName),
130 m.speedMbits, networkLoadRx, networkLoadTx);
131 aCollector->registerBaseMetric(networkLoad);
132
133 aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed, 0));
134 aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed,
135 new pm::AggregateAvg()));
136 aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed,
137 new pm::AggregateMin()));
138 aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed,
139 new pm::AggregateMax()));
140
141 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx, 0));
142 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx,
143 new pm::AggregateAvg()));
144 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx,
145 new pm::AggregateMin()));
146 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx,
147 new pm::AggregateMax()));
148
149 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx, 0));
150 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx,
151 new pm::AggregateAvg()));
152 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx,
153 new pm::AggregateMin()));
154 aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx,
155 new pm::AggregateMax()));
156}
157
158void HostNetworkInterface::i_unregisterMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr)
159{
160 LogFlowThisFunc(("mShortName={%s}, mInterfaceName={%s}, mGuid={%s}\n",
161 mShortName.c_str(), mInterfaceName.c_str(), mGuid.toString().c_str()));
162 Utf8StrFmt name("Net/%s", mShortName.c_str());
163 aCollector->unregisterMetricsFor(objptr, name + "/*");
164 aCollector->unregisterBaseMetricsFor(objptr, name);
165}
166
167#endif /* VBOX_WITH_RESOURCE_USAGE_API */
168
169#ifdef VBOX_WITH_HOSTNETIF_API
170#if defined(RT_OS_WINDOWS)
171
172HRESULT HostNetworkInterface::saveAdapterConfigParameter(const char *szParamName, const Utf8Str &strValue)
173{
174 AssertReturn(mVirtualBox != NULL, E_POINTER);
175 return mVirtualBox->SetExtraData(BstrFmt("HostOnly/{%RTuuid}/%s", mGuid.raw(), szParamName).raw(), Bstr(strValue).raw());
176}
177
178HRESULT HostNetworkInterface::eraseAdapterConfigParameter(const char *szParamName)
179{
180 AssertReturn(mVirtualBox != NULL, E_POINTER);
181 return mVirtualBox->SetExtraData(BstrFmt("HostOnly/{%RTuuid}/%s", mGuid.raw(), szParamName).raw(), NULL);
182}
183
184HRESULT HostNetworkInterface::saveAdapterConfigIPv4Dhcp()
185{
186 HRESULT hrc = saveAdapterConfigParameter("IPAddress", "DHCP");
187 if (hrc == S_OK)
188 hrc = eraseAdapterConfigParameter("IPNetMask");
189 return hrc;
190}
191
192HRESULT HostNetworkInterface::saveAdapterConfigIPv4(ULONG addr, ULONG mask)
193{
194 HRESULT hrc = saveAdapterConfigParameter("IPAddress", Utf8StrFmt("%RTnaipv4", addr));
195 if (hrc == S_OK)
196 hrc = saveAdapterConfigParameter("IPNetMask", Utf8StrFmt("%RTnaipv4", mask));
197 return hrc;
198}
199
200HRESULT HostNetworkInterface::saveAdapterConfigIPv6(const Utf8Str& addr, ULONG prefix)
201{
202 HRESULT hrc = saveAdapterConfigParameter("IPV6Address", addr);
203 if (hrc == S_OK)
204 hrc = saveAdapterConfigParameter("IPV6PrefixLen", Utf8StrFmt("%u", prefix));
205 return hrc;
206}
207
208bool HostNetworkInterface::isInConfigFile(void)
209{
210 /* We care about host-only adapters only */
211 if (mIfType != HostNetworkInterfaceType_HostOnly)
212 return true;
213
214 Assert(mVirtualBox != NULL);
215 if (mVirtualBox == NULL)
216 return false; /* Trigger config update, which will fail with proper return code */
217 Bstr tmpName;
218 mVirtualBox->GetExtraData(BstrFmt("HostOnly/{%RTuuid}/Name", mGuid.raw()).raw(), tmpName.asOutParam());
219 return (tmpName.isNotEmpty() && tmpName == mInterfaceName);
220
221}
222
223HRESULT HostNetworkInterface::saveAdapterConfig(void)
224{
225 /* We care about host-only adapters only */
226 if (mIfType != HostNetworkInterfaceType_HostOnly)
227 return true;
228
229 HRESULT hrc = saveAdapterConfigParameter("Name", mInterfaceName.c_str());
230 if (FAILED(hrc))
231 return hrc;
232 if (m.dhcpEnabled)
233 hrc = saveAdapterConfigIPv4Dhcp();
234 else
235 hrc = saveAdapterConfigIPv4(m.IPAddress, m.networkMask);
236 if (SUCCEEDED(hrc))
237 hrc = saveAdapterConfigIPv6(m.IPV6Address.c_str(), m.IPV6NetworkMaskPrefixLength);
238 return hrc;
239}
240
241HRESULT HostNetworkInterface::i_updatePersistentConfig(void)
242{
243 if (mVirtualBox == NULL)
244 return E_POINTER;
245
246 HRESULT hrc = S_OK;
247 if (!isInConfigFile())
248 {
249 hrc = saveAdapterConfig();
250 }
251 return hrc;
252}
253
254#endif /* defined(RT_OS_WINDOWS) */
255
256HRESULT HostNetworkInterface::updateConfig()
257{
258 NETIFINFO info;
259 int rc = NetIfGetConfig(this, &info);
260 if (RT_SUCCESS(rc))
261 {
262 int iPrefixIPv6;
263
264 m.realIPAddress = m.IPAddress = info.IPAddress.u;
265 m.realNetworkMask = m.networkMask = info.IPNetMask.u;
266 m.dhcpEnabled = info.fDhcpEnabled;
267 if (info.IPv6Address.s.Lo || info.IPv6Address.s.Hi)
268 m.realIPV6Address = m.IPV6Address = Utf8StrFmt("%RTnaipv6", &info.IPv6Address);
269 else
270 m.realIPV6Address = m.IPV6Address = Utf8Str::Empty;
271 RTNetMaskToPrefixIPv6(&info.IPv6NetMask, &iPrefixIPv6);
272 m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = (ULONG)iPrefixIPv6;
273 m.hardwareAddress = Utf8StrFmt("%RTmac", &info.MACAddress);
274 AssertCompile((unsigned)NETIF_T_UNKNOWN == (unsigned)HostNetworkInterfaceMediumType_Unknown);
275 m.mediumType = (HostNetworkInterfaceMediumType_T)info.enmMediumType;
276 AssertCompile((unsigned)NETIF_S_UNKNOWN == (unsigned)HostNetworkInterfaceStatus_Unknown);
277 m.status = (HostNetworkInterfaceStatus_T)info.enmStatus;
278 m.speedMbits = info.uSpeedMbits;
279 m.wireless = info.fWireless;
280 return S_OK;
281 }
282 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
283}
284
285Utf8Str HostNetworkInterface::i_composeNetworkName(const Utf8Str aShortName)
286{
287 return Utf8Str("HostInterfaceNetworking-").append(aShortName);
288}
289/**
290 * Initializes the host object.
291 *
292 * @returns COM result indicator
293 * @param aInterfaceName name of the network interface
294 * @param aGuid GUID of the host network interface
295 */
296HRESULT HostNetworkInterface::init(Utf8Str aInterfaceName, HostNetworkInterfaceType_T ifType, PNETIFINFO pIf)
297{
298// LogFlowThisFunc(("aInterfaceName={%s}, aGuid={%s}\n",
299// aInterfaceName.c_str(), aGuid.toString().c_str()));
300
301// ComAssertRet(aInterfaceName, E_INVALIDARG);
302// ComAssertRet(aGuid.isValid(), E_INVALIDARG);
303 ComAssertRet(pIf, E_INVALIDARG);
304
305 /* Enclose the state transition NotReady->InInit->Ready */
306 AutoInitSpan autoInitSpan(this);
307 AssertReturn(autoInitSpan.isOk(), E_FAIL);
308
309 unconst(mInterfaceName) = aInterfaceName;
310 unconst(mGuid) = pIf->Uuid;
311 if (pIf->szShortName[0])
312 {
313 unconst(mNetworkName) = i_composeNetworkName(pIf->szShortName);
314 unconst(mShortName) = pIf->szShortName;
315 }
316 else
317 {
318 unconst(mNetworkName) = i_composeNetworkName(aInterfaceName);
319 unconst(mShortName) = aInterfaceName;
320 }
321 mIfType = ifType;
322
323 int iPrefixIPv6;
324
325 m.realIPAddress = m.IPAddress = pIf->IPAddress.u;
326 m.realNetworkMask = m.networkMask = pIf->IPNetMask.u;
327 if (pIf->IPv6Address.s.Lo || pIf->IPv6Address.s.Hi)
328 m.realIPV6Address = m.IPV6Address = Utf8StrFmt("%RTnaipv6", &pIf->IPv6Address);
329 else
330 m.realIPV6Address = m.IPV6Address = Utf8Str::Empty;
331 RTNetMaskToPrefixIPv6(&pIf->IPv6NetMask, &iPrefixIPv6);
332 m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = (ULONG)iPrefixIPv6;
333 m.dhcpEnabled = pIf->fDhcpEnabled;
334 m.hardwareAddress = Utf8StrFmt("%RTmac", &pIf->MACAddress);
335 AssertCompile((unsigned)NETIF_T_UNKNOWN == (unsigned)HostNetworkInterfaceMediumType_Unknown);
336 m.mediumType = (HostNetworkInterfaceMediumType_T)pIf->enmMediumType;
337 AssertCompile((unsigned)NETIF_S_UNKNOWN == (unsigned)HostNetworkInterfaceStatus_Unknown);
338 m.status = (HostNetworkInterfaceStatus_T)pIf->enmStatus;
339 m.speedMbits = pIf->uSpeedMbits;
340 m.wireless = pIf->fWireless;
341
342 /* Confirm a successful initialization */
343 autoInitSpan.setSucceeded();
344
345 return S_OK;
346}
347
348#endif /* VBOX_WITH_HOSTNETIF_API */
349
350// wrapped IHostNetworkInterface properties
351/////////////////////////////////////////////////////////////////////////////
352/**
353 * Returns the name of the host network interface.
354 *
355 * @returns COM status code
356 * @param aInterfaceName - Interface Name
357 */
358
359HRESULT HostNetworkInterface::getName(com::Utf8Str &aInterfaceName)
360{
361 aInterfaceName = mInterfaceName;
362 return S_OK;
363}
364
365/**
366 * Returns the short name of the host network interface.
367 *
368 * @returns COM status code
369 * @param aShortName Short Name
370 */
371
372HRESULT HostNetworkInterface::getShortName(com::Utf8Str &aShortName)
373{
374 aShortName = mShortName;
375
376 return S_OK;
377}
378
379/**
380 * Returns the GUID of the host network interface.
381 *
382 * @returns COM status code
383 * @param aGuid GUID
384 */
385HRESULT HostNetworkInterface::getId(com::Guid &aGuid)
386{
387 aGuid = mGuid;
388
389 return S_OK;
390}
391
392HRESULT HostNetworkInterface::getDHCPEnabled(BOOL *aDHCPEnabled)
393{
394 *aDHCPEnabled = m.dhcpEnabled;
395
396 return S_OK;
397}
398
399
400/**
401 * Returns the IP address of the host network interface.
402 *
403 * @returns COM status code
404 * @param aIPAddress Address name
405 */
406HRESULT HostNetworkInterface::getIPAddress(com::Utf8Str &aIPAddress)
407{
408 in_addr tmp;
409#if defined(RT_OS_WINDOWS)
410 tmp.S_un.S_addr = m.IPAddress;
411#else
412 tmp.s_addr = m.IPAddress;
413#endif
414 char *addr = inet_ntoa(tmp);
415 if (addr)
416 {
417 aIPAddress = addr;
418 return S_OK;
419 }
420
421 return E_FAIL;
422}
423
424/**
425 * Returns the netwok mask of the host network interface.
426 *
427 * @returns COM status code
428 * @param aNetworkMask name.
429 */
430HRESULT HostNetworkInterface::getNetworkMask(com::Utf8Str &aNetworkMask)
431{
432
433 in_addr tmp;
434#if defined(RT_OS_WINDOWS)
435 tmp.S_un.S_addr = m.networkMask;
436#else
437 tmp.s_addr = m.networkMask;
438#endif
439 char *addr = inet_ntoa(tmp);
440 if (addr)
441 {
442 aNetworkMask = Utf8Str(addr);
443 return S_OK;
444 }
445
446 return E_FAIL;
447}
448
449HRESULT HostNetworkInterface::getIPV6Supported(BOOL *aIPV6Supported)
450{
451#if defined(RT_OS_WINDOWS)
452 *aIPV6Supported = FALSE;
453#else
454 *aIPV6Supported = TRUE;
455#endif
456
457 return S_OK;
458}
459
460/**
461 * Returns the IP V6 address of the host network interface.
462 *
463 * @returns COM status code
464 * @param aIPV6Address
465 */
466HRESULT HostNetworkInterface::getIPV6Address(com::Utf8Str &aIPV6Address)
467{
468 aIPV6Address = m.IPV6Address;
469 return S_OK;
470}
471
472/**
473 * Returns the IP V6 network mask prefix length of the host network interface.
474 *
475 * @returns COM status code
476 * @param aIPV6NetworkMaskPrefixLength address of result pointer
477 */
478HRESULT HostNetworkInterface::getIPV6NetworkMaskPrefixLength(ULONG *aIPV6NetworkMaskPrefixLength)
479{
480 *aIPV6NetworkMaskPrefixLength = m.IPV6NetworkMaskPrefixLength;
481
482 return S_OK;
483}
484
485/**
486 * Returns the hardware address of the host network interface.
487 *
488 * @returns COM status code
489 * @param aHardwareAddress hardware address
490 */
491HRESULT HostNetworkInterface::getHardwareAddress(com::Utf8Str &aHardwareAddress)
492{
493 aHardwareAddress = m.hardwareAddress;
494 return S_OK;
495}
496
497/**
498 * Returns the encapsulation protocol type of the host network interface.
499 *
500 * @returns COM status code
501 * @param aType address of result pointer
502 */
503HRESULT HostNetworkInterface::getMediumType(HostNetworkInterfaceMediumType_T *aType)
504{
505 *aType = m.mediumType;
506
507 return S_OK;
508}
509
510/**
511 * Returns the current state of the host network interface.
512 *
513 * @returns COM status code
514 * @param aStatus address of result pointer
515 */
516HRESULT HostNetworkInterface::getStatus(HostNetworkInterfaceStatus_T *aStatus)
517{
518 *aStatus = m.status;
519
520 return S_OK;
521}
522
523/**
524 * Returns network interface type
525 *
526 * @returns COM status code
527 * @param aType address of result pointer
528 */
529HRESULT HostNetworkInterface::getInterfaceType(HostNetworkInterfaceType_T *aType)
530{
531 *aType = mIfType;
532
533 return S_OK;
534
535}
536
537HRESULT HostNetworkInterface::getNetworkName(com::Utf8Str &aNetworkName)
538{
539 aNetworkName = mNetworkName;
540
541 return S_OK;
542}
543
544HRESULT HostNetworkInterface::getWireless(BOOL *aWireless)
545{
546 *aWireless = m.wireless;
547
548 return S_OK;
549}
550
551HRESULT HostNetworkInterface::enableStaticIPConfig(const com::Utf8Str &aIPAddress,
552 const com::Utf8Str &aNetworkMask)
553{
554#ifndef VBOX_WITH_HOSTNETIF_API
555 RT_NOREF(aIPAddress, aNetworkMask);
556 return E_NOTIMPL;
557#else
558 HRESULT hrc;
559
560 if (aIPAddress.isEmpty())
561 {
562 if (m.IPAddress)
563 {
564 int rc = NetIfEnableStaticIpConfig(mVirtualBox, this, m.IPAddress, 0, 0);
565 if (RT_SUCCESS(rc))
566 {
567 m.realIPAddress = 0;
568#if defined(RT_OS_WINDOWS)
569 eraseAdapterConfigParameter("IPAddress");
570 eraseAdapterConfigParameter("IPNetMask");
571#else /* !defined(RT_OS_WINDOWS) */
572 if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPAddress",
573 mInterfaceName.c_str()).raw(), NULL)))
574 return E_FAIL;
575 if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPNetMask",
576 mInterfaceName.c_str()).raw(), NULL)))
577 return E_FAIL;
578#endif /* !defined(RT_OS_WINDOWS) */
579 return S_OK;
580 }
581 }
582 else
583 return S_OK;
584 }
585
586 ULONG ip, mask;
587 ip = inet_addr(aIPAddress.c_str());
588 if (ip != INADDR_NONE)
589 {
590 if (aNetworkMask.isEmpty())
591 mask = 0xFFFFFF;
592 else
593 mask = inet_addr(aNetworkMask.c_str());
594 if (mask != INADDR_NONE)
595 {
596 if (m.realIPAddress == ip && m.realNetworkMask == mask)
597 return S_OK;
598 int rc = NetIfEnableStaticIpConfig(mVirtualBox, this, m.IPAddress, ip, mask);
599 if (RT_SUCCESS(rc))
600 {
601 m.realIPAddress = ip;
602 m.realNetworkMask = mask;
603#if defined(RT_OS_WINDOWS)
604 saveAdapterConfigIPv4(ip, mask);
605#else /* !defined(RT_OS_WINDOWS) */
606 if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPAddress",
607 mInterfaceName.c_str()).raw(),
608 Bstr(aIPAddress).raw())))
609 return E_FAIL;
610 if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPNetMask",
611 mInterfaceName.c_str()).raw(),
612 Bstr(aNetworkMask).raw())))
613 return E_FAIL;
614#endif /* !defined(RT_OS_WINDOWS) */
615 return S_OK;
616 }
617 else
618 {
619 LogRel(("Failed to EnableStaticIpConfig with rc=%Rrc\n", rc));
620 /* Global::vboxStatusCodeToCOM assert things we can guarantee */
621 switch (rc)
622 {
623 case VERR_NOT_IMPLEMENTED:
624 hrc = E_NOTIMPL;
625 break;
626 case VERR_ACCESS_DENIED:
627 hrc = E_ACCESSDENIED;
628 break;
629 default:
630 hrc = E_FAIL;
631 break;
632 }
633 return hrc;
634 }
635
636 }
637 }
638 return E_FAIL;
639#endif
640}
641
642HRESULT HostNetworkInterface::enableStaticIPConfigV6(const com::Utf8Str &aIPV6Address,
643 ULONG aIPV6NetworkMaskPrefixLength)
644{
645#ifndef VBOX_WITH_HOSTNETIF_API
646 RT_NOREF(aIPV6Address, aIPV6NetworkMaskPrefixLength);
647 return E_NOTIMPL;
648#else
649 if (aIPV6NetworkMaskPrefixLength > 128)
650 return mVirtualBox->setErrorBoth(E_INVALIDARG, VERR_INVALID_PARAMETER,
651 tr("Invalid IPv6 prefix length"));
652
653 HRESULT hrc;
654 int rc;
655
656 RTNETADDRIPV6 AddrOld, AddrNew;
657 char *pszZoneIgnored;
658 bool fAddrChanged;
659
660 rc = RTNetStrToIPv6Addr(aIPV6Address.c_str(), &AddrNew, &pszZoneIgnored);
661 if (RT_FAILURE(rc))
662 {
663 return mVirtualBox->setErrorBoth(E_INVALIDARG, rc, tr("Invalid IPv6 address"));
664 }
665
666 rc = RTNetStrToIPv6Addr(com::Utf8Str(m.realIPV6Address).c_str(), &AddrOld, &pszZoneIgnored);
667 if (RT_SUCCESS(rc))
668 {
669 fAddrChanged = (AddrNew.s.Lo != AddrOld.s.Lo || AddrNew.s.Hi != AddrOld.s.Hi);
670 }
671 else
672 {
673 fAddrChanged = true;
674 }
675
676 if ( fAddrChanged
677 || m.realIPV6PrefixLength != aIPV6NetworkMaskPrefixLength)
678 {
679 if (aIPV6NetworkMaskPrefixLength == 0)
680 aIPV6NetworkMaskPrefixLength = 64;
681 rc = NetIfEnableStaticIpConfigV6(mVirtualBox, this, m.IPV6Address.c_str(),
682 aIPV6Address.c_str(),
683 aIPV6NetworkMaskPrefixLength);
684 if (RT_FAILURE(rc))
685 {
686 LogRel(("Failed to EnableStaticIpConfigV6 with rc=%Rrc\n", rc));
687 /* Global::vboxStatusCodeToCOM assert things we can guarantee */
688 switch (rc)
689 {
690 case VERR_NOT_IMPLEMENTED:
691 hrc = E_NOTIMPL;
692 break;
693 case VERR_ACCESS_DENIED:
694 hrc = E_ACCESSDENIED;
695 break;
696 default:
697 hrc = E_FAIL;
698 break;
699 }
700 return hrc;
701 }
702 else
703 {
704 m.realIPV6Address = aIPV6Address;
705 m.realIPV6PrefixLength = aIPV6NetworkMaskPrefixLength;
706#if defined(RT_OS_WINDOWS)
707 saveAdapterConfigIPv6(Bstr(aIPV6Address).raw(), aIPV6NetworkMaskPrefixLength);
708#else /* !defined(RT_OS_WINDOWS) */
709 if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPV6Address",
710 mInterfaceName.c_str()).raw(),
711 Bstr(aIPV6Address).raw())))
712 return E_FAIL;
713 if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask",
714 mInterfaceName.c_str()).raw(),
715 BstrFmt("%u", aIPV6NetworkMaskPrefixLength).raw())))
716#endif /* !defined(RT_OS_WINDOWS) */
717 return E_FAIL;
718 }
719
720 }
721 return S_OK;
722#endif
723}
724
725HRESULT HostNetworkInterface::enableDynamicIPConfig()
726{
727#ifndef VBOX_WITH_HOSTNETIF_API
728 return E_NOTIMPL;
729#else
730 int rc = NetIfEnableDynamicIpConfig(mVirtualBox, this);
731 if (RT_FAILURE(rc))
732 {
733 LogRel(("Failed to EnableDynamicIpConfig with rc=%Rrc\n", rc));
734 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
735 }
736 return S_OK;
737#endif
738}
739
740HRESULT HostNetworkInterface::dHCPRediscover()
741{
742#ifndef VBOX_WITH_HOSTNETIF_API
743 return E_NOTIMPL;
744#else
745 int rc = NetIfDhcpRediscover(mVirtualBox, this);
746 if (RT_FAILURE(rc))
747 {
748 LogRel(("Failed to DhcpRediscover with rc=%Rrc\n", rc));
749 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
750 }
751 return S_OK;
752#endif
753}
754
755HRESULT HostNetworkInterface::i_setVirtualBox(VirtualBox *pVirtualBox)
756{
757 AutoCaller autoCaller(this);
758 if (FAILED(autoCaller.rc())) return autoCaller.rc();
759
760 AssertReturn(mVirtualBox != pVirtualBox, S_OK);
761
762 unconst(mVirtualBox) = pVirtualBox;
763
764#if !defined(RT_OS_WINDOWS)
765 /* If IPv4 address hasn't been initialized */
766 if (m.IPAddress == 0 && mIfType == HostNetworkInterfaceType_HostOnly)
767 {
768 Bstr tmpAddr, tmpMask;
769 HRESULT hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress",
770 mInterfaceName.c_str()).raw(),
771 tmpAddr.asOutParam());
772 if (FAILED(hrc) || tmpAddr.isEmpty())
773 tmpAddr = getDefaultIPv4Address(mInterfaceName);
774
775 hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask",
776 mInterfaceName.c_str()).raw(),
777 tmpMask.asOutParam());
778 if (FAILED(hrc) || tmpMask.isEmpty())
779 tmpMask = Bstr(VBOXNET_IPV4MASK_DEFAULT);
780
781 m.IPAddress = inet_addr(Utf8Str(tmpAddr).c_str());
782 m.networkMask = inet_addr(Utf8Str(tmpMask).c_str());
783 }
784
785 if (m.IPV6Address.isEmpty())
786 {
787 Bstr bstrIPV4Addr;
788 Bstr tmpPrefixLen;
789 HRESULT hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address",
790 mInterfaceName.c_str()).raw(),
791 bstrIPV4Addr.asOutParam());
792 if (SUCCEEDED(hrc))
793 {
794 m.IPV6Address = bstrIPV4Addr;
795 if (!m.IPV6Address.isEmpty())
796 {
797 hrc = mVirtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6PrefixLen",
798 mInterfaceName.c_str()).raw(),
799 tmpPrefixLen.asOutParam());
800 if (SUCCEEDED(hrc) && !tmpPrefixLen.isEmpty())
801 m.IPV6NetworkMaskPrefixLength = Utf8Str(tmpPrefixLen).toUInt32();
802 else
803 m.IPV6NetworkMaskPrefixLength = 64;
804 }
805 }
806 }
807#endif
808
809 return S_OK;
810}
811
812/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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