1
/* $Id: NetworkAdapterImpl.cpp $ */
3
* Implementation of INetworkAdaptor in VBoxSVC.
7
* Copyright (C) 2006-2010 Oracle Corporation
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18
#include "NetworkAdapterImpl.h"
19
#include "NATEngineImpl.h"
20
#include "AutoCaller.h"
22
#include "MachineImpl.h"
23
#include "GuestOSTypeImpl.h"
25
#include <iprt/string.h>
26
#include <iprt/cpp/utils.h>
29
#include <VBox/settings.h>
31
#include "AutoStateDep.h"
33
// constructor / destructor
34
////////////////////////////////////////////////////////////////////////////////
36
NetworkAdapter::NetworkAdapter()
41
NetworkAdapter::~NetworkAdapter()
45
HRESULT NetworkAdapter::FinalConstruct()
51
void NetworkAdapter::FinalRelease()
56
// public initializer/uninitializer for internal purposes only
57
////////////////////////////////////////////////////////////////////////////////
60
* Initializes the network adapter object.
62
* @param aParent Handle of the parent object.
64
HRESULT NetworkAdapter::init(Machine *aParent, ULONG aSlot)
66
LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
68
ComAssertRet(aParent, E_INVALIDARG);
69
ComAssertRet(aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
71
/* Enclose the state transition NotReady->InInit->Ready */
72
AutoInitSpan autoInitSpan(this);
73
AssertReturn(autoInitSpan.isOk(), E_FAIL);
75
unconst(mParent) = aParent;
76
unconst(mNATEngine).createObject();
77
mNATEngine->init(aParent);
78
/* mPeer is left null */
87
/* default to Am79C973 */
88
mData->mAdapterType = NetworkAdapterType_Am79C973;
90
/* generate the MAC address early to guarantee it is the same both after
91
* changing some other property (i.e. after mData.backup()) and after the
92
* subsequent mData.rollback(). */
95
/* Confirm a successful initialization */
96
autoInitSpan.setSucceeded();
102
* Initializes the network adapter object given another network adapter object
103
* (a kind of copy constructor). This object shares data with
104
* the object passed as an argument.
106
* @note This object must be destroyed before the original object
107
* it shares data with is destroyed.
109
* @note Locks @a aThat object for reading.
111
HRESULT NetworkAdapter::init(Machine *aParent, NetworkAdapter *aThat)
113
LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
115
ComAssertRet(aParent && aThat, E_INVALIDARG);
117
/* Enclose the state transition NotReady->InInit->Ready */
118
AutoInitSpan autoInitSpan(this);
119
AssertReturn(autoInitSpan.isOk(), E_FAIL);
121
unconst(mParent) = aParent;
122
unconst(mPeer) = aThat;
123
unconst(mNATEngine).createObject();
124
mNATEngine->init(aParent, aThat->mNATEngine);
126
AutoCaller thatCaller (aThat);
127
AssertComRCReturnRC(thatCaller.rc());
129
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
130
mData.share (aThat->mData);
132
/* Confirm a successful initialization */
133
autoInitSpan.setSucceeded();
139
* Initializes the guest object given another guest object
140
* (a kind of copy constructor). This object makes a private copy of data
141
* of the original object passed as an argument.
143
* @note Locks @a aThat object for reading.
145
HRESULT NetworkAdapter::initCopy(Machine *aParent, NetworkAdapter *aThat)
147
LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
149
ComAssertRet(aParent && aThat, E_INVALIDARG);
151
/* Enclose the state transition NotReady->InInit->Ready */
152
AutoInitSpan autoInitSpan(this);
153
AssertReturn(autoInitSpan.isOk(), E_FAIL);
155
unconst(mParent) = aParent;
156
/* mPeer is left null */
158
unconst(mNATEngine).createObject();
159
mNATEngine->initCopy(aParent, aThat->mNATEngine);
161
AutoCaller thatCaller (aThat);
162
AssertComRCReturnRC(thatCaller.rc());
164
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
165
mData.attachCopy (aThat->mData);
167
/* Confirm a successful initialization */
168
autoInitSpan.setSucceeded();
174
* Uninitializes the instance and sets the ready flag to FALSE.
175
* Called either from FinalRelease() or by the parent when it gets destroyed.
177
void NetworkAdapter::uninit()
179
LogFlowThisFunc(("\n"));
181
/* Enclose the state transition Ready->InUninit->NotReady */
182
AutoUninitSpan autoUninitSpan(this);
183
if (autoUninitSpan.uninitDone())
188
unconst(mNATEngine).setNull();
189
unconst(mPeer) = NULL;
190
unconst(mParent) = NULL;
193
// INetworkAdapter properties
194
////////////////////////////////////////////////////////////////////////////////
196
STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
198
CheckComArgOutPointerValid(aAdapterType);
200
AutoCaller autoCaller(this);
201
if (FAILED(autoCaller.rc())) return autoCaller.rc();
203
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
205
*aAdapterType = mData->mAdapterType;
210
STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
212
AutoCaller autoCaller(this);
213
if (FAILED(autoCaller.rc())) return autoCaller.rc();
215
/* the machine needs to be mutable */
216
AutoMutableStateDependency adep(mParent);
217
if (FAILED(adep.rc())) return adep.rc();
219
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
221
/* make sure the value is allowed */
222
switch (aAdapterType)
224
case NetworkAdapterType_Am79C970A:
225
case NetworkAdapterType_Am79C973:
226
#ifdef VBOX_WITH_E1000
227
case NetworkAdapterType_I82540EM:
228
case NetworkAdapterType_I82543GC:
229
case NetworkAdapterType_I82545EM:
231
#ifdef VBOX_WITH_VIRTIO
232
case NetworkAdapterType_Virtio:
233
#endif /* VBOX_WITH_VIRTIO */
236
return setError(E_FAIL,
237
tr("Invalid network adapter type '%d'"),
241
if (mData->mAdapterType != aAdapterType)
244
mData->mAdapterType = aAdapterType;
247
// leave the lock before informing callbacks
250
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
251
mParent->setModified(Machine::IsModified_NetworkAdapters);
254
/* Changing the network adapter type during runtime is not allowed,
255
* therefore no immediate change in CFGM logic => changeAdapter=FALSE. */
256
mParent->onNetworkAdapterChange(this, FALSE);
262
STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
264
CheckComArgOutPointerValid(aSlot);
266
AutoCaller autoCaller(this);
267
if (FAILED(autoCaller.rc())) return autoCaller.rc();
269
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
271
*aSlot = mData->mSlot;
276
STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
278
CheckComArgOutPointerValid(aEnabled);
280
AutoCaller autoCaller(this);
281
if (FAILED(autoCaller.rc())) return autoCaller.rc();
283
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
285
*aEnabled = mData->mEnabled;
290
STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
292
AutoCaller autoCaller(this);
293
if (FAILED(autoCaller.rc())) return autoCaller.rc();
295
/* the machine needs to be mutable */
296
AutoMutableStateDependency adep(mParent);
297
if (FAILED(adep.rc())) return adep.rc();
299
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
301
if (mData->mEnabled != aEnabled)
304
mData->mEnabled = aEnabled;
307
// leave the lock before informing callbacks
310
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
311
mParent->setModified(Machine::IsModified_NetworkAdapters);
314
/* Disabling the network adapter during runtime is not allowed
315
* therefore no immediate change in CFGM logic => changeAdapter=FALSE. */
316
mParent->onNetworkAdapterChange(this, FALSE);
322
STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress)
324
CheckComArgOutPointerValid(aMACAddress);
326
AutoCaller autoCaller(this);
327
if (FAILED(autoCaller.rc())) return autoCaller.rc();
329
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
331
ComAssertRet(!mData->mMACAddress.isEmpty(), E_FAIL);
333
mData->mMACAddress.cloneTo(aMACAddress);
338
STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress)
340
AutoCaller autoCaller(this);
341
if (FAILED(autoCaller.rc())) return autoCaller.rc();
343
/* the machine needs to be mutable */
344
AutoMutableStateDependency adep(mParent);
345
if (FAILED(adep.rc())) return adep.rc();
348
bool emitChangeEvent = false;
351
* Are we supposed to generate a MAC?
353
if (!aMACAddress || !*aMACAddress)
355
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
358
generateMACAddress();
359
emitChangeEvent = true;
362
// leave the lock before informing callbacks
365
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
366
mParent->setModified(Machine::IsModified_NetworkAdapters);
371
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
372
if (mData->mMACAddress != aMACAddress)
375
* Verify given MAC address
377
Utf8Str macAddressUtf = aMACAddress;
378
char *macAddressStr = macAddressUtf.mutableRaw();
380
while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK))
382
char c = *macAddressStr;
383
/* canonicalize hex digits to capital letters */
384
if (c >= 'a' && c <= 'f')
386
/** @todo the runtime lacks an ascii lower/upper conv */
390
/* we only accept capital letters */
391
if (((c < '0') || (c > '9')) &&
392
((c < 'A') || (c > 'F')))
393
rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
394
/* the second digit must have even value for unicast addresses */
395
if ((i == 1) && (!!(c & 1) == (c >= '0' && c <= '9')))
396
rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
401
/* we must have parsed exactly 12 characters */
403
rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
409
mData->mMACAddress = macAddressUtf;
411
emitChangeEvent = true;
414
// leave the lock before informing callbacks
417
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
418
mParent->setModified(Machine::IsModified_NetworkAdapters);
424
// we have left the lock in any case at this point
428
/* Changing the MAC via the Main API during runtime is not allowed,
429
* therefore no immediate change in CFGM logic => changeAdapter=FALSE. */
430
mParent->onNetworkAdapterChange(this, FALSE);
436
STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
437
NetworkAttachmentType_T *aAttachmentType)
439
CheckComArgOutPointerValid(aAttachmentType);
441
AutoCaller autoCaller(this);
442
if (FAILED(autoCaller.rc())) return autoCaller.rc();
444
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
446
*aAttachmentType = mData->mAttachmentType;
451
STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
453
CheckComArgOutPointerValid(aHostInterface);
455
AutoCaller autoCaller(this);
456
if (FAILED(autoCaller.rc())) return autoCaller.rc();
458
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
460
mData->mHostInterface.cloneTo(aHostInterface);
465
STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface)
469
aHostInterface = bstrEmpty;
471
AutoCaller autoCaller(this);
472
if (FAILED(autoCaller.rc())) return autoCaller.rc();
474
/* the machine needs to be mutable */
475
AutoMutableStateDependency adep(mParent);
476
if (FAILED(adep.rc())) return adep.rc();
478
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
480
if (mData->mHostInterface != aHostInterface)
483
mData->mHostInterface = aHostInterface;
486
// leave the lock before informing callbacks
489
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
490
mParent->setModified(Machine::IsModified_NetworkAdapters);
493
/* When changing the host adapter, adapt the CFGM logic to make this
494
* change immediately effect and to notifiy the guest that the network
495
* might have changed, therefore changeAdapter=TRUE. */
496
mParent->onNetworkAdapterChange(this, TRUE);
502
STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
504
CheckComArgOutPointerValid(aInternalNetwork);
506
AutoCaller autoCaller(this);
507
if (FAILED(autoCaller.rc())) return autoCaller.rc();
509
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
511
mData->mInternalNetwork.cloneTo(aInternalNetwork);
516
STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwork)
518
AutoCaller autoCaller(this);
519
if (FAILED(autoCaller.rc())) return autoCaller.rc();
521
/* the machine needs to be mutable */
522
AutoMutableStateDependency adep(mParent);
523
if (FAILED(adep.rc())) return adep.rc();
525
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
527
if (mData->mInternalNetwork != aInternalNetwork)
529
/* if an empty/null string is to be set, internal networking must be
531
if ( (aInternalNetwork == NULL || *aInternalNetwork == '\0')
532
&& mData->mAttachmentType == NetworkAttachmentType_Internal)
534
return setError(E_FAIL,
535
tr("Empty or null internal network name is not valid"));
539
mData->mInternalNetwork = aInternalNetwork;
542
// leave the lock before informing callbacks
545
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
546
mParent->setModified(Machine::IsModified_NetworkAdapters);
549
/* When changing the internal network, adapt the CFGM logic to make this
550
* change immediately effect and to notifiy the guest that the network
551
* might have changed, therefore changeAdapter=TRUE. */
552
mParent->onNetworkAdapterChange(this, TRUE);
558
STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
560
CheckComArgOutPointerValid(aNATNetwork);
562
AutoCaller autoCaller(this);
563
if (FAILED(autoCaller.rc())) return autoCaller.rc();
565
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
567
mData->mNATNetwork.cloneTo(aNATNetwork);
572
STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork)
576
aNATNetwork = bstrEmpty;
578
AutoCaller autoCaller(this);
579
if (FAILED(autoCaller.rc())) return autoCaller.rc();
581
/* the machine needs to be mutable */
582
AutoMutableStateDependency adep(mParent);
583
if (FAILED(adep.rc())) return adep.rc();
585
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
587
if (mData->mNATNetwork != aNATNetwork)
590
mData->mNATNetwork = aNATNetwork;
593
// leave the lock before informing callbacks
596
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
597
mParent->setModified(Machine::IsModified_NetworkAdapters);
600
/* Changing the NAT network isn't allowed during runtime, therefore
601
* no immediate replug in CFGM logic => changeAdapter=FALSE */
602
mParent->onNetworkAdapterChange(this, FALSE);
608
STDMETHODIMP NetworkAdapter::COMGETTER(VDENetwork) (BSTR *aVDENetwork)
610
#if defined(VBOX_WITH_VDE)
611
CheckComArgOutPointerValid(aVDENetwork);
613
AutoCaller autoCaller(this);
614
if (FAILED(autoCaller.rc())) return autoCaller.rc();
616
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
618
mData->mVDENetwork.cloneTo(aVDENetwork);
627
STDMETHODIMP NetworkAdapter::COMSETTER(VDENetwork) (IN_BSTR aVDENetwork)
629
#if defined(VBOX_WITH_VDE)
632
aVDENetwork = bstrEmpty;
634
AutoCaller autoCaller(this);
635
if (FAILED(autoCaller.rc())) return autoCaller.rc();
637
/* the machine needs to be mutable */
638
AutoMutableStateDependency adep (mParent);
639
if (FAILED(adep.rc())) return adep.rc();
641
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
643
if (mData->mVDENetwork != aVDENetwork)
646
mData->mVDENetwork = aVDENetwork;
648
/* leave the lock before informing callbacks */
651
mParent->onNetworkAdapterChange (this, FALSE);
661
STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
663
CheckComArgOutPointerValid(aConnected);
665
AutoCaller autoCaller(this);
666
if (FAILED(autoCaller.rc())) return autoCaller.rc();
668
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
670
*aConnected = mData->mCableConnected;
675
STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
677
AutoCaller autoCaller(this);
678
if (FAILED(autoCaller.rc())) return autoCaller.rc();
680
/* the machine needs to be mutable */
681
AutoMutableStateDependency adep(mParent);
682
if (FAILED(adep.rc())) return adep.rc();
684
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
686
if (aConnected != mData->mCableConnected)
689
mData->mCableConnected = aConnected;
692
// leave the lock before informing callbacks
695
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
696
mParent->setModified(Machine::IsModified_NetworkAdapters);
699
/* No change in CFGM logic => changeAdapter=FALSE. */
700
mParent->onNetworkAdapterChange(this, FALSE);
706
STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
708
CheckComArgOutPointerValid(aSpeed);
710
AutoCaller autoCaller(this);
711
if (FAILED(autoCaller.rc())) return autoCaller.rc();
713
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
715
*aSpeed = mData->mLineSpeed;
720
STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
722
AutoCaller autoCaller(this);
723
if (FAILED(autoCaller.rc())) return autoCaller.rc();
725
/* the machine needs to be mutable */
726
AutoMutableStateDependency adep(mParent);
727
if (FAILED(adep.rc())) return adep.rc();
729
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
731
if (aSpeed != mData->mLineSpeed)
734
mData->mLineSpeed = aSpeed;
737
// leave the lock before informing callbacks
740
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
741
mParent->setModified(Machine::IsModified_NetworkAdapters);
744
/* No change in CFGM logic => changeAdapter=FALSE. */
745
mParent->onNetworkAdapterChange(this, FALSE);
751
STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
753
CheckComArgOutPointerValid(aEnabled);
755
AutoCaller autoCaller(this);
756
if (FAILED(autoCaller.rc())) return autoCaller.rc();
758
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
760
*aEnabled = mData->mTraceEnabled;
764
STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
766
AutoCaller autoCaller(this);
767
if (FAILED(autoCaller.rc())) return autoCaller.rc();
769
/* the machine needs to be mutable */
770
AutoMutableStateDependency adep(mParent);
771
if (FAILED(adep.rc())) return adep.rc();
773
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
775
if (aEnabled != mData->mTraceEnabled)
778
mData->mTraceEnabled = aEnabled;
781
// leave the lock before informing callbacks
784
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
785
mParent->setModified(Machine::IsModified_NetworkAdapters);
788
/* Adapt the CFGM logic changeAdapter=TRUE */
789
mParent->onNetworkAdapterChange(this, TRUE);
795
STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
797
CheckComArgOutPointerValid(aTraceFile);
799
AutoCaller autoCaller(this);
800
if (FAILED(autoCaller.rc())) return autoCaller.rc();
802
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
804
mData->mTraceFile.cloneTo(aTraceFile);
809
STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
811
AutoCaller autoCaller(this);
812
if (FAILED(autoCaller.rc())) return autoCaller.rc();
814
/* the machine needs to be mutable */
815
AutoMutableStateDependency adep(mParent);
816
if (FAILED(adep.rc())) return adep.rc();
818
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
820
if (mData->mTraceFile != aTraceFile)
823
mData->mTraceFile = aTraceFile;
826
// leave the lock before informing callbacks
829
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
830
mParent->setModified(Machine::IsModified_NetworkAdapters);
833
/* No change in CFGM logic => changeAdapter=FALSE. */
834
mParent->onNetworkAdapterChange(this, FALSE);
840
STDMETHODIMP NetworkAdapter::COMGETTER(NatDriver) (INATEngine **aNatDriver)
842
CheckComArgOutPointerValid(aNatDriver);
844
AutoCaller autoCaller(this);
845
if (FAILED(autoCaller.rc())) return autoCaller.rc();
847
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
849
mNATEngine.queryInterfaceTo(aNatDriver);
854
STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority) (ULONG *aBootPriority)
856
CheckComArgOutPointerValid(aBootPriority);
858
AutoCaller autoCaller(this);
859
if (FAILED(autoCaller.rc())) return autoCaller.rc();
861
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
863
*aBootPriority = mData->mBootPriority;
868
STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority) (ULONG aBootPriority)
870
AutoCaller autoCaller(this);
871
if (FAILED(autoCaller.rc())) return autoCaller.rc();
873
/* the machine needs to be mutable */
874
AutoMutableStateDependency adep(mParent);
875
if (FAILED(adep.rc())) return adep.rc();
877
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
879
if (aBootPriority != mData->mBootPriority)
882
mData->mBootPriority = aBootPriority;
885
// leave the lock before informing callbacks
888
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
889
mParent->setModified(Machine::IsModified_NetworkAdapters);
892
/* No change in CFGM logic => changeAdapter=FALSE. */
893
mParent->onNetworkAdapterChange(this, FALSE);
899
// INetworkAdapter methods
900
////////////////////////////////////////////////////////////////////////////////
902
STDMETHODIMP NetworkAdapter::AttachToNAT()
904
AutoCaller autoCaller(this);
905
if (FAILED(autoCaller.rc())) return autoCaller.rc();
907
/* the machine needs to be mutable */
908
AutoMutableStateDependency adep(mParent);
909
if (FAILED(adep.rc())) return adep.rc();
911
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
913
if (mData->mAttachmentType != NetworkAttachmentType_NAT)
917
// Commented this for now as it resets the parameter mData->mNATNetwork
918
// which is essential while changing the Attachment dynamically.
921
mData->mAttachmentType = NetworkAttachmentType_NAT;
924
// leave the lock before informing callbacks
927
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
928
mParent->setModified(Machine::IsModified_NetworkAdapters);
931
/* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
932
HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
935
/* If changing the attachment failed then we can't assume
936
* that the previous attachment will attach correctly
937
* and thus return error along with dettaching all
948
STDMETHODIMP NetworkAdapter::AttachToBridgedInterface()
950
AutoCaller autoCaller(this);
951
if (FAILED(autoCaller.rc())) return autoCaller.rc();
953
/* the machine needs to be mutable */
954
AutoMutableStateDependency adep(mParent);
955
if (FAILED(adep.rc())) return adep.rc();
957
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
959
/* don't do anything if we're already host interface attached */
960
if (mData->mAttachmentType != NetworkAttachmentType_Bridged)
964
/* first detach the current attachment */
965
// Commented this for now as it reset the parameter mData->mHostInterface
966
// which is essential while changing the Attachment dynamically.
969
mData->mAttachmentType = NetworkAttachmentType_Bridged;
972
// leave the lock before informing callbacks
975
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
976
mParent->setModified(Machine::IsModified_NetworkAdapters);
979
/* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
980
HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
983
/* If changing the attachment failed then we can't assume that the
984
* previous attachment will attach correctly and thus return error
985
* along with dettaching all attachments.
995
STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
997
AutoCaller autoCaller(this);
998
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1000
/* the machine needs to be mutable */
1001
AutoMutableStateDependency adep(mParent);
1002
if (FAILED(adep.rc())) return adep.rc();
1004
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1006
/* don't do anything if we're already internal network attached */
1007
if (mData->mAttachmentType != NetworkAttachmentType_Internal)
1011
/* first detach the current attachment */
1012
// Commented this for now as it reset the parameter mData->mInternalNetwork
1013
// which is essential while changing the Attachment dynamically.
1016
/* there must an internal network name */
1017
if (mData->mInternalNetwork.isEmpty())
1019
LogRel (("Internal network name not defined, "
1020
"setting to default \"intnet\"\n"));
1021
mData->mInternalNetwork = "intnet";
1024
mData->mAttachmentType = NetworkAttachmentType_Internal;
1027
// leave the lock before informing callbacks
1030
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1031
mParent->setModified(Machine::IsModified_NetworkAdapters);
1034
/* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1035
HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1038
/* If changing the attachment failed then we can't assume
1039
* that the previous attachment will attach correctly
1040
* and thus return error along with dettaching all
1051
STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface()
1053
AutoCaller autoCaller(this);
1054
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1056
/* the machine needs to be mutable */
1057
AutoMutableStateDependency adep(mParent);
1058
if (FAILED(adep.rc())) return adep.rc();
1060
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1062
/* don't do anything if we're already host interface attached */
1063
if (mData->mAttachmentType != NetworkAttachmentType_HostOnly)
1067
/* first detach the current attachment */
1068
// Commented this for now as it reset the parameter mData->mHostInterface
1069
// which is essential while changing the Attachment dynamically.
1072
mData->mAttachmentType = NetworkAttachmentType_HostOnly;
1075
// leave the lock before informing callbacks
1078
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1079
mParent->setModified(Machine::IsModified_NetworkAdapters);
1082
/* Adapt the CFGM logic and notify the guest => changeAdpater=TRUE. */
1083
HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1086
/* If changing the attachment failed then we can't assume
1087
* that the previous attachment will attach correctly
1088
* and thus return error along with dettaching all
1099
STDMETHODIMP NetworkAdapter::AttachToVDE()
1101
#if defined(VBOX_WITH_VDE)
1102
AutoCaller autoCaller(this);
1103
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1105
/* the machine needs to be mutable */
1106
AutoMutableStateDependency adep (mParent);
1107
if (FAILED(adep.rc())) return adep.rc();
1109
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1111
/* don't do anything if we're already host interface attached */
1112
if (mData->mAttachmentType != NetworkAttachmentType_VDE)
1116
/* first detach the current attachment */
1117
// Commented this for now as it reset the parameter mData->mHostInterface
1118
// which is essential while changing the Attachment dynamically.
1121
mData->mAttachmentType = NetworkAttachmentType_VDE;
1123
/* leave the lock before informing callbacks */
1126
HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
1129
/* If changing the attachment failed then we can't assume
1130
* that the previous attachment will attach correctly
1131
* and thus return error along with dettaching all
1140
#else /* !VBOX_WITH_VDE */
1145
STDMETHODIMP NetworkAdapter::Detach()
1147
AutoCaller autoCaller(this);
1148
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1150
/* the machine needs to be mutable */
1151
AutoMutableStateDependency adep(mParent);
1152
if (FAILED(adep.rc())) return adep.rc();
1154
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1156
if (mData->mAttachmentType != NetworkAttachmentType_Null)
1163
// leave the lock before informing callbacks
1166
AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1167
mParent->setModified(Machine::IsModified_NetworkAdapters);
1170
/* adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1171
mParent->onNetworkAdapterChange(this, TRUE);
1177
// public methods only for internal purposes
1178
////////////////////////////////////////////////////////////////////////////////
1181
* Loads settings from the given adapter node.
1182
* May be called once right after this object creation.
1184
* @param aAdapterNode <Adapter> node.
1186
* @note Locks this object for writing.
1188
HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
1190
AutoCaller autoCaller(this);
1191
AssertComRCReturnRC(autoCaller.rc());
1193
/* Note: we assume that the default values for attributes of optional
1194
* nodes are assigned in the Data::Data() constructor and don't do it
1195
* here. It implies that this method may only be called after constructing
1196
* a new BIOSSettings object while all its data fields are in the default
1197
* values. Exceptions are fields whose creation time defaults don't match
1198
* values that should be applied when these fields are not explicitly set
1199
* in the settings file (for backwards compatibility reasons). This takes
1200
* place when a setting of a newly created object must default to A while
1201
* the same setting of an object loaded from the old settings file must
1206
mData->mAdapterType = data.type;
1207
mData->mEnabled = data.fEnabled;
1208
/* MAC address (can be null) */
1209
rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress));
1210
if (FAILED(rc)) return rc;
1211
/* cable (required) */
1212
mData->mCableConnected = data.fCableConnected;
1213
/* line speed (defaults to 100 Mbps) */
1214
mData->mLineSpeed = data.ulLineSpeed;
1215
/* tracing (defaults to false) */
1216
mData->mTraceEnabled = data.fTraceEnabled;
1217
mData->mTraceFile = data.strTraceFile;
1218
/* boot priority (defaults to 0, i.e. lowest) */
1219
mData->mBootPriority = data.ulBootPriority;
1223
case NetworkAttachmentType_NAT:
1224
mNATEngine->loadSettings(data.nat);
1226
if (FAILED(rc)) return rc;
1229
case NetworkAttachmentType_Bridged:
1230
rc = COMSETTER(HostInterface)(Bstr(data.strName));
1231
if (FAILED(rc)) return rc;
1232
rc = AttachToBridgedInterface();
1233
if (FAILED(rc)) return rc;
1236
case NetworkAttachmentType_Internal:
1237
mData->mInternalNetwork = data.strName;
1238
Assert(!mData->mInternalNetwork.isEmpty());
1240
rc = AttachToInternalNetwork();
1241
if (FAILED(rc)) return rc;
1244
case NetworkAttachmentType_HostOnly:
1245
#if defined(VBOX_WITH_NETFLT)
1246
rc = COMSETTER(HostInterface)(Bstr(data.strName));
1247
if (FAILED(rc)) return rc;
1249
rc = AttachToHostOnlyInterface();
1250
if (FAILED(rc)) return rc;
1253
#if defined(VBOX_WITH_VDE)
1254
case NetworkAttachmentType_VDE:
1255
mData->mVDENetwork = data.strName;
1257
if (FAILED(rc)) return rc;
1261
case NetworkAttachmentType_Null:
1263
if (FAILED(rc)) return rc;
1266
if (data.fHasDisabledNAT)
1267
mNATEngine->loadSettings(data.nat);
1269
// after loading settings, we are no longer different from the XML on disk
1270
m_fModified = false;
1276
* Saves settings to the given adapter node.
1278
* Note that the given Adapter node is comletely empty on input.
1280
* @param aAdapterNode <Adapter> node.
1282
* @note Locks this object for reading.
1284
HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
1286
AutoCaller autoCaller(this);
1287
AssertComRCReturnRC(autoCaller.rc());
1289
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1291
data.fEnabled = !!mData->mEnabled;
1292
data.strMACAddress = mData->mMACAddress;
1293
data.fCableConnected = !!mData->mCableConnected;
1295
data.ulLineSpeed = mData->mLineSpeed;
1297
data.fTraceEnabled = !!mData->mTraceEnabled;
1299
data.strTraceFile = mData->mTraceFile;
1301
data.ulBootPriority = mData->mBootPriority;
1303
data.type = mData->mAdapterType;
1305
switch (data.mode = mData->mAttachmentType)
1307
case NetworkAttachmentType_Null:
1308
data.strName.setNull();
1311
case NetworkAttachmentType_NAT:
1312
data.fHasDisabledNAT = 0;
1313
mNATEngine->commit();
1314
mNATEngine->saveSettings(data.nat);
1317
case NetworkAttachmentType_Bridged:
1318
data.strName = mData->mHostInterface;
1321
case NetworkAttachmentType_Internal:
1322
data.strName = mData->mInternalNetwork;
1325
case NetworkAttachmentType_HostOnly:
1326
data.strName = mData->mHostInterface;
1329
#if defined(VBOX_WITH_VDE)
1330
case NetworkAttachmentType_VDE:
1331
data.strName = mData->mVDENetwork;
1336
if (data.mode != NetworkAttachmentType_NAT)
1338
data.fHasDisabledNAT = 1; /* ??? */
1339
mNATEngine->commit();
1340
mNATEngine->saveSettings(data.nat);
1343
// after saving settings, we are no longer different from the XML on disk
1344
m_fModified = false;
1350
* Returns true if any setter method has modified settings of this instance.
1353
bool NetworkAdapter::isModified() {
1354
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1355
bool fChanged = m_fModified;
1356
fChanged |= (mData->mAdapterType == NetworkAttachmentType_NAT? mNATEngine->isModified() : false);
1361
* @note Locks this object for writing.
1363
void NetworkAdapter::rollback()
1366
AutoCaller autoCaller(this);
1367
AssertComRCReturnVoid(autoCaller.rc());
1369
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1375
* @note Locks this object for writing, together with the peer object (also
1376
* for writing) if there is one.
1378
void NetworkAdapter::commit()
1381
AutoCaller autoCaller(this);
1382
AssertComRCReturnVoid (autoCaller.rc());
1385
AutoCaller peerCaller (mPeer);
1386
AssertComRCReturnVoid (peerCaller.rc());
1388
/* lock both for writing since we modify both (mPeer is "master" so locked
1390
AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1392
if (mData.isBackedUp())
1397
/* attach new data to the peer and reshare it */
1398
mPeer->mData.attach (mData);
1404
* @note Locks this object for writing, together with the peer object
1405
* represented by @a aThat (locked for reading).
1407
void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1409
AssertReturnVoid (aThat != NULL);
1412
AutoCaller autoCaller(this);
1413
AssertComRCReturnVoid (autoCaller.rc());
1416
AutoCaller thatCaller (aThat);
1417
AssertComRCReturnVoid (thatCaller.rc());
1419
/* peer is not modified, lock it for reading (aThat is "master" so locked
1421
AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1422
AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1424
/* this will back up current data */
1425
mData.assignCopy (aThat->mData);
1428
void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
1430
AssertReturnVoid (aOsType != NULL);
1433
AutoCaller autoCaller(this);
1434
AssertComRCReturnVoid (autoCaller.rc());
1436
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1438
bool e1000enabled = false;
1439
#ifdef VBOX_WITH_E1000
1440
e1000enabled = true;
1441
#endif // VBOX_WITH_E1000
1443
NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1445
/* Set default network adapter for this OS type */
1446
if (defaultType == NetworkAdapterType_I82540EM ||
1447
defaultType == NetworkAdapterType_I82543GC ||
1448
defaultType == NetworkAdapterType_I82545EM)
1450
if (e1000enabled) mData->mAdapterType = defaultType;
1452
else mData->mAdapterType = defaultType;
1454
/* Enable and connect the first one adapter to the NAT */
1455
if (mData->mSlot == 0)
1457
mData->mEnabled = true;
1458
mData->mAttachmentType = NetworkAttachmentType_NAT;
1459
mData->mCableConnected = true;
1464
////////////////////////////////////////////////////////////////////////////////
1467
* Worker routine for detach handling. No locking, no notifications.
1469
* @note Must be called from under the object's write lock.
1471
void NetworkAdapter::detach()
1473
AssertReturnVoid (isWriteLockOnCurrentThread());
1475
switch (mData->mAttachmentType)
1477
case NetworkAttachmentType_Null:
1479
/* nothing to do here */
1482
case NetworkAttachmentType_NAT:
1486
case NetworkAttachmentType_Bridged:
1488
/* reset handle and device name */
1489
mData->mHostInterface = "";
1492
case NetworkAttachmentType_Internal:
1494
mData->mInternalNetwork.setNull();
1497
case NetworkAttachmentType_HostOnly:
1499
#if defined(VBOX_WITH_NETFLT)
1500
/* reset handle and device name */
1501
mData->mHostInterface = "";
1507
mData->mAttachmentType = NetworkAttachmentType_Null;
1511
* Generates a new unique MAC address based on our vendor ID and
1514
* @note Must be called from under the object's write lock or within the init
1517
void NetworkAdapter::generateMACAddress()
1520
* Our strategy is as follows: the first three bytes are our fixed
1521
* vendor ID (080027). The remaining 3 bytes will be taken from the
1522
* start of a GUID. This is a fairly safe algorithm.
1527
RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1528
guid.ptr()->au8[0], guid.ptr()->au8[1], guid.ptr()->au8[2]);
1529
LogFlowThisFunc(("generated MAC: '%s'\n", strMAC));
1530
mData->mMACAddress = strMAC;
1532
/* vi: set tabstop=4 shiftwidth=4 expandtab: */