diff options
Diffstat (limited to 'src/VBox/Main/src-server/NetworkAdapterImpl.cpp')
-rw-r--r-- | src/VBox/Main/src-server/NetworkAdapterImpl.cpp | 824 |
1 files changed, 354 insertions, 470 deletions
diff --git a/src/VBox/Main/src-server/NetworkAdapterImpl.cpp b/src/VBox/Main/src-server/NetworkAdapterImpl.cpp index 81459ac05..85bfc08bd 100644 --- a/src/VBox/Main/src-server/NetworkAdapterImpl.cpp +++ b/src/VBox/Main/src-server/NetworkAdapterImpl.cpp @@ -1,10 +1,10 @@ -/* $Id: NetworkAdapterImpl.cpp $ */ +/* $Id: NetworkAdapterImpl.cpp 37927 2011-07-13 15:48:41Z vboxsync $ */ /** @file * Implementation of INetworkAdaptor in VBoxSVC. */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -21,6 +21,7 @@ #include "Logging.h" #include "MachineImpl.h" #include "GuestOSTypeImpl.h" +#include "HostImpl.h" #include <iprt/string.h> #include <iprt/cpp/utils.h> @@ -45,12 +46,13 @@ NetworkAdapter::~NetworkAdapter() HRESULT NetworkAdapter::FinalConstruct() { - return S_OK; + return BaseFinalConstruct(); } void NetworkAdapter::FinalRelease() { uninit(); + BaseFinalRelease(); } // public initializer/uninitializer for internal purposes only @@ -84,9 +86,6 @@ HRESULT NetworkAdapter::init(Machine *aParent, ULONG aSlot) /* initialize data */ mData->mSlot = aSlot; - /* Default limit is not capped/unlimited. */ - mData->mBandwidthLimit = 0; - /* default to Am79C973 */ mData->mAdapterType = NetworkAdapterType_Am79C973; @@ -338,47 +337,23 @@ STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress) return S_OK; } -STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress) +HRESULT NetworkAdapter::updateMacAddress(Utf8Str aMACAddress) { - AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return autoCaller.rc(); - - /* the machine needs to be mutable */ - AutoMutableStateDependency adep(mParent); - if (FAILED(adep.rc())) return adep.rc(); - HRESULT rc = S_OK; - bool emitChangeEvent = false; /* * Are we supposed to generate a MAC? */ - if (!aMACAddress || !*aMACAddress) - { - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - mData.backup(); - + if (aMACAddress.isEmpty()) generateMACAddress(); - emitChangeEvent = true; - - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); - - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); - } else { - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (mData->mMACAddress != aMACAddress) { /* * Verify given MAC address */ - Utf8Str macAddressUtf = aMACAddress; - char *macAddressStr = macAddressUtf.mutableRaw(); + char *macAddressStr = aMACAddress.mutableRaw(); int i = 0; while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK)) { @@ -406,28 +381,37 @@ STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress) rc = setError(E_INVALIDARG, tr("Invalid MAC address format")); if (SUCCEEDED(rc)) - { - mData.backup(); + mData->mMACAddress = aMACAddress; + } + } - mData->mMACAddress = macAddressUtf; + return rc; +} - emitChangeEvent = true; +STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress) +{ + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(mParent); + if (FAILED(adep.rc())) return adep.rc(); - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); - } - } - } - // we have left the lock in any case at this point + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + mData.backup(); - if (emitChangeEvent) + HRESULT rc = updateMacAddress(aMACAddress); + if (SUCCEEDED(rc)) { + m_fModified = true; + // leave the lock before informing callbacks + alock.release(); + + AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock + mParent->setModified(Machine::IsModified_NetworkAdapters); + mlock.release(); + /* Changing the MAC via the Main API during runtime is not allowed, * therefore no immediate change in CFGM logic => changeAdapter=FALSE. */ mParent->onNetworkAdapterChange(this, FALSE); @@ -451,25 +435,116 @@ STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)( return S_OK; } -STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface) +STDMETHODIMP NetworkAdapter::COMSETTER(AttachmentType)( + NetworkAttachmentType_T aAttachmentType) +{ + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(mParent); + if (FAILED(adep.rc())) return adep.rc(); + + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + + if (mData->mAttachmentType != aAttachmentType) + { + mData.backup(); + + /* there must an internal network name */ + if (mData->mInternalNetwork.isEmpty()) + { + Log(("Internal network name not defined, setting to default \"intnet\"\n")); + mData->mInternalNetwork = "intnet"; + } + + mData->mAttachmentType = aAttachmentType; + + m_fModified = true; + // leave the lock before informing callbacks + alock.release(); + + AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock + mParent->setModified(Machine::IsModified_NetworkAdapters); + mlock.release(); + + /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */ + mParent->onNetworkAdapterChange(this, TRUE); + } + + return S_OK; +} + +STDMETHODIMP NetworkAdapter::COMGETTER(BridgedInterface)(BSTR *aBridgedInterface) +{ + CheckComArgOutPointerValid(aBridgedInterface); + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + + mData->mBridgedInterface.cloneTo(aBridgedInterface); + + return S_OK; +} + +STDMETHODIMP NetworkAdapter::COMSETTER(BridgedInterface)(IN_BSTR aBridgedInterface) +{ + Bstr bstrEmpty(""); + if (!aBridgedInterface) + aBridgedInterface = bstrEmpty.raw(); + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(mParent); + if (FAILED(adep.rc())) return adep.rc(); + + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + + if (mData->mBridgedInterface != aBridgedInterface) + { + mData.backup(); + mData->mBridgedInterface = aBridgedInterface; + + m_fModified = true; + // leave the lock before informing callbacks + alock.release(); + + AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock + mParent->setModified(Machine::IsModified_NetworkAdapters); + mlock.release(); + + /* When changing the host adapter, adapt the CFGM logic to make this + * change immediately effect and to notify the guest that the network + * might have changed, therefore changeAdapter=TRUE. */ + mParent->onNetworkAdapterChange(this, TRUE); + } + + return S_OK; +} + +STDMETHODIMP NetworkAdapter::COMGETTER(HostOnlyInterface)(BSTR *aHostOnlyInterface) { - CheckComArgOutPointerValid(aHostInterface); + CheckComArgOutPointerValid(aHostOnlyInterface); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); - mData->mHostInterface.cloneTo(aHostInterface); + mData->mHostOnlyInterface.cloneTo(aHostOnlyInterface); return S_OK; } -STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface) +STDMETHODIMP NetworkAdapter::COMSETTER(HostOnlyInterface)(IN_BSTR aHostOnlyInterface) { Bstr bstrEmpty(""); - if (!aHostInterface) - aHostInterface = bstrEmpty.raw(); + if (!aHostOnlyInterface) + aHostOnlyInterface = bstrEmpty.raw(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); @@ -480,10 +555,10 @@ STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface) AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - if (mData->mHostInterface != aHostInterface) + if (mData->mHostOnlyInterface != aHostOnlyInterface) { mData.backup(); - mData->mHostInterface = aHostInterface; + mData->mHostOnlyInterface = aHostOnlyInterface; m_fModified = true; // leave the lock before informing callbacks @@ -608,57 +683,47 @@ STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork) return S_OK; } -STDMETHODIMP NetworkAdapter::COMGETTER(VDENetwork) (BSTR *aVDENetwork) +STDMETHODIMP NetworkAdapter::COMGETTER(GenericDriver)(BSTR *aGenericDriver) { -#if defined(VBOX_WITH_VDE) - CheckComArgOutPointerValid(aVDENetwork); + CheckComArgOutPointerValid(aGenericDriver); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); - mData->mVDENetwork.cloneTo(aVDENetwork); + mData->mGenericDriver.cloneTo(aGenericDriver); return S_OK; -#else - NOREF(aVDENetwork); - return E_NOTIMPL; -#endif } -STDMETHODIMP NetworkAdapter::COMSETTER(VDENetwork) (IN_BSTR aVDENetwork) +STDMETHODIMP NetworkAdapter::COMSETTER(GenericDriver)(IN_BSTR aGenericDriver) { -#if defined(VBOX_WITH_VDE) Bstr bstrEmpty(""); - if (!aVDENetwork) - aVDENetwork = bstrEmpty.raw(); + if (!aGenericDriver) + aGenericDriver = bstrEmpty.raw(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); /* the machine needs to be mutable */ - AutoMutableStateDependency adep (mParent); + AutoMutableStateDependency adep(mParent); if (FAILED(adep.rc())) return adep.rc(); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - if (mData->mVDENetwork != aVDENetwork) + if (mData->mGenericDriver != aGenericDriver) { mData.backup(); - mData->mVDENetwork = aVDENetwork; + mData->mGenericDriver = aGenericDriver; /* leave the lock before informing callbacks */ alock.release(); - mParent->onNetworkAdapterChange (this, FALSE); + mParent->onNetworkAdapterChange(this, FALSE); } return S_OK; -#else - NOREF(aVDENetwork); - return E_NOTIMPL; -#endif } STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected) @@ -751,45 +816,52 @@ STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed) return S_OK; } -STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthLimit) (ULONG *aLimit) + +STDMETHODIMP NetworkAdapter::COMGETTER(PromiscModePolicy)(NetworkAdapterPromiscModePolicy_T *aPromiscModePolicy) { - CheckComArgOutPointerValid(aLimit); + CheckComArgOutPointerValid(aPromiscModePolicy); AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return autoCaller.rc(); - - AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); - - *aLimit = mData->mBandwidthLimit; - return S_OK; + HRESULT hrc = autoCaller.rc(); + if (SUCCEEDED(hrc)) + { + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + *aPromiscModePolicy = mData->mPromiscModePolicy; + } + return hrc; } -STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthLimit) (ULONG aLimit) +STDMETHODIMP NetworkAdapter::COMSETTER(PromiscModePolicy)(NetworkAdapterPromiscModePolicy_T aPromiscModePolicy) { - AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return autoCaller.rc(); - - /* the machine doesn't need to be mutable */ - - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - - if (aLimit != mData->mBandwidthLimit) + switch (aPromiscModePolicy) { - mData.backup(); - mData->mBandwidthLimit = aLimit; + case NetworkAdapterPromiscModePolicy_Deny: + case NetworkAdapterPromiscModePolicy_AllowNetwork: + case NetworkAdapterPromiscModePolicy_AllowAll: + break; + default: + return setError(E_INVALIDARG, tr("Invalid promiscuous mode policy (%d)"), aPromiscModePolicy); + } - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); + AutoCaller autoCaller(this); + HRESULT hrc = autoCaller.rc(); - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); + if (SUCCEEDED(hrc)) + { + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + if (aPromiscModePolicy != mData->mPromiscModePolicy) + { + mData.backup(); + mData->mPromiscModePolicy = aPromiscModePolicy; + m_fModified = true; - /* No change in CFGM logic => changeAdapter=FALSE. */ - mParent->onNetworkAdapterChange(this, FALSE); + alock.release(); + mParent->setModifiedLock(Machine::IsModified_NetworkAdapters); + mParent->onNetworkAdapterChange(this, TRUE); + } } - return S_OK; + + return hrc; } STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled) @@ -943,280 +1015,116 @@ STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority) (ULONG aBootPriority) // INetworkAdapter methods //////////////////////////////////////////////////////////////////////////////// -STDMETHODIMP NetworkAdapter::AttachToNAT() +STDMETHODIMP NetworkAdapter::GetProperty(IN_BSTR aKey, BSTR *aValue) { - AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return autoCaller.rc(); - - /* the machine needs to be mutable */ - AutoMutableStateDependency adep(mParent); - if (FAILED(adep.rc())) return adep.rc(); + CheckComArgOutPointerValid(aValue); - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - - if (mData->mAttachmentType != NetworkAttachmentType_NAT) - { - mData.backup(); - - // Commented this for now as it resets the parameter mData->mNATNetwork - // which is essential while changing the Attachment dynamically. - //detach(); - - mData->mAttachmentType = NetworkAttachmentType_NAT; - - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); - - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); - - /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */ - HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE); - if (FAILED(rc)) - { - /* If changing the attachment failed then we can't assume - * that the previous attachment will attach correctly - * and thus return error along with detaching all - * attachments. - */ - Detach(); - return rc; - } - } - - return S_OK; -} - -STDMETHODIMP NetworkAdapter::AttachToBridgedInterface() -{ AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); - /* the machine needs to be mutable */ - AutoMutableStateDependency adep(mParent); - if (FAILED(adep.rc())) return adep.rc(); + Bstr key = aKey; + Bstr value; - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); - /* don't do anything if we're already host interface attached */ - if (mData->mAttachmentType != NetworkAttachmentType_Bridged) + Utf8Str strKey(key); + settings::StringsMap::const_iterator it = mData->mGenericProperties.find(strKey); + if (it != mData->mGenericProperties.end()) { - mData.backup(); - - /* first detach the current attachment */ - // Commented this for now as it reset the parameter mData->mHostInterface - // which is essential while changing the Attachment dynamically. - //detach(); - - mData->mAttachmentType = NetworkAttachmentType_Bridged; - - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); - - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); - - /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */ - HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE); - if (FAILED(rc)) - { - /* If changing the attachment failed then we can't assume that the - * previous attachment will attach correctly and thus return error - * along with detaching all attachments. - */ - Detach(); - return rc; - } + value = it->second; // source is a Utf8Str + value.cloneTo(aValue); } return S_OK; } -STDMETHODIMP NetworkAdapter::AttachToInternalNetwork() +STDMETHODIMP NetworkAdapter::SetProperty(IN_BSTR aKey, IN_BSTR aValue) { + LogFlowThisFunc(("\n")); + AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); - /* the machine needs to be mutable */ + /* The machine needs to be mutable. */ AutoMutableStateDependency adep(mParent); if (FAILED(adep.rc())) return adep.rc(); - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - - /* don't do anything if we're already internal network attached */ - if (mData->mAttachmentType != NetworkAttachmentType_Internal) - { - mData.backup(); - - /* first detach the current attachment */ - // Commented this for now as it reset the parameter mData->mInternalNetwork - // which is essential while changing the Attachment dynamically. - //detach(); - - /* there must an internal network name */ - if (mData->mInternalNetwork.isEmpty()) - { - LogRel (("Internal network name not defined, " - "setting to default \"intnet\"\n")); - mData->mInternalNetwork = "intnet"; - } + Bstr key = aKey; - mData->mAttachmentType = NetworkAttachmentType_Internal; - - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); - - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); - - /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */ - HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE); - if (FAILED(rc)) - { - /* If changing the attachment failed then we can't assume - * that the previous attachment will attach correctly - * and thus return error along with detaching all - * attachments. - */ - Detach(); - return rc; - } - } - - return S_OK; -} + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); -STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface() -{ - AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return autoCaller.rc(); + bool fGenericChange = (mData->mAttachmentType == NetworkAttachmentType_Generic); - /* the machine needs to be mutable */ - AutoMutableStateDependency adep(mParent); - if (FAILED(adep.rc())) return adep.rc(); + /* Generic properties processing. + * Look up the old value first; if nothing's changed then do nothing. + */ + Utf8Str strValue(aValue); + Utf8Str strKey(aKey); + Utf8Str strOldValue; - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + settings::StringsMap::const_iterator it = mData->mGenericProperties.find(strKey); + if (it != mData->mGenericProperties.end()) + strOldValue = it->second; - /* don't do anything if we're already host interface attached */ - if (mData->mAttachmentType != NetworkAttachmentType_HostOnly) + if (strOldValue != strValue) { - mData.backup(); - - /* first detach the current attachment */ - // Commented this for now as it reset the parameter mData->mHostInterface - // which is essential while changing the Attachment dynamically. - //detach(); - - mData->mAttachmentType = NetworkAttachmentType_HostOnly; + if (strValue.isEmpty()) + mData->mGenericProperties.erase(strKey); + else + mData->mGenericProperties[strKey] = strValue; - m_fModified = true; - // leave the lock before informing callbacks + /* leave the lock before informing callbacks */ alock.release(); - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock + AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); mParent->setModified(Machine::IsModified_NetworkAdapters); mlock.release(); - /* Adapt the CFGM logic and notify the guest => changeAdpater=TRUE. */ - HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE); - if (FAILED(rc)) - { - /* If changing the attachment failed then we can't assume - * that the previous attachment will attach correctly - * and thus return error along with detaching all - * attachments. - */ - Detach(); - return rc; - } + /* Avoid deadlock when the event triggers a call to a method of this + * interface. */ + adep.release(); + + mParent->onNetworkAdapterChange(this, fGenericChange); } return S_OK; } -STDMETHODIMP NetworkAdapter::AttachToVDE() +STDMETHODIMP NetworkAdapter::GetProperties(IN_BSTR aNames, + ComSafeArrayOut(BSTR, aReturnNames), + ComSafeArrayOut(BSTR, aReturnValues)) { -#if defined(VBOX_WITH_VDE) + CheckComArgOutSafeArrayPointerValid(aReturnNames); + CheckComArgOutSafeArrayPointerValid(aReturnValues); + AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); - /* the machine needs to be mutable */ - AutoMutableStateDependency adep (mParent); - if (FAILED(adep.rc())) return adep.rc(); - - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - - /* don't do anything if we're already host interface attached */ - if (mData->mAttachmentType != NetworkAttachmentType_VDE) - { - mData.backup(); - - /* first detach the current attachment */ - // Commented this for now as it reset the parameter mData->mHostInterface - // which is essential while changing the Attachment dynamically. - //detach(); + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); - mData->mAttachmentType = NetworkAttachmentType_VDE; + /// @todo make use of aNames according to the documentation + NOREF(aNames); - /* leave the lock before informing callbacks */ - alock.release(); + com::SafeArray<BSTR> names(mData->mGenericProperties.size()); + com::SafeArray<BSTR> values(mData->mGenericProperties.size()); + size_t i = 0; - HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE); - if (FAILED (rc)) - { - /* If changing the attachment failed then we can't assume - * that the previous attachment will attach correctly - * and thus return error along with detaching all - * attachments. - */ - Detach(); - return rc; - } + for (settings::StringsMap::const_iterator it = mData->mGenericProperties.begin(); + it != mData->mGenericProperties.end(); + ++it) + { + it->first.cloneTo(&names[i]); + it->second.cloneTo(&values[i]); + ++i; } + names.detachTo(ComSafeArrayOutArg(aReturnNames)); + values.detachTo(ComSafeArrayOutArg(aReturnValues)); + return S_OK; -#else /* !VBOX_WITH_VDE */ - return E_NOTIMPL; -#endif } -STDMETHODIMP NetworkAdapter::Detach() -{ - AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return autoCaller.rc(); - /* the machine needs to be mutable */ - AutoMutableStateDependency adep(mParent); - if (FAILED(adep.rc())) return adep.rc(); - - AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - - if (mData->mAttachmentType != NetworkAttachmentType_Null) - { - mData.backup(); - - detach(); - - m_fModified = true; - // leave the lock before informing callbacks - alock.release(); - - AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock - mParent->setModified(Machine::IsModified_NetworkAdapters); - mlock.release(); - - /* adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */ - mParent->onNetworkAdapterChange(this, TRUE); - } - - return S_OK; -} // public methods only for internal purposes //////////////////////////////////////////////////////////////////////////////// @@ -1229,11 +1137,14 @@ STDMETHODIMP NetworkAdapter::Detach() * * @note Locks this object for writing. */ -HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data) +HRESULT NetworkAdapter::loadSettings(BandwidthControl *bwctl, + const settings::NetworkAdapter &data) { AutoCaller autoCaller(this); AssertComRCReturnRC(autoCaller.rc()); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + /* Note: we assume that the default values for attributes of optional * nodes are assigned in the Data::Data() constructor and don't do it * here. It implies that this method may only be called after constructing @@ -1250,67 +1161,40 @@ HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data) mData->mAdapterType = data.type; mData->mEnabled = data.fEnabled; /* MAC address (can be null) */ - rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress).raw()); + rc = updateMacAddress(data.strMACAddress); if (FAILED(rc)) return rc; /* cable (required) */ mData->mCableConnected = data.fCableConnected; /* line speed (defaults to 100 Mbps) */ mData->mLineSpeed = data.ulLineSpeed; + mData->mPromiscModePolicy = data.enmPromiscModePolicy; /* tracing (defaults to false) */ mData->mTraceEnabled = data.fTraceEnabled; mData->mTraceFile = data.strTraceFile; /* boot priority (defaults to 0, i.e. lowest) */ mData->mBootPriority = data.ulBootPriority; - /* Bandwidth limit in Mbps. */ - mData->mBandwidthLimit = data.ulBandwidthLimit; - - switch (data.mode) + /* bandwidth group */ + if (data.strBandwidthGroup.isEmpty()) + updateBandwidthGroup(NULL); + else { - case NetworkAttachmentType_NAT: - mNATEngine->loadSettings(data.nat); - rc = AttachToNAT(); - if (FAILED(rc)) return rc; - break; - - case NetworkAttachmentType_Bridged: - rc = COMSETTER(HostInterface)(Bstr(data.strName).raw()); - if (FAILED(rc)) return rc; - rc = AttachToBridgedInterface(); - if (FAILED(rc)) return rc; - break; - - case NetworkAttachmentType_Internal: - mData->mInternalNetwork = data.strName; - Assert(!mData->mInternalNetwork.isEmpty()); - - rc = AttachToInternalNetwork(); - if (FAILED(rc)) return rc; - break; - - case NetworkAttachmentType_HostOnly: -#if defined(VBOX_WITH_NETFLT) - rc = COMSETTER(HostInterface)(Bstr(data.strName).raw()); - if (FAILED(rc)) return rc; -#endif - rc = AttachToHostOnlyInterface(); - if (FAILED(rc)) return rc; - break; - -#if defined(VBOX_WITH_VDE) - case NetworkAttachmentType_VDE: - mData->mVDENetwork = data.strName; - rc = AttachToVDE(); - if (FAILED(rc)) return rc; - break; -#endif - - case NetworkAttachmentType_Null: - rc = Detach(); - if (FAILED(rc)) return rc; - break; + ComObjPtr<BandwidthGroup> group; + rc = bwctl->getBandwidthGroupByName(data.strBandwidthGroup, group, true); + if (FAILED(rc)) return rc; } - if (data.fHasDisabledNAT) - mNATEngine->loadSettings(data.nat); + + mNATEngine->loadSettings(data.nat); + mData->mBridgedInterface = data.strBridgedName; + mData->mInternalNetwork = data.strInternalNetworkName; + mData->mHostOnlyInterface = data.strHostOnlyName; + mData->mGenericDriver = data.strGenericDriver; + mData->mGenericProperties = data.genericProperties; + + // leave the lock before setting attachment type + alock.release(); + + rc = COMSETTER(AttachmentType)(data.mode); + if (FAILED(rc)) return rc; // after loading settings, we are no longer different from the XML on disk m_fModified = false; @@ -1338,6 +1222,7 @@ HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data) data.strMACAddress = mData->mMACAddress; data.fCableConnected = !!mData->mCableConnected; + data.enmPromiscModePolicy = mData->mPromiscModePolicy; data.ulLineSpeed = mData->mLineSpeed; data.fTraceEnabled = !!mData->mTraceEnabled; @@ -1346,47 +1231,26 @@ HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data) data.ulBootPriority = mData->mBootPriority; - data.ulBandwidthLimit = mData->mBandwidthLimit; + if (mData->mBandwidthGroup.isNull()) + data.strBandwidthGroup = ""; + else + data.strBandwidthGroup = mData->mBandwidthGroup->getName(); data.type = mData->mAdapterType; - switch (data.mode = mData->mAttachmentType) - { - case NetworkAttachmentType_Null: - data.strName.setNull(); - break; - - case NetworkAttachmentType_NAT: - data.fHasDisabledNAT = 0; - mNATEngine->commit(); - mNATEngine->saveSettings(data.nat); - break; - - case NetworkAttachmentType_Bridged: - data.strName = mData->mHostInterface; - break; - - case NetworkAttachmentType_Internal: - data.strName = mData->mInternalNetwork; - break; - - case NetworkAttachmentType_HostOnly: - data.strName = mData->mHostInterface; - break; - -#if defined(VBOX_WITH_VDE) - case NetworkAttachmentType_VDE: - data.strName = mData->mVDENetwork; - break; -#endif - } + data.mode = mData->mAttachmentType; - if (data.mode != NetworkAttachmentType_NAT) - { - data.fHasDisabledNAT = 1; /* ??? */ - mNATEngine->commit(); - mNATEngine->saveSettings(data.nat); - } + mNATEngine->commit(); + mNATEngine->saveSettings(data.nat); + + data.strBridgedName = mData->mBridgedInterface; + + data.strHostOnlyName = mData->mHostOnlyInterface; + + data.strInternalNetworkName = mData->mInternalNetwork; + + data.strGenericDriver = mData->mGenericDriver; + data.genericProperties = mData->mGenericProperties; // after saving settings, we are no longer different from the XML on disk m_fModified = false; @@ -1512,69 +1376,89 @@ void NetworkAdapter::applyDefaults (GuestOSType *aOsType) //////////////////////////////////////////////////////////////////////////////// /** - * Worker routine for detach handling. No locking, no notifications. - - * @note Must be called from under the object's write lock. + * Generates a new unique MAC address based on our vendor ID and + * parts of a GUID. + * + * @note Must be called from under the object's write lock or within the init + * span. */ -void NetworkAdapter::detach() +void NetworkAdapter::generateMACAddress() { - AssertReturnVoid (isWriteLockOnCurrentThread()); + Utf8Str mac; + Host::generateMACAddress(mac); + LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str())); + mData->mMACAddress = mac; +} + +STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthGroup) (IBandwidthGroup **aBwGroup) +{ + LogFlowThisFuncEnter(); + CheckComArgOutPointerValid(aBwGroup); + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); - switch (mData->mAttachmentType) + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + + mData->mBandwidthGroup.queryInterfaceTo(aBwGroup); + + LogFlowThisFuncLeave(); + return S_OK; +} + +STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthGroup) (IBandwidthGroup *aBwGroup) +{ + LogFlowThisFuncEnter(); + + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return autoCaller.rc(); + + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(mParent); + if (FAILED(adep.rc())) return adep.rc(); + + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + + if (mData->mBandwidthGroup != aBwGroup) { - case NetworkAttachmentType_Null: - { - /* nothing to do here */ - break; - } - case NetworkAttachmentType_NAT: - { - break; - } - case NetworkAttachmentType_Bridged: - { - /* reset handle and device name */ - mData->mHostInterface = ""; - break; - } - case NetworkAttachmentType_Internal: - { - mData->mInternalNetwork.setNull(); - break; - } - case NetworkAttachmentType_HostOnly: - { -#if defined(VBOX_WITH_NETFLT) - /* reset handle and device name */ - mData->mHostInterface = ""; -#endif - break; - } + mData.backup(); + + updateBandwidthGroup(static_cast<BandwidthGroup*>(aBwGroup)); + + m_fModified = true; + // leave the lock before informing callbacks + alock.release(); + + AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); + mParent->setModified(Machine::IsModified_NetworkAdapters); + mlock.release(); + + /* TODO: changeAdapter=???. */ + mParent->onNetworkAdapterChange(this, FALSE); } - mData->mAttachmentType = NetworkAttachmentType_Null; + LogFlowThisFuncLeave(); + return S_OK; } -/** - * Generates a new unique MAC address based on our vendor ID and - * parts of a GUID. - * - * @note Must be called from under the object's write lock or within the init - * span. - */ -void NetworkAdapter::generateMACAddress() +void NetworkAdapter::updateBandwidthGroup(BandwidthGroup *aBwGroup) { - /* - * Our strategy is as follows: the first three bytes are our fixed - * vendor ID (080027). The remaining 3 bytes will be taken from the - * start of a GUID. This is a fairly safe algorithm. - */ - char strMAC[13]; - Guid guid; - guid.create(); - RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X", - guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]); - LogFlowThisFunc(("generated MAC: '%s'\n", strMAC)); - mData->mMACAddress = strMAC; + LogFlowThisFuncEnter(); + Assert(isWriteLockOnCurrentThread()); + + mData.backup(); + if (!mData->mBandwidthGroup.isNull()) + { + mData->mBandwidthGroup->release(); + mData->mBandwidthGroup.setNull(); + } + + if (aBwGroup) + { + mData->mBandwidthGroup = aBwGroup; + mData->mBandwidthGroup->reference(); + } + + LogFlowThisFuncLeave(); } /* vi: set tabstop=4 shiftwidth=4 expandtab: */ |