VirtualBox

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

Last change on this file since 36986 was 36057, checked in by vboxsync, 14 years ago

Main/NetIf: Fixed host-only interface creation failure on Windows (#3873)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.4 KB
Line 
1/* $Id: HostNetworkInterfaceImpl.cpp 36057 2011-02-22 20:56:44Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2008 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include "HostNetworkInterfaceImpl.h"
21#include "AutoCaller.h"
22#include "Logging.h"
23#include "netif.h"
24
25#include <iprt/cpp/utils.h>
26
27#ifdef RT_OS_FREEBSD
28# include <netinet/in.h> /* INADDR_NONE */
29#endif /* RT_OS_FREEBSD */
30
31// constructor / destructor
32/////////////////////////////////////////////////////////////////////////////
33
34HostNetworkInterface::HostNetworkInterface()
35 : mVBox(NULL)
36{
37}
38
39HostNetworkInterface::~HostNetworkInterface()
40{
41}
42
43HRESULT HostNetworkInterface::FinalConstruct()
44{
45 return BaseFinalConstruct();
46}
47
48void HostNetworkInterface::FinalRelease()
49{
50 uninit ();
51 BaseFinalRelease();
52}
53
54// public initializer/uninitializer for internal purposes only
55/////////////////////////////////////////////////////////////////////////////
56
57/**
58 * Initializes the host object.
59 *
60 * @returns COM result indicator
61 * @param aInterfaceName name of the network interface
62 * @param aGuid GUID of the host network interface
63 */
64HRESULT HostNetworkInterface::init(Bstr aInterfaceName, Guid aGuid, HostNetworkInterfaceType_T ifType)
65{
66 LogFlowThisFunc(("aInterfaceName={%ls}, aGuid={%s}\n",
67 aInterfaceName.raw(), aGuid.toString().c_str()));
68
69 ComAssertRet(!aInterfaceName.isEmpty(), E_INVALIDARG);
70 ComAssertRet(!aGuid.isEmpty(), E_INVALIDARG);
71
72 /* Enclose the state transition NotReady->InInit->Ready */
73 AutoInitSpan autoInitSpan(this);
74 AssertReturn(autoInitSpan.isOk(), E_FAIL);
75
76 unconst(mInterfaceName) = aInterfaceName;
77 unconst(mGuid) = aGuid;
78 mIfType = ifType;
79
80 /* Confirm a successful initialization */
81 autoInitSpan.setSucceeded();
82
83 return S_OK;
84}
85
86#ifdef VBOX_WITH_HOSTNETIF_API
87
88HRESULT HostNetworkInterface::updateConfig ()
89{
90 NETIFINFO info;
91 int rc = NetIfGetConfig(this, &info);
92 if (RT_SUCCESS(rc))
93 {
94 m.realIPAddress = m.IPAddress = info.IPAddress.u;
95 m.realNetworkMask = m.networkMask = info.IPNetMask.u;
96 m.dhcpEnabled = info.bDhcpEnabled;
97 m.realIPV6Address = m.IPV6Address = composeIPv6Address(&info.IPv6Address);
98 m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = composeIPv6PrefixLenghFromAddress(&info.IPv6NetMask);
99 m.hardwareAddress = composeHardwareAddress(&info.MACAddress);
100#ifdef RT_OS_WINDOWS
101 m.mediumType = (HostNetworkInterfaceMediumType)info.enmMediumType;
102 m.status = (HostNetworkInterfaceStatus)info.enmStatus;
103#else /* !RT_OS_WINDOWS */
104 m.mediumType = info.enmMediumType;
105 m.status = info.enmStatus;
106
107#endif /* !RT_OS_WINDOWS */
108 return S_OK;
109 }
110 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
111}
112
113/**
114 * Initializes the host object.
115 *
116 * @returns COM result indicator
117 * @param aInterfaceName name of the network interface
118 * @param aGuid GUID of the host network interface
119 */
120HRESULT HostNetworkInterface::init (Bstr aInterfaceName, HostNetworkInterfaceType_T ifType, PNETIFINFO pIf)
121{
122// LogFlowThisFunc(("aInterfaceName={%ls}, aGuid={%s}\n",
123// aInterfaceName.raw(), aGuid.toString().raw()));
124
125// ComAssertRet(aInterfaceName, E_INVALIDARG);
126// ComAssertRet(!aGuid.isEmpty(), E_INVALIDARG);
127 ComAssertRet(pIf, E_INVALIDARG);
128
129 /* Enclose the state transition NotReady->InInit->Ready */
130 AutoInitSpan autoInitSpan(this);
131 AssertReturn(autoInitSpan.isOk(), E_FAIL);
132
133 unconst(mInterfaceName) = aInterfaceName;
134 unconst(mGuid) = pIf->Uuid;
135 mIfType = ifType;
136
137 m.realIPAddress = m.IPAddress = pIf->IPAddress.u;
138 m.realNetworkMask = m.networkMask = pIf->IPNetMask.u;
139 m.realIPV6Address = m.IPV6Address = composeIPv6Address(&pIf->IPv6Address);
140 m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = composeIPv6PrefixLenghFromAddress(&pIf->IPv6NetMask);
141 m.dhcpEnabled = pIf->bDhcpEnabled;
142 m.hardwareAddress = composeHardwareAddress(&pIf->MACAddress);
143#ifdef RT_OS_WINDOWS
144 m.mediumType = (HostNetworkInterfaceMediumType)pIf->enmMediumType;
145 m.status = (HostNetworkInterfaceStatus)pIf->enmStatus;
146#else /* !RT_OS_WINDOWS */
147 m.mediumType = pIf->enmMediumType;
148 m.status = pIf->enmStatus;
149#endif /* !RT_OS_WINDOWS */
150
151 /* Confirm a successful initialization */
152 autoInitSpan.setSucceeded();
153
154 return S_OK;
155}
156#endif
157
158// IHostNetworkInterface properties
159/////////////////////////////////////////////////////////////////////////////
160
161/**
162 * Returns the name of the host network interface.
163 *
164 * @returns COM status code
165 * @param aInterfaceName address of result pointer
166 */
167STDMETHODIMP HostNetworkInterface::COMGETTER(Name) (BSTR *aInterfaceName)
168{
169 CheckComArgOutPointerValid(aInterfaceName);
170
171 AutoCaller autoCaller(this);
172 if (FAILED(autoCaller.rc())) return autoCaller.rc();
173
174 mInterfaceName.cloneTo(aInterfaceName);
175
176 return S_OK;
177}
178
179/**
180 * Returns the GUID of the host network interface.
181 *
182 * @returns COM status code
183 * @param aGuid address of result pointer
184 */
185STDMETHODIMP HostNetworkInterface::COMGETTER(Id) (BSTR *aGuid)
186{
187 CheckComArgOutPointerValid(aGuid);
188
189 AutoCaller autoCaller(this);
190 if (FAILED(autoCaller.rc())) return autoCaller.rc();
191
192 mGuid.toUtf16().cloneTo(aGuid);
193
194 return S_OK;
195}
196
197STDMETHODIMP HostNetworkInterface::COMGETTER(DhcpEnabled) (BOOL *aDhcpEnabled)
198{
199 CheckComArgOutPointerValid(aDhcpEnabled);
200
201 AutoCaller autoCaller(this);
202 if (FAILED(autoCaller.rc())) return autoCaller.rc();
203
204 *aDhcpEnabled = m.dhcpEnabled;
205
206 return S_OK;
207}
208
209
210/**
211 * Returns the IP address of the host network interface.
212 *
213 * @returns COM status code
214 * @param aIPAddress address of result pointer
215 */
216STDMETHODIMP HostNetworkInterface::COMGETTER(IPAddress) (BSTR *aIPAddress)
217{
218 CheckComArgOutPointerValid(aIPAddress);
219
220 AutoCaller autoCaller(this);
221 if (FAILED(autoCaller.rc())) return autoCaller.rc();
222
223 if (m.IPAddress == 0)
224 {
225 getDefaultIPv4Address(mInterfaceName).detachTo(aIPAddress);
226 return S_OK;
227 }
228
229 in_addr tmp;
230#if defined(RT_OS_WINDOWS)
231 tmp.S_un.S_addr = m.IPAddress;
232#else
233 tmp.s_addr = m.IPAddress;
234#endif
235 char *addr = inet_ntoa(tmp);
236 if (addr)
237 {
238 Bstr(addr).detachTo(aIPAddress);
239 return S_OK;
240 }
241
242 return E_FAIL;
243}
244
245/**
246 * Returns the netwok mask of the host network interface.
247 *
248 * @returns COM status code
249 * @param aNetworkMask address of result pointer
250 */
251STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkMask) (BSTR *aNetworkMask)
252{
253 CheckComArgOutPointerValid(aNetworkMask);
254
255 AutoCaller autoCaller(this);
256 if (FAILED(autoCaller.rc())) return autoCaller.rc();
257
258 if (m.networkMask == 0)
259 {
260 Bstr(VBOXNET_IPV4MASK_DEFAULT).detachTo(aNetworkMask);
261 return S_OK;
262 }
263
264 in_addr tmp;
265#if defined(RT_OS_WINDOWS)
266 tmp.S_un.S_addr = m.networkMask;
267#else
268 tmp.s_addr = m.networkMask;
269#endif
270 char *addr = inet_ntoa(tmp);
271 if (addr)
272 {
273 Bstr(addr).detachTo(aNetworkMask);
274 return S_OK;
275 }
276
277 return E_FAIL;
278}
279
280STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Supported) (BOOL *aIPV6Supported)
281{
282 CheckComArgOutPointerValid(aIPV6Supported);
283#if defined(RT_OS_WINDOWS)
284 *aIPV6Supported = FALSE;
285#else
286 *aIPV6Supported = TRUE;
287#endif
288
289 return S_OK;
290}
291
292/**
293 * Returns the IP V6 address of the host network interface.
294 *
295 * @returns COM status code
296 * @param aIPV6Address address of result pointer
297 */
298STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Address) (BSTR *aIPV6Address)
299{
300 CheckComArgOutPointerValid(aIPV6Address);
301
302 AutoCaller autoCaller(this);
303 if (FAILED(autoCaller.rc())) return autoCaller.rc();
304
305 m.IPV6Address.cloneTo(aIPV6Address);
306
307 return S_OK;
308}
309
310/**
311 * Returns the IP V6 network mask of the host network interface.
312 *
313 * @returns COM status code
314 * @param aIPV6Mask address of result pointer
315 */
316STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6NetworkMaskPrefixLength) (ULONG *aIPV6NetworkMaskPrefixLength)
317{
318 CheckComArgOutPointerValid(aIPV6NetworkMaskPrefixLength);
319
320 AutoCaller autoCaller(this);
321 if (FAILED(autoCaller.rc())) return autoCaller.rc();
322
323 *aIPV6NetworkMaskPrefixLength = m.IPV6NetworkMaskPrefixLength;
324
325 return S_OK;
326}
327
328/**
329 * Returns the hardware address of the host network interface.
330 *
331 * @returns COM status code
332 * @param aHardwareAddress address of result pointer
333 */
334STDMETHODIMP HostNetworkInterface::COMGETTER(HardwareAddress) (BSTR *aHardwareAddress)
335{
336 CheckComArgOutPointerValid(aHardwareAddress);
337
338 AutoCaller autoCaller(this);
339 if (FAILED(autoCaller.rc())) return autoCaller.rc();
340
341 m.hardwareAddress.cloneTo(aHardwareAddress);
342
343 return S_OK;
344}
345
346/**
347 * Returns the encapsulation protocol type of the host network interface.
348 *
349 * @returns COM status code
350 * @param aType address of result pointer
351 */
352STDMETHODIMP HostNetworkInterface::COMGETTER(MediumType) (HostNetworkInterfaceMediumType_T *aType)
353{
354 CheckComArgOutPointerValid(aType);
355
356 AutoCaller autoCaller(this);
357 if (FAILED(autoCaller.rc())) return autoCaller.rc();
358
359 *aType = m.mediumType;
360
361 return S_OK;
362}
363
364/**
365 * Returns the current state of the host network interface.
366 *
367 * @returns COM status code
368 * @param aStatus address of result pointer
369 */
370STDMETHODIMP HostNetworkInterface::COMGETTER(Status) (HostNetworkInterfaceStatus_T *aStatus)
371{
372 CheckComArgOutPointerValid(aStatus);
373
374 AutoCaller autoCaller(this);
375 if (FAILED(autoCaller.rc())) return autoCaller.rc();
376
377 *aStatus = m.status;
378
379 return S_OK;
380}
381
382/**
383 * Returns network interface type
384 *
385 * @returns COM status code
386 * @param aType address of result pointer
387 */
388STDMETHODIMP HostNetworkInterface::COMGETTER(InterfaceType) (HostNetworkInterfaceType_T *aType)
389{
390 CheckComArgOutPointerValid(aType);
391
392 AutoCaller autoCaller(this);
393 if (FAILED(autoCaller.rc())) return autoCaller.rc();
394
395 *aType = mIfType;
396
397 return S_OK;
398
399}
400
401STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkName) (BSTR *aNetworkName)
402{
403 AutoCaller autoCaller(this);
404 if (FAILED(autoCaller.rc())) return autoCaller.rc();
405
406 Utf8Str utf8Name("HostInterfaceNetworking-");
407 utf8Name.append(Utf8Str(mInterfaceName)) ;
408 Bstr netName(utf8Name);
409 netName.detachTo(aNetworkName);
410
411 return S_OK;
412}
413
414STDMETHODIMP HostNetworkInterface::EnableStaticIpConfig (IN_BSTR aIPAddress, IN_BSTR aNetMask)
415{
416#ifndef VBOX_WITH_HOSTNETIF_API
417 return E_NOTIMPL;
418#else
419 AutoCaller autoCaller(this);
420 if (FAILED(autoCaller.rc())) return autoCaller.rc();
421
422 if (Bstr(aIPAddress).isEmpty())
423 {
424 if (m.IPAddress)
425 {
426 int rc = NetIfEnableStaticIpConfig(mVBox, this, m.IPAddress, 0, 0);
427 if (RT_SUCCESS(rc))
428 {
429 m.realIPAddress = 0;
430 if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), NULL)))
431 return E_FAIL;
432 if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), NULL)))
433 return E_FAIL;
434 return S_OK;
435 }
436 }
437 else
438 return S_OK;
439 }
440
441 ULONG ip, mask;
442 ip = inet_addr(Utf8Str(aIPAddress).c_str());
443 if (ip != INADDR_NONE)
444 {
445 if (Bstr(aNetMask).isEmpty())
446 mask = 0xFFFFFF;
447 else
448 mask = inet_addr(Utf8Str(aNetMask).c_str());
449 if (mask != INADDR_NONE)
450 {
451 if (m.realIPAddress == ip && m.realNetworkMask == mask)
452 return S_OK;
453 int rc = NetIfEnableStaticIpConfig(mVBox, this, m.IPAddress, ip, mask);
454 if (RT_SUCCESS(rc))
455 {
456 m.realIPAddress = ip;
457 m.realNetworkMask = mask;
458 if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), Bstr(aIPAddress).raw())))
459 return E_FAIL;
460 if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), Bstr(aNetMask).raw())))
461 return E_FAIL;
462 return S_OK;
463 }
464 else
465 {
466 LogRel(("Failed to EnableStaticIpConfig with rc=%Rrc\n", rc));
467 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
468 }
469
470 }
471 }
472 return E_FAIL;
473#endif
474}
475
476STDMETHODIMP HostNetworkInterface::EnableStaticIpConfigV6 (IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
477{
478#ifndef VBOX_WITH_HOSTNETIF_API
479 return E_NOTIMPL;
480#else
481 if (!aIPV6Address)
482 return E_INVALIDARG;
483 if (aIPV6MaskPrefixLength > 128)
484 return E_INVALIDARG;
485
486 AutoCaller autoCaller(this);
487 if (FAILED(autoCaller.rc())) return autoCaller.rc();
488
489 int rc = S_OK;
490 if (m.realIPV6Address != aIPV6Address || m.realIPV6PrefixLength != aIPV6MaskPrefixLength)
491 {
492 if (aIPV6MaskPrefixLength == 0)
493 aIPV6MaskPrefixLength = 64;
494 rc = NetIfEnableStaticIpConfigV6(mVBox, this, m.IPV6Address.raw(), aIPV6Address, aIPV6MaskPrefixLength);
495 if (RT_FAILURE(rc))
496 {
497 LogRel(("Failed to EnableStaticIpConfigV6 with rc=%Rrc\n", rc));
498 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
499 }
500 else
501 {
502 m.realIPV6Address = aIPV6Address;
503 m.realIPV6PrefixLength = aIPV6MaskPrefixLength;
504 if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), Bstr(aIPV6Address).raw())))
505 return E_FAIL;
506 if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6NetMask", mInterfaceName.raw()).raw(),
507 BstrFmt("%u", aIPV6MaskPrefixLength).raw())))
508 return E_FAIL;
509 }
510
511 }
512 return S_OK;
513#endif
514}
515
516STDMETHODIMP HostNetworkInterface::EnableDynamicIpConfig ()
517{
518#ifndef VBOX_WITH_HOSTNETIF_API
519 return E_NOTIMPL;
520#else
521 AutoCaller autoCaller(this);
522 if (FAILED(autoCaller.rc())) return autoCaller.rc();
523
524 int rc = NetIfEnableDynamicIpConfig(mVBox, this);
525 if (RT_FAILURE(rc))
526 {
527 LogRel(("Failed to EnableDynamicIpConfig with rc=%Rrc\n", rc));
528 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
529 }
530 return S_OK;
531#endif
532}
533
534STDMETHODIMP HostNetworkInterface::DhcpRediscover ()
535{
536#ifndef VBOX_WITH_HOSTNETIF_API
537 return E_NOTIMPL;
538#else
539 AutoCaller autoCaller(this);
540 if (FAILED(autoCaller.rc())) return autoCaller.rc();
541
542 int rc = NetIfDhcpRediscover(mVBox, this);
543 if (RT_FAILURE(rc))
544 {
545 LogRel(("Failed to DhcpRediscover with rc=%Rrc\n", rc));
546 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
547 }
548 return S_OK;
549#endif
550}
551
552HRESULT HostNetworkInterface::setVirtualBox(VirtualBox *pVBox)
553{
554 HRESULT hrc;
555 AutoCaller autoCaller(this);
556 if (FAILED(autoCaller.rc())) return autoCaller.rc();
557 unconst(mVBox) = pVBox;
558
559#if !defined(RT_OS_WINDOWS)
560 /* If IPv4 address hasn't been initialized */
561 if (m.IPAddress == 0 && mIfType == HostNetworkInterfaceType_HostOnly)
562 {
563 Bstr tmpAddr, tmpMask;
564 hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), tmpAddr.asOutParam());
565 hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), tmpMask.asOutParam());
566 if (tmpAddr.isEmpty())
567 {
568 tmpAddr = getDefaultIPv4Address(mInterfaceName);
569 /*
570 * We need to write the default IP address and mask to extra data now,
571 * so the interface gets re-created after vboxnetadp.ko reload.
572 * Note that we avoid calling EnableStaticIpConfig since it would
573 * change the address on host's interface as well and we want to
574 * postpone the change until VM actually starts.
575 */
576 hrc = mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress",
577 mInterfaceName.raw()).raw(),
578 tmpAddr.raw());
579 ComAssertComRCRet(hrc, hrc);
580 }
581
582 if (tmpMask.isEmpty())
583 {
584 tmpMask = Bstr(VBOXNET_IPV4MASK_DEFAULT);
585 hrc = mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask",
586 mInterfaceName.raw()).raw(),
587 Bstr(VBOXNET_IPV4MASK_DEFAULT).raw());
588 ComAssertComRCRet(hrc, hrc);
589 }
590 m.IPAddress = inet_addr(Utf8Str(tmpAddr).c_str());
591 m.networkMask = inet_addr(Utf8Str(tmpMask).c_str());
592 }
593
594 if (m.IPV6Address.isEmpty())
595 {
596 Bstr tmpPrefixLen;
597 hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), m.IPV6Address.asOutParam());
598 if (!m.IPV6Address.isEmpty())
599 {
600 hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6PrefixLen", mInterfaceName.raw()).raw(), tmpPrefixLen.asOutParam());
601 if (SUCCEEDED(hrc) && !tmpPrefixLen.isEmpty())
602 m.IPV6NetworkMaskPrefixLength = Utf8Str(tmpPrefixLen).toUInt32();
603 else
604 m.IPV6NetworkMaskPrefixLength = 64;
605 }
606 }
607#endif
608
609 return S_OK;
610}
611
612/* 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