VirtualBox

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

Last change on this file since 16560 was 16560, checked in by vboxsync, 15 years ago

Main: do not include include/VBox/settings.h from other header files but only from implementations that need it (save compile time)

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

© 2023 Oracle
ContactPrivacy policyTerms of Use