VirtualBox

source: vbox/trunk/src/VBox/Main/NetworkAdapterImpl.cpp@ 25414

Last change on this file since 25414 was 25346, checked in by vboxsync, 14 years ago

iprt/cpputils.h -> iprt/cpp/utils.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.8 KB
RevLine 
[20704]1/* $Id: NetworkAdapterImpl.cpp 25346 2009-12-13 16:21:19Z vboxsync $ */
[1]2/** @file
[20704]3 * Implementation of INetworkAdaptor in VBoxSVC.
[1]4 */
5
6/*
[8155]7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
[1]8 *
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
[5999]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.
[8155]16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
[1]20 */
21
22#include "NetworkAdapterImpl.h"
23#include "Logging.h"
24#include "MachineImpl.h"
[14664]25#include "GuestOSTypeImpl.h"
[1]26
27#include <iprt/string.h>
[25346]28#include <iprt/cpp/utils.h>
[1]29
[3348]30#include <VBox/err.h>
[16560]31#include <VBox/settings.h>
[1]32
33// constructor / destructor
34////////////////////////////////////////////////////////////////////////////////
35
[3348]36DEFINE_EMPTY_CTOR_DTOR (NetworkAdapter)
37
[1]38HRESULT NetworkAdapter::FinalConstruct()
39{
40 return S_OK;
41}
42
43void NetworkAdapter::FinalRelease()
44{
[3348]45 uninit ();
[1]46}
47
48// public initializer/uninitializer for internal purposes only
49////////////////////////////////////////////////////////////////////////////////
50
51/**
[3348]52 * Initializes the network adapter object.
[1]53 *
[3348]54 * @param aParent Handle of the parent object.
[1]55 */
[3348]56HRESULT NetworkAdapter::init (Machine *aParent, ULONG aSlot)
[1]57{
[21878]58 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
[1]59
[3348]60 ComAssertRet (aParent, E_INVALIDARG);
61 ComAssertRet (aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
[1]62
[3348]63 /* Enclose the state transition NotReady->InInit->Ready */
[21878]64 AutoInitSpan autoInitSpan(this);
65 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]66
[21878]67 unconst(mParent) = aParent;
[3348]68 /* mPeer is left null */
[1]69
70 mData.allocate();
71
[3348]72 /* initialize data */
73 mData->mSlot = aSlot;
[1]74
[3348]75 /* default to Am79C973 */
[7207]76 mData->mAdapterType = NetworkAdapterType_Am79C973;
[1]77
[3348]78 /* generate the MAC address early to guarantee it is the same both after
79 * changing some other property (i.e. after mData.backup()) and after the
80 * subsequent mData.rollback(). */
[1]81 generateMACAddress();
82
[3348]83 /* Confirm a successful initialization */
84 autoInitSpan.setSucceeded();
85
[1]86 return S_OK;
87}
88
89/**
90 * Initializes the network adapter object given another network adapter object
91 * (a kind of copy constructor). This object shares data with
92 * the object passed as an argument.
93 *
94 * @note This object must be destroyed before the original object
95 * it shares data with is destroyed.
[3348]96 *
97 * @note Locks @a aThat object for reading.
[1]98 */
[3348]99HRESULT NetworkAdapter::init (Machine *aParent, NetworkAdapter *aThat)
[1]100{
[21878]101 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
[1]102
[3348]103 ComAssertRet (aParent && aThat, E_INVALIDARG);
[1]104
[3348]105 /* Enclose the state transition NotReady->InInit->Ready */
[21878]106 AutoInitSpan autoInitSpan(this);
107 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]108
[21878]109 unconst(mParent) = aParent;
110 unconst(mPeer) = aThat;
[1]111
[3348]112 AutoCaller thatCaller (aThat);
[21878]113 AssertComRCReturnRC(thatCaller.rc());
[1]114
[25310]115 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[3348]116 mData.share (aThat->mData);
117
118 /* Confirm a successful initialization */
119 autoInitSpan.setSucceeded();
120
[1]121 return S_OK;
122}
123
124/**
125 * Initializes the guest object given another guest object
126 * (a kind of copy constructor). This object makes a private copy of data
127 * of the original object passed as an argument.
[3348]128 *
129 * @note Locks @a aThat object for reading.
[1]130 */
[3348]131HRESULT NetworkAdapter::initCopy (Machine *aParent, NetworkAdapter *aThat)
[1]132{
[21878]133 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
[1]134
[3348]135 ComAssertRet (aParent && aThat, E_INVALIDARG);
[1]136
[3348]137 /* Enclose the state transition NotReady->InInit->Ready */
[21878]138 AutoInitSpan autoInitSpan(this);
139 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]140
[21878]141 unconst(mParent) = aParent;
[3348]142 /* mPeer is left null */
[1]143
[3348]144 AutoCaller thatCaller (aThat);
[21878]145 AssertComRCReturnRC(thatCaller.rc());
[1]146
[25310]147 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[3348]148 mData.attachCopy (aThat->mData);
149
150 /* Confirm a successful initialization */
151 autoInitSpan.setSucceeded();
152
[1]153 return S_OK;
154}
155
156/**
157 * Uninitializes the instance and sets the ready flag to FALSE.
158 * Called either from FinalRelease() or by the parent when it gets destroyed.
159 */
160void NetworkAdapter::uninit()
161{
[21878]162 LogFlowThisFunc(("\n"));
[1]163
[3348]164 /* Enclose the state transition Ready->InUninit->NotReady */
[21878]165 AutoUninitSpan autoUninitSpan(this);
[3348]166 if (autoUninitSpan.uninitDone())
167 return;
[1]168
169 mData.free();
170
[21878]171 unconst(mPeer).setNull();
172 unconst(mParent).setNull();
[1]173}
174
175// INetworkAdapter properties
176////////////////////////////////////////////////////////////////////////////////
177
[3348]178STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
[1]179{
[14972]180 CheckComArgOutPointerValid(aAdapterType);
[1]181
[21878]182 AutoCaller autoCaller(this);
[25149]183 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]184
[25310]185 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]186
187 *aAdapterType = mData->mAdapterType;
188
[1]189 return S_OK;
190}
191
[3348]192STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
[1]193{
[21878]194 AutoCaller autoCaller(this);
[25149]195 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]196
[3348]197 /* the machine needs to be mutable */
[25149]198 Machine::AutoMutableStateDependency adep(mParent);
199 if (FAILED(adep.rc())) return adep.rc();
[1]200
[25310]201 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]202
[1]203 /* make sure the value is allowed */
[3348]204 switch (aAdapterType)
[1]205 {
[7207]206 case NetworkAdapterType_Am79C970A:
207 case NetworkAdapterType_Am79C973:
[5755]208#ifdef VBOX_WITH_E1000
[7207]209 case NetworkAdapterType_I82540EM:
[8439]210 case NetworkAdapterType_I82543GC:
[18591]211 case NetworkAdapterType_I82545EM:
[5755]212#endif
[22866]213#ifdef VBOX_WITH_VIRTIO
214 case NetworkAdapterType_Virtio:
215#endif /* VBOX_WITH_VIRTIO */
[1]216 break;
217 default:
[3348]218 return setError (E_FAIL,
219 tr("Invalid network adapter type '%d'"),
220 aAdapterType);
[1]221 }
222
[3348]223 if (mData->mAdapterType != aAdapterType)
[1]224 {
225 mData.backup();
[3348]226 mData->mAdapterType = aAdapterType;
[1]227
[3348]228 /* leave the lock before informing callbacks */
[25279]229 alock.release();
[3348]230
[21961]231 mParent->onNetworkAdapterChange (this, FALSE);
[1]232 }
233
234 return S_OK;
235}
236
[3348]237STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
[1]238{
[14972]239 CheckComArgOutPointerValid(aSlot);
[1]240
[21878]241 AutoCaller autoCaller(this);
[25149]242 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]243
[25310]244 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]245
246 *aSlot = mData->mSlot;
247
[1]248 return S_OK;
249}
250
[3348]251STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
[1]252{
[14972]253 CheckComArgOutPointerValid(aEnabled);
[1]254
[21878]255 AutoCaller autoCaller(this);
[25149]256 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]257
[25310]258 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]259
260 *aEnabled = mData->mEnabled;
261
[1]262 return S_OK;
263}
264
[3348]265STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
[1]266{
[21878]267 AutoCaller autoCaller(this);
[25149]268 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]269
[3348]270 /* the machine needs to be mutable */
[25149]271 Machine::AutoMutableStateDependency adep(mParent);
272 if (FAILED(adep.rc())) return adep.rc();
[1]273
[25310]274 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]275
276 if (mData->mEnabled != aEnabled)
[1]277 {
278 mData.backup();
[3348]279 mData->mEnabled = aEnabled;
[1]280
[3348]281 /* leave the lock before informing callbacks */
[25279]282 alock.release();
[3348]283
[21961]284 mParent->onNetworkAdapterChange (this, FALSE);
[1]285 }
286
287 return S_OK;
288}
289
[3348]290STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress)
[1]291{
[14972]292 CheckComArgOutPointerValid(aMACAddress);
[1]293
[21878]294 AutoCaller autoCaller(this);
[25149]295 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]296
[25310]297 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]298
[1]299 ComAssertRet (!!mData->mMACAddress, E_FAIL);
300
[21878]301 mData->mMACAddress.cloneTo(aMACAddress);
[1]302
303 return S_OK;
304}
305
[15051]306STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress)
[1]307{
[21878]308 AutoCaller autoCaller(this);
[25149]309 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]310
[3348]311 /* the machine needs to be mutable */
[25149]312 Machine::AutoMutableStateDependency adep(mParent);
313 if (FAILED(adep.rc())) return adep.rc();
[1]314
[25310]315 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]316
[1]317 HRESULT rc = S_OK;
318 bool emitChangeEvent = false;
319
320 /*
321 * Are we supposed to generate a MAC?
322 */
[20977]323 if (!aMACAddress || !*aMACAddress)
[1]324 {
325 mData.backup();
[3348]326
[1]327 generateMACAddress();
328 emitChangeEvent = true;
329 }
330 else
331 {
[3348]332 if (mData->mMACAddress != aMACAddress)
[1]333 {
334 /*
335 * Verify given MAC address
336 */
[3348]337 Utf8Str macAddressUtf = aMACAddress;
[5117]338 char *macAddressStr = macAddressUtf.mutableRaw();
[1]339 int i = 0;
[5117]340 while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK))
[1]341 {
342 char c = *macAddressStr;
[5117]343 /* canonicalize hex digits to capital letters */
344 if (c >= 'a' && c <= 'f')
345 {
346 /** @todo the runtime lacks an ascii lower/upper conv */
347 c &= 0xdf;
348 *macAddressStr = c;
349 }
[1]350 /* we only accept capital letters */
351 if (((c < '0') || (c > '9')) &&
352 ((c < 'A') || (c > 'F')))
353 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
[5378]354 /* the second digit must have even value for unicast addresses */
355 if ((i == 1) && (!!(c & 1) == (c >= '0' && c <= '9')))
[5117]356 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
[5120]357
[1]358 macAddressStr++;
359 i++;
360 }
361 /* we must have parsed exactly 12 characters */
362 if (i != 12)
363 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
364
[21878]365 if (SUCCEEDED(rc))
[1]366 {
367 mData.backup();
[3348]368
[5117]369 mData->mMACAddress = macAddressUtf;
[1]370 emitChangeEvent = true;
371 }
372 }
373 }
374
375 if (emitChangeEvent)
376 {
[3348]377 /* leave the lock before informing callbacks */
[25279]378 alock.release();
[3348]379
[21961]380 mParent->onNetworkAdapterChange (this, FALSE);
[1]381 }
382
383 return rc;
384}
385
[3348]386STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
387 NetworkAttachmentType_T *aAttachmentType)
[1]388{
[14972]389 CheckComArgOutPointerValid(aAttachmentType);
[1]390
[21878]391 AutoCaller autoCaller(this);
[25149]392 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]393
[25310]394 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]395
396 *aAttachmentType = mData->mAttachmentType;
397
[1]398 return S_OK;
399}
400
[18829]401STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
[1]402{
[14972]403 CheckComArgOutPointerValid(aHostInterface);
[1]404
[21878]405 AutoCaller autoCaller(this);
[25149]406 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]407
[25310]408 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]409
[21878]410 mData->mHostInterface.cloneTo(aHostInterface);
[3348]411
[1]412 return S_OK;
413}
414
[18829]415STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface)
[1]416{
[23061]417 Bstr bstrEmpty("");
418 if (!aHostInterface)
419 aHostInterface = bstrEmpty;
[1]420
[21878]421 AutoCaller autoCaller(this);
[25149]422 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]423
[3348]424 /* the machine needs to be mutable */
[25149]425 Machine::AutoMutableStateDependency adep(mParent);
426 if (FAILED(adep.rc())) return adep.rc();
[1]427
[25310]428 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]429
[18829]430 if (mData->mHostInterface != aHostInterface)
[1]431 {
432 mData.backup();
[18829]433 mData->mHostInterface = aHostInterface;
[1]434
[3348]435 /* leave the lock before informing callbacks */
[25279]436 alock.release();
[3348]437
[21961]438 mParent->onNetworkAdapterChange (this, FALSE);
[1]439 }
440
441 return S_OK;
442}
443
[3348]444STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
[1]445{
[14972]446 CheckComArgOutPointerValid(aInternalNetwork);
[1]447
[21878]448 AutoCaller autoCaller(this);
[25149]449 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]450
[25310]451 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]452
[21878]453 mData->mInternalNetwork.cloneTo(aInternalNetwork);
[3348]454
[1]455 return S_OK;
456}
457
[15051]458STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwork)
[1]459{
[21878]460 AutoCaller autoCaller(this);
[25149]461 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]462
[3348]463 /* the machine needs to be mutable */
[25149]464 Machine::AutoMutableStateDependency adep(mParent);
465 if (FAILED(adep.rc())) return adep.rc();
[1]466
[25310]467 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]468
469 if (mData->mInternalNetwork != aInternalNetwork)
[1]470 {
[8367]471 /* if an empty/null string is to be set, internal networking must be
472 * turned off */
473 if ( (aInternalNetwork == NULL || *aInternalNetwork == '\0')
474 && mData->mAttachmentType == NetworkAttachmentType_Internal)
[1]475 {
[8367]476 return setError (E_FAIL,
477 tr ("Empty or null internal network name is not valid"));
[1]478 }
479
480 mData.backup();
[3348]481 mData->mInternalNetwork = aInternalNetwork;
[1]482
[3348]483 /* leave the lock before informing callbacks */
[25279]484 alock.release();
[3348]485
[21961]486 mParent->onNetworkAdapterChange (this, FALSE);
[1]487 }
488
489 return S_OK;
490}
491
[8367]492STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
493{
[14972]494 CheckComArgOutPointerValid(aNATNetwork);
[8367]495
[21878]496 AutoCaller autoCaller(this);
[25149]497 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[8367]498
[25310]499 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[8367]500
[21878]501 mData->mNATNetwork.cloneTo(aNATNetwork);
[8367]502
503 return S_OK;
504}
505
[15051]506STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork)
[8367]507{
[25098]508 Bstr bstrEmpty("");
509 if (!aNATNetwork)
510 aNATNetwork = bstrEmpty;
511
[21878]512 AutoCaller autoCaller(this);
[25149]513 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[8367]514
515 /* the machine needs to be mutable */
[25149]516 Machine::AutoMutableStateDependency adep(mParent);
517 if (FAILED(adep.rc())) return adep.rc();
[8367]518
[25310]519 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[8367]520
521 if (mData->mNATNetwork != aNATNetwork)
522 {
523 mData.backup();
524 mData->mNATNetwork = aNATNetwork;
525
526 /* leave the lock before informing callbacks */
[25279]527 alock.release();
[8367]528
[21961]529 mParent->onNetworkAdapterChange (this, FALSE);
[8367]530 }
531
532 return S_OK;
533}
534
[3348]535STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
[1]536{
[14972]537 CheckComArgOutPointerValid(aConnected);
[1]538
[21878]539 AutoCaller autoCaller(this);
[25149]540 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]541
[25310]542 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]543
544 *aConnected = mData->mCableConnected;
545
[1]546 return S_OK;
547}
548
[3348]549STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
[1]550{
[21878]551 AutoCaller autoCaller(this);
[25149]552 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]553
[3348]554 /* the machine needs to be mutable */
[25149]555 Machine::AutoMutableStateDependency adep(mParent);
556 if (FAILED(adep.rc())) return adep.rc();
[1]557
[25310]558 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]559
560 if (aConnected != mData->mCableConnected)
[1]561 {
562 mData.backup();
[3348]563 mData->mCableConnected = aConnected;
[1]564
[3348]565 /* leave the lock before informing callbacks */
[25279]566 alock.release();
[3348]567
[21961]568 mParent->onNetworkAdapterChange (this, FALSE);
[1]569 }
570
571 return S_OK;
572}
573
[5060]574STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
575{
[14972]576 CheckComArgOutPointerValid(aSpeed);
[5060]577
[21878]578 AutoCaller autoCaller(this);
[25149]579 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[5060]580
[25310]581 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[5060]582
583 *aSpeed = mData->mLineSpeed;
584
585 return S_OK;
586}
587
588STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
589{
[21878]590 AutoCaller autoCaller(this);
[25149]591 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[5060]592
593 /* the machine needs to be mutable */
[25149]594 Machine::AutoMutableStateDependency adep(mParent);
595 if (FAILED(adep.rc())) return adep.rc();
[5060]596
[25310]597 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[5060]598
599 if (aSpeed != mData->mLineSpeed)
600 {
601 mData.backup();
602 mData->mLineSpeed = aSpeed;
603
604 /* leave the lock before informing callbacks */
[25279]605 alock.release();
[5060]606
[21961]607 mParent->onNetworkAdapterChange (this, FALSE);
[5060]608 }
609
610 return S_OK;
611}
612
[3348]613STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
[1]614{
[14972]615 CheckComArgOutPointerValid(aEnabled);
[1]616
[21878]617 AutoCaller autoCaller(this);
[25149]618 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]619
[25310]620 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]621
622 *aEnabled = mData->mTraceEnabled;
[1]623 return S_OK;
624}
625
[3348]626STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
[1]627{
[21878]628 AutoCaller autoCaller(this);
[25149]629 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]630
[3348]631 /* the machine needs to be mutable */
[25149]632 Machine::AutoMutableStateDependency adep(mParent);
633 if (FAILED(adep.rc())) return adep.rc();
[1]634
[25310]635 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]636
637 if (aEnabled != mData->mTraceEnabled)
[1]638 {
639 mData.backup();
[3348]640 mData->mTraceEnabled = aEnabled;
[1]641
[3348]642 /* leave the lock before informing callbacks */
[25279]643 alock.release();
[3348]644
[23222]645 mParent->onNetworkAdapterChange (this, TRUE);
[1]646 }
647
648 return S_OK;
649}
650
[3348]651STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
[1]652{
[14972]653 CheckComArgOutPointerValid(aTraceFile);
[1]654
[21878]655 AutoCaller autoCaller(this);
[25149]656 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]657
[25310]658 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]659
[21878]660 mData->mTraceFile.cloneTo(aTraceFile);
[3348]661
[1]662 return S_OK;
663}
664
[15051]665STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
[1]666{
[21878]667 AutoCaller autoCaller(this);
[25149]668 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]669
[3348]670 /* the machine needs to be mutable */
[25149]671 Machine::AutoMutableStateDependency adep(mParent);
672 if (FAILED(adep.rc())) return adep.rc();
[1]673
[25310]674 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]675
[3348]676 if (mData->mTraceFile != aTraceFile)
677 {
678 mData.backup();
679 mData->mTraceFile = aTraceFile;
[1]680
[3348]681 /* leave the lock before informing callbacks */
[25279]682 alock.release();
[3348]683
[21961]684 mParent->onNetworkAdapterChange (this, FALSE);
[3348]685 }
686
[1]687 return S_OK;
688}
689
690// INetworkAdapter methods
691////////////////////////////////////////////////////////////////////////////////
692
693STDMETHODIMP NetworkAdapter::AttachToNAT()
694{
[21878]695 AutoCaller autoCaller(this);
[25149]696 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]697
[3348]698 /* the machine needs to be mutable */
[25149]699 Machine::AutoMutableStateDependency adep(mParent);
700 if (FAILED(adep.rc())) return adep.rc();
[1]701
[25310]702 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]703
[7207]704 if (mData->mAttachmentType != NetworkAttachmentType_NAT)
[1]705 {
706 mData.backup();
[3348]707
[21817]708 // Commented this for now as it resets the parameter mData->mNATNetwork
709 // which is essential while changing the Attachment dynamically.
710 //detach();
[3348]711
[7207]712 mData->mAttachmentType = NetworkAttachmentType_NAT;
[1]713
[3348]714 /* leave the lock before informing callbacks */
[25279]715 alock.release();
[3348]716
[21961]717 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
718 if (FAILED (rc))
719 {
720 /* If changing the attachment failed then we can't assume
721 * that the previous attachment will attach correctly
722 * and thus return error along with dettaching all
723 * attachments.
724 */
725 Detach();
726 return rc;
727 }
[1]728 }
729
730 return S_OK;
731}
732
[17387]733STDMETHODIMP NetworkAdapter::AttachToBridgedInterface()
[1]734{
[21878]735 AutoCaller autoCaller(this);
[25149]736 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]737
[3348]738 /* the machine needs to be mutable */
[25149]739 Machine::AutoMutableStateDependency adep(mParent);
740 if (FAILED(adep.rc())) return adep.rc();
[1]741
[25310]742 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]743
[1]744 /* don't do anything if we're already host interface attached */
[17275]745 if (mData->mAttachmentType != NetworkAttachmentType_Bridged)
[1]746 {
747 mData.backup();
[3348]748
[1]749 /* first detach the current attachment */
[21817]750 // Commented this for now as it reset the parameter mData->mHostInterface
751 // which is essential while changing the Attachment dynamically.
752 //detach();
[3348]753
[17275]754 mData->mAttachmentType = NetworkAttachmentType_Bridged;
[1]755
[3348]756 /* leave the lock before informing callbacks */
[25279]757 alock.release();
[3348]758
[21961]759 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
760 if (FAILED (rc))
761 {
762 /* If changing the attachment failed then we can't assume
763 * that the previous attachment will attach correctly
764 * and thus return error along with dettaching all
765 * attachments.
766 */
767 Detach();
768 return rc;
769 }
[1]770 }
771
772 return S_OK;
773}
774
775STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
776{
[21878]777 AutoCaller autoCaller(this);
[25149]778 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]779
[3348]780 /* the machine needs to be mutable */
[25149]781 Machine::AutoMutableStateDependency adep(mParent);
782 if (FAILED(adep.rc())) return adep.rc();
[1]783
[25310]784 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]785
[1]786 /* don't do anything if we're already internal network attached */
[7207]787 if (mData->mAttachmentType != NetworkAttachmentType_Internal)
[1]788 {
[3348]789 mData.backup();
790
791 /* first detach the current attachment */
[21817]792 // Commented this for now as it reset the parameter mData->mInternalNetwork
793 // which is essential while changing the Attachment dynamically.
794 //detach();
[3348]795
[1]796 /* there must an internal network name */
[8367]797 if (mData->mInternalNetwork.isEmpty())
[1]798 {
[3348]799 LogRel (("Internal network name not defined, "
800 "setting to default \"intnet\"\n"));
[8367]801 mData->mInternalNetwork = "intnet";
[1]802 }
803
[7207]804 mData->mAttachmentType = NetworkAttachmentType_Internal;
[1]805
[3348]806 /* leave the lock before informing callbacks */
[25279]807 alock.release();
[3348]808
[21961]809 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
810 if (FAILED (rc))
811 {
812 /* If changing the attachment failed then we can't assume
813 * that the previous attachment will attach correctly
814 * and thus return error along with dettaching all
815 * attachments.
816 */
817 Detach();
818 return rc;
819 }
[1]820 }
821
822 return S_OK;
823}
824
[17387]825STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface()
[16509]826{
[21878]827 AutoCaller autoCaller(this);
[25149]828 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[16509]829
830 /* the machine needs to be mutable */
[25149]831 Machine::AutoMutableStateDependency adep(mParent);
832 if (FAILED(adep.rc())) return adep.rc();
[16509]833
[25310]834 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[16509]835
836 /* don't do anything if we're already host interface attached */
837 if (mData->mAttachmentType != NetworkAttachmentType_HostOnly)
838 {
839 mData.backup();
840
841 /* first detach the current attachment */
[21817]842 // Commented this for now as it reset the parameter mData->mHostInterface
843 // which is essential while changing the Attachment dynamically.
844 //detach();
[16509]845
846 mData->mAttachmentType = NetworkAttachmentType_HostOnly;
847
848 /* leave the lock before informing callbacks */
[25279]849 alock.release();
[16509]850
[21961]851 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
852 if (FAILED (rc))
853 {
854 /* If changing the attachment failed then we can't assume
855 * that the previous attachment will attach correctly
856 * and thus return error along with dettaching all
857 * attachments.
858 */
859 Detach();
860 return rc;
861 }
[16509]862 }
863
864 return S_OK;
865}
866
[1]867STDMETHODIMP NetworkAdapter::Detach()
868{
[21878]869 AutoCaller autoCaller(this);
[25149]870 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]871
[3348]872 /* the machine needs to be mutable */
[25149]873 Machine::AutoMutableStateDependency adep(mParent);
874 if (FAILED(adep.rc())) return adep.rc();
[1]875
[25310]876 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]877
[7207]878 if (mData->mAttachmentType != NetworkAttachmentType_Null)
[1]879 {
880 mData.backup();
[3348]881
[1]882 detach();
883
[3348]884 /* leave the lock before informing callbacks */
[25279]885 alock.release();
[3348]886
[21961]887 mParent->onNetworkAdapterChange (this, TRUE);
[1]888 }
889
890 return S_OK;
891}
892
893// public methods only for internal purposes
894////////////////////////////////////////////////////////////////////////////////
895
[5117]896/**
[6076]897 * Loads settings from the given adapter node.
898 * May be called once right after this object creation.
[7207]899 *
[6076]900 * @param aAdapterNode <Adapter> node.
[7207]901 *
902 * @note Locks this object for writing.
[6076]903 */
[22173]904HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
[6076]905{
[21878]906 AutoCaller autoCaller(this);
907 AssertComRCReturnRC(autoCaller.rc());
[6076]908
[25310]909 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[6076]910
911 /* Note: we assume that the default values for attributes of optional
912 * nodes are assigned in the Data::Data() constructor and don't do it
913 * here. It implies that this method may only be called after constructing
914 * a new BIOSSettings object while all its data fields are in the default
915 * values. Exceptions are fields whose creation time defaults don't match
916 * values that should be applied when these fields are not explicitly set
917 * in the settings file (for backwards compatibility reasons). This takes
918 * place when a setting of a newly created object must default to A while
919 * the same setting of an object loaded from the old settings file must
[7207]920 * default to B. */
[6076]921
922 HRESULT rc = S_OK;
923
[22173]924 mData->mAdapterType = data.type;
925 mData->mEnabled = data.fEnabled;
[6076]926 /* MAC address (can be null) */
[22173]927 rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress));
[25149]928 if (FAILED(rc)) return rc;
[6076]929 /* cable (required) */
[22173]930 mData->mCableConnected = data.fCableConnected;
[6076]931 /* line speed (defaults to 100 Mbps) */
[22173]932 mData->mLineSpeed = data.ulLineSpeed;
[6076]933 /* tracing (defaults to false) */
[22173]934 mData->mTraceEnabled = data.fTraceEnabled;
935 mData->mTraceFile = data.strTraceFile;
[6076]936
[22173]937 switch (data.mode)
[6076]938 {
[22173]939 case NetworkAttachmentType_NAT:
940 mData->mNATNetwork = data.strName;
[25098]941 if (mData->mNATNetwork.isNull())
942 mData->mNATNetwork = "";
[22173]943 rc = AttachToNAT();
[25149]944 if (FAILED(rc)) return rc;
[22173]945 break;
[6076]946
[22173]947 case NetworkAttachmentType_Bridged:
948 rc = COMSETTER(HostInterface)(Bstr(data.strName));
[25149]949 if (FAILED(rc)) return rc;
[22173]950 rc = AttachToBridgedInterface();
[25149]951 if (FAILED(rc)) return rc;
[22173]952 break;
[8367]953
[22173]954 case NetworkAttachmentType_Internal:
955 mData->mInternalNetwork = data.strName;
956 Assert(!mData->mInternalNetwork.isNull());
[6076]957
[22173]958 rc = AttachToInternalNetwork();
[25149]959 if (FAILED(rc)) return rc;
[22173]960 break;
[15708]961
[22173]962 case NetworkAttachmentType_HostOnly:
[17843]963#if defined(VBOX_WITH_NETFLT)
[22173]964 rc = COMSETTER(HostInterface)(Bstr(data.strName));
[25149]965 if (FAILED(rc)) return rc;
[16967]966#endif
[22173]967 rc = AttachToHostOnlyInterface();
[25149]968 if (FAILED(rc)) return rc;
[22173]969 break;
[16967]970
[22173]971 case NetworkAttachmentType_Null:
972 rc = Detach();
[25149]973 if (FAILED(rc)) return rc;
[22173]974 break;
[16509]975 }
[6076]976
977 return S_OK;
978}
979
[7207]980/**
[6076]981 * Saves settings to the given adapter node.
[7207]982 *
[6076]983 * Note that the given Adapter node is comletely empty on input.
984 *
985 * @param aAdapterNode <Adapter> node.
[7207]986 *
987 * @note Locks this object for reading.
[6076]988 */
[22173]989HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
[6076]990{
[21878]991 AutoCaller autoCaller(this);
992 AssertComRCReturnRC(autoCaller.rc());
[6076]993
[25310]994 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[6076]995
[22173]996 data.fEnabled = !!mData->mEnabled;
997 data.strMACAddress = mData->mMACAddress;
998 data.fCableConnected = !!mData->mCableConnected;
[6076]999
[22173]1000 data.ulLineSpeed = mData->mLineSpeed;
[6076]1001
[22186]1002 data.fTraceEnabled = !!mData->mTraceEnabled;
[6076]1003
[22173]1004 data.strTraceFile = mData->mTraceFile;
[6076]1005
[22173]1006 data.type = mData->mAdapterType;
[6076]1007
[22173]1008 switch (data.mode = mData->mAttachmentType)
[6076]1009 {
[7207]1010 case NetworkAttachmentType_Null:
[22173]1011 data.strName.setNull();
1012 break;
1013
[7207]1014 case NetworkAttachmentType_NAT:
[22173]1015 data.strName = mData->mNATNetwork;
1016 break;
1017
[17275]1018 case NetworkAttachmentType_Bridged:
[22173]1019 data.strName = mData->mHostInterface;
1020 break;
1021
[7207]1022 case NetworkAttachmentType_Internal:
[22173]1023 data.strName = mData->mInternalNetwork;
1024 break;
1025
[16509]1026 case NetworkAttachmentType_HostOnly:
[22173]1027 data.strName = mData->mHostInterface;
1028 break;
[6076]1029 }
1030
1031 return S_OK;
1032}
1033
1034/**
[3348]1035 * @note Locks this object for writing.
1036 */
[1]1037bool NetworkAdapter::rollback()
1038{
[3348]1039 /* sanity */
[21878]1040 AutoCaller autoCaller(this);
[3348]1041 AssertComRCReturn (autoCaller.rc(), false);
1042
[25310]1043 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]1044
1045 bool changed = false;
1046
1047 if (mData.isBackedUp())
1048 {
[3348]1049 /* we need to check all data to see whether anything will be changed
1050 * after rollback */
[1]1051 changed = mData.hasActualChanges();
1052 mData.rollback();
1053 }
1054
1055 return changed;
1056}
1057
[5117]1058/**
[3348]1059 * @note Locks this object for writing, together with the peer object (also
1060 * for writing) if there is one.
1061 */
[1]1062void NetworkAdapter::commit()
1063{
[3348]1064 /* sanity */
[21878]1065 AutoCaller autoCaller(this);
[3348]1066 AssertComRCReturnVoid (autoCaller.rc());
1067
1068 /* sanity too */
[7992]1069 AutoCaller peerCaller (mPeer);
1070 AssertComRCReturnVoid (peerCaller.rc());
[3348]1071
[7992]1072 /* lock both for writing since we modify both (mPeer is "master" so locked
1073 * first) */
[25310]1074 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
[3348]1075
[1]1076 if (mData.isBackedUp())
1077 {
1078 mData.commit();
1079 if (mPeer)
1080 {
[3348]1081 /* attach new data to the peer and reshare it */
[1]1082 mPeer->mData.attach (mData);
1083 }
1084 }
1085}
1086
[5117]1087/**
[3348]1088 * @note Locks this object for writing, together with the peer object
1089 * represented by @a aThat (locked for reading).
1090 */
[1]1091void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1092{
[3348]1093 AssertReturnVoid (aThat != NULL);
[1]1094
[3348]1095 /* sanity */
[21878]1096 AutoCaller autoCaller(this);
[3348]1097 AssertComRCReturnVoid (autoCaller.rc());
1098
1099 /* sanity too */
[7992]1100 AutoCaller thatCaller (aThat);
[3348]1101 AssertComRCReturnVoid (thatCaller.rc());
1102
[7992]1103 /* peer is not modified, lock it for reading (aThat is "master" so locked
1104 * first) */
[25310]1105 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1106 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
[3348]1107
1108 /* this will back up current data */
[1]1109 mData.assignCopy (aThat->mData);
1110}
1111
[14664]1112void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
1113{
[14665]1114 AssertReturnVoid (aOsType != NULL);
[14664]1115
[14665]1116 /* sanity */
[21878]1117 AutoCaller autoCaller(this);
[14665]1118 AssertComRCReturnVoid (autoCaller.rc());
1119
[25310]1120 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[14665]1121
[14664]1122 bool e1000enabled = false;
1123#ifdef VBOX_WITH_E1000
[14665]1124 e1000enabled = true;
[14664]1125#endif // VBOX_WITH_E1000
1126
1127 NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1128
1129 /* Set default network adapter for this OS type */
1130 if (defaultType == NetworkAdapterType_I82540EM ||
[18591]1131 defaultType == NetworkAdapterType_I82543GC ||
1132 defaultType == NetworkAdapterType_I82545EM)
[14664]1133 {
1134 if (e1000enabled) mData->mAdapterType = defaultType;
1135 }
1136 else mData->mAdapterType = defaultType;
1137
1138 /* Enable and connect the first one adapter to the NAT */
1139 if (mData->mSlot == 0)
1140 {
1141 mData->mEnabled = true;
1142 mData->mAttachmentType = NetworkAttachmentType_NAT;
1143 mData->mCableConnected = true;
1144 }
1145}
1146
[1]1147// private methods
1148////////////////////////////////////////////////////////////////////////////////
1149
1150/**
[3348]1151 * Worker routine for detach handling. No locking, no notifications.
1152
1153 * @note Must be called from under the object's write lock.
[1]1154 */
1155void NetworkAdapter::detach()
1156{
[8083]1157 AssertReturnVoid (isWriteLockOnCurrentThread());
[3348]1158
[1]1159 switch (mData->mAttachmentType)
1160 {
[7207]1161 case NetworkAttachmentType_Null:
[1]1162 {
1163 /* nothing to do here */
1164 break;
1165 }
[7207]1166 case NetworkAttachmentType_NAT:
[1]1167 {
1168 break;
1169 }
[17275]1170 case NetworkAttachmentType_Bridged:
[1]1171 {
1172 /* reset handle and device name */
[18829]1173 mData->mHostInterface = "";
[1]1174 break;
1175 }
[7207]1176 case NetworkAttachmentType_Internal:
[1]1177 {
1178 mData->mInternalNetwork.setNull();
1179 break;
1180 }
[16509]1181 case NetworkAttachmentType_HostOnly:
1182 {
[17843]1183#if defined(VBOX_WITH_NETFLT)
[16967]1184 /* reset handle and device name */
[18829]1185 mData->mHostInterface = "";
[16967]1186#endif
[16509]1187 break;
1188 }
[1]1189 }
1190
[7207]1191 mData->mAttachmentType = NetworkAttachmentType_Null;
[1]1192}
1193
1194/**
[3348]1195 * Generates a new unique MAC address based on our vendor ID and
1196 * parts of a GUID.
1197 *
1198 * @note Must be called from under the object's write lock or within the init
1199 * span.
[1]1200 */
1201void NetworkAdapter::generateMACAddress()
1202{
1203 /*
1204 * Our strategy is as follows: the first three bytes are our fixed
1205 * vendor ID (080027). The remaining 3 bytes will be taken from the
1206 * start of a GUID. This is a fairly safe algorithm.
1207 */
1208 char strMAC[13];
1209 Guid guid;
1210 guid.create();
[3348]1211 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1212 guid.ptr()->au8[0], guid.ptr()->au8[1], guid.ptr()->au8[2]);
[21878]1213 LogFlowThisFunc(("generated MAC: '%s'\n", strMAC));
[1]1214 mData->mMACAddress = strMAC;
1215}
[14772]1216/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use