VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/NetworkAdapterImpl.cpp@ 35638

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

Main. QT/FE: fix long standing COM issue

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.7 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 35638 2011-01-19 19:10:49Z vboxsync $ */
2/** @file
3 * Implementation of INetworkAdaptor in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
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
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.
16 */
17
18#include "NetworkAdapterImpl.h"
19#include "NATEngineImpl.h"
20#include "AutoCaller.h"
21#include "Logging.h"
22#include "MachineImpl.h"
23#include "GuestOSTypeImpl.h"
24
25#include <iprt/string.h>
26#include <iprt/cpp/utils.h>
27
28#include <VBox/err.h>
29#include <VBox/settings.h>
30
31#include "AutoStateDep.h"
32
33// constructor / destructor
34////////////////////////////////////////////////////////////////////////////////
35
36NetworkAdapter::NetworkAdapter()
37 : mParent(NULL)
38{
39}
40
41NetworkAdapter::~NetworkAdapter()
42{
43}
44
45HRESULT NetworkAdapter::FinalConstruct()
46{
47
48 return BaseFinalConstruct();
49}
50
51void NetworkAdapter::FinalRelease()
52{
53 uninit();
54 BaseFinalRelease();
55}
56
57// public initializer/uninitializer for internal purposes only
58////////////////////////////////////////////////////////////////////////////////
59
60/**
61 * Initializes the network adapter object.
62 *
63 * @param aParent Handle of the parent object.
64 */
65HRESULT NetworkAdapter::init(Machine *aParent, ULONG aSlot)
66{
67 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
68
69 ComAssertRet(aParent, E_INVALIDARG);
70 ComAssertRet(aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
71
72 /* Enclose the state transition NotReady->InInit->Ready */
73 AutoInitSpan autoInitSpan(this);
74 AssertReturn(autoInitSpan.isOk(), E_FAIL);
75
76 unconst(mParent) = aParent;
77 unconst(mNATEngine).createObject();
78 mNATEngine->init(aParent, this);
79 /* mPeer is left null */
80
81 m_fModified = false;
82
83 mData.allocate();
84
85 /* initialize data */
86 mData->mSlot = aSlot;
87
88 /* Default limit is not capped/unlimited. */
89 mData->mBandwidthLimit = 0;
90
91 /* default to Am79C973 */
92 mData->mAdapterType = NetworkAdapterType_Am79C973;
93
94 /* generate the MAC address early to guarantee it is the same both after
95 * changing some other property (i.e. after mData.backup()) and after the
96 * subsequent mData.rollback(). */
97 generateMACAddress();
98
99 /* Confirm a successful initialization */
100 autoInitSpan.setSucceeded();
101
102 return S_OK;
103}
104
105/**
106 * Initializes the network adapter object given another network adapter object
107 * (a kind of copy constructor). This object shares data with
108 * the object passed as an argument.
109 *
110 * @note This object must be destroyed before the original object
111 * it shares data with is destroyed.
112 *
113 * @note Locks @a aThat object for reading.
114 */
115HRESULT NetworkAdapter::init(Machine *aParent, NetworkAdapter *aThat)
116{
117 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
118
119 ComAssertRet(aParent && aThat, E_INVALIDARG);
120
121 /* Enclose the state transition NotReady->InInit->Ready */
122 AutoInitSpan autoInitSpan(this);
123 AssertReturn(autoInitSpan.isOk(), E_FAIL);
124
125 unconst(mParent) = aParent;
126 unconst(mPeer) = aThat;
127 unconst(mNATEngine).createObject();
128 mNATEngine->init(aParent, this, aThat->mNATEngine);
129
130 AutoCaller thatCaller (aThat);
131 AssertComRCReturnRC(thatCaller.rc());
132
133 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
134 mData.share (aThat->mData);
135
136 /* Confirm a successful initialization */
137 autoInitSpan.setSucceeded();
138
139 return S_OK;
140}
141
142/**
143 * Initializes the guest object given another guest object
144 * (a kind of copy constructor). This object makes a private copy of data
145 * of the original object passed as an argument.
146 *
147 * @note Locks @a aThat object for reading.
148 */
149HRESULT NetworkAdapter::initCopy(Machine *aParent, NetworkAdapter *aThat)
150{
151 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
152
153 ComAssertRet(aParent && aThat, E_INVALIDARG);
154
155 /* Enclose the state transition NotReady->InInit->Ready */
156 AutoInitSpan autoInitSpan(this);
157 AssertReturn(autoInitSpan.isOk(), E_FAIL);
158
159 unconst(mParent) = aParent;
160 /* mPeer is left null */
161
162 unconst(mNATEngine).createObject();
163 mNATEngine->initCopy(aParent, this, aThat->mNATEngine);
164
165 AutoCaller thatCaller (aThat);
166 AssertComRCReturnRC(thatCaller.rc());
167
168 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
169 mData.attachCopy (aThat->mData);
170
171 /* Confirm a successful initialization */
172 autoInitSpan.setSucceeded();
173
174 return S_OK;
175}
176
177/**
178 * Uninitializes the instance and sets the ready flag to FALSE.
179 * Called either from FinalRelease() or by the parent when it gets destroyed.
180 */
181void NetworkAdapter::uninit()
182{
183 LogFlowThisFunc(("\n"));
184
185 /* Enclose the state transition Ready->InUninit->NotReady */
186 AutoUninitSpan autoUninitSpan(this);
187 if (autoUninitSpan.uninitDone())
188 return;
189
190 mData.free();
191
192 unconst(mNATEngine).setNull();
193 unconst(mPeer) = NULL;
194 unconst(mParent) = NULL;
195}
196
197// INetworkAdapter properties
198////////////////////////////////////////////////////////////////////////////////
199
200STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
201{
202 CheckComArgOutPointerValid(aAdapterType);
203
204 AutoCaller autoCaller(this);
205 if (FAILED(autoCaller.rc())) return autoCaller.rc();
206
207 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
208
209 *aAdapterType = mData->mAdapterType;
210
211 return S_OK;
212}
213
214STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
215{
216 AutoCaller autoCaller(this);
217 if (FAILED(autoCaller.rc())) return autoCaller.rc();
218
219 /* the machine needs to be mutable */
220 AutoMutableStateDependency adep(mParent);
221 if (FAILED(adep.rc())) return adep.rc();
222
223 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
224
225 /* make sure the value is allowed */
226 switch (aAdapterType)
227 {
228 case NetworkAdapterType_Am79C970A:
229 case NetworkAdapterType_Am79C973:
230#ifdef VBOX_WITH_E1000
231 case NetworkAdapterType_I82540EM:
232 case NetworkAdapterType_I82543GC:
233 case NetworkAdapterType_I82545EM:
234#endif
235#ifdef VBOX_WITH_VIRTIO
236 case NetworkAdapterType_Virtio:
237#endif /* VBOX_WITH_VIRTIO */
238 break;
239 default:
240 return setError(E_FAIL,
241 tr("Invalid network adapter type '%d'"),
242 aAdapterType);
243 }
244
245 if (mData->mAdapterType != aAdapterType)
246 {
247 mData.backup();
248 mData->mAdapterType = aAdapterType;
249
250 m_fModified = true;
251 // leave the lock before informing callbacks
252 alock.release();
253
254 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
255 mParent->setModified(Machine::IsModified_NetworkAdapters);
256 mlock.release();
257
258 /* Changing the network adapter type during runtime is not allowed,
259 * therefore no immediate change in CFGM logic => changeAdapter=FALSE. */
260 mParent->onNetworkAdapterChange(this, FALSE);
261 }
262
263 return S_OK;
264}
265
266STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
267{
268 CheckComArgOutPointerValid(aSlot);
269
270 AutoCaller autoCaller(this);
271 if (FAILED(autoCaller.rc())) return autoCaller.rc();
272
273 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
274
275 *aSlot = mData->mSlot;
276
277 return S_OK;
278}
279
280STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
281{
282 CheckComArgOutPointerValid(aEnabled);
283
284 AutoCaller autoCaller(this);
285 if (FAILED(autoCaller.rc())) return autoCaller.rc();
286
287 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
288
289 *aEnabled = mData->mEnabled;
290
291 return S_OK;
292}
293
294STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
295{
296 AutoCaller autoCaller(this);
297 if (FAILED(autoCaller.rc())) return autoCaller.rc();
298
299 /* the machine needs to be mutable */
300 AutoMutableStateDependency adep(mParent);
301 if (FAILED(adep.rc())) return adep.rc();
302
303 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
304
305 if (mData->mEnabled != aEnabled)
306 {
307 mData.backup();
308 mData->mEnabled = aEnabled;
309
310 m_fModified = true;
311 // leave the lock before informing callbacks
312 alock.release();
313
314 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
315 mParent->setModified(Machine::IsModified_NetworkAdapters);
316 mlock.release();
317
318 /* Disabling the network adapter during runtime is not allowed
319 * therefore no immediate change in CFGM logic => changeAdapter=FALSE. */
320 mParent->onNetworkAdapterChange(this, FALSE);
321 }
322
323 return S_OK;
324}
325
326STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress)
327{
328 CheckComArgOutPointerValid(aMACAddress);
329
330 AutoCaller autoCaller(this);
331 if (FAILED(autoCaller.rc())) return autoCaller.rc();
332
333 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
334
335 ComAssertRet(!mData->mMACAddress.isEmpty(), E_FAIL);
336
337 mData->mMACAddress.cloneTo(aMACAddress);
338
339 return S_OK;
340}
341
342STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress)
343{
344 AutoCaller autoCaller(this);
345 if (FAILED(autoCaller.rc())) return autoCaller.rc();
346
347 /* the machine needs to be mutable */
348 AutoMutableStateDependency adep(mParent);
349 if (FAILED(adep.rc())) return adep.rc();
350
351 HRESULT rc = S_OK;
352 bool emitChangeEvent = false;
353
354 /*
355 * Are we supposed to generate a MAC?
356 */
357 if (!aMACAddress || !*aMACAddress)
358 {
359 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
360 mData.backup();
361
362 generateMACAddress();
363 emitChangeEvent = true;
364
365 m_fModified = true;
366 // leave the lock before informing callbacks
367 alock.release();
368
369 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
370 mParent->setModified(Machine::IsModified_NetworkAdapters);
371 mlock.release();
372 }
373 else
374 {
375 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
376 if (mData->mMACAddress != aMACAddress)
377 {
378 /*
379 * Verify given MAC address
380 */
381 Utf8Str macAddressUtf = aMACAddress;
382 char *macAddressStr = macAddressUtf.mutableRaw();
383 int i = 0;
384 while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK))
385 {
386 char c = *macAddressStr;
387 /* canonicalize hex digits to capital letters */
388 if (c >= 'a' && c <= 'f')
389 {
390 /** @todo the runtime lacks an ascii lower/upper conv */
391 c &= 0xdf;
392 *macAddressStr = c;
393 }
394 /* we only accept capital letters */
395 if (((c < '0') || (c > '9')) &&
396 ((c < 'A') || (c > 'F')))
397 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
398 /* the second digit must have even value for unicast addresses */
399 if ((i == 1) && (!!(c & 1) == (c >= '0' && c <= '9')))
400 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
401
402 macAddressStr++;
403 i++;
404 }
405 /* we must have parsed exactly 12 characters */
406 if (i != 12)
407 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
408
409 if (SUCCEEDED(rc))
410 {
411 mData.backup();
412
413 mData->mMACAddress = macAddressUtf;
414
415 emitChangeEvent = true;
416
417 m_fModified = true;
418 // leave the lock before informing callbacks
419 alock.release();
420
421 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
422 mParent->setModified(Machine::IsModified_NetworkAdapters);
423 mlock.release();
424 }
425 }
426 }
427
428 // we have left the lock in any case at this point
429
430 if (emitChangeEvent)
431 {
432 /* Changing the MAC via the Main API during runtime is not allowed,
433 * therefore no immediate change in CFGM logic => changeAdapter=FALSE. */
434 mParent->onNetworkAdapterChange(this, FALSE);
435 }
436
437 return rc;
438}
439
440STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
441 NetworkAttachmentType_T *aAttachmentType)
442{
443 CheckComArgOutPointerValid(aAttachmentType);
444
445 AutoCaller autoCaller(this);
446 if (FAILED(autoCaller.rc())) return autoCaller.rc();
447
448 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
449
450 *aAttachmentType = mData->mAttachmentType;
451
452 return S_OK;
453}
454
455STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
456{
457 CheckComArgOutPointerValid(aHostInterface);
458
459 AutoCaller autoCaller(this);
460 if (FAILED(autoCaller.rc())) return autoCaller.rc();
461
462 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
463
464 mData->mHostInterface.cloneTo(aHostInterface);
465
466 return S_OK;
467}
468
469STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface)
470{
471 Bstr bstrEmpty("");
472 if (!aHostInterface)
473 aHostInterface = bstrEmpty.raw();
474
475 AutoCaller autoCaller(this);
476 if (FAILED(autoCaller.rc())) return autoCaller.rc();
477
478 /* the machine needs to be mutable */
479 AutoMutableStateDependency adep(mParent);
480 if (FAILED(adep.rc())) return adep.rc();
481
482 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
483
484 if (mData->mHostInterface != aHostInterface)
485 {
486 mData.backup();
487 mData->mHostInterface = aHostInterface;
488
489 m_fModified = true;
490 // leave the lock before informing callbacks
491 alock.release();
492
493 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
494 mParent->setModified(Machine::IsModified_NetworkAdapters);
495 mlock.release();
496
497 /* When changing the host adapter, adapt the CFGM logic to make this
498 * change immediately effect and to notify the guest that the network
499 * might have changed, therefore changeAdapter=TRUE. */
500 mParent->onNetworkAdapterChange(this, TRUE);
501 }
502
503 return S_OK;
504}
505
506STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
507{
508 CheckComArgOutPointerValid(aInternalNetwork);
509
510 AutoCaller autoCaller(this);
511 if (FAILED(autoCaller.rc())) return autoCaller.rc();
512
513 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
514
515 mData->mInternalNetwork.cloneTo(aInternalNetwork);
516
517 return S_OK;
518}
519
520STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwork)
521{
522 AutoCaller autoCaller(this);
523 if (FAILED(autoCaller.rc())) return autoCaller.rc();
524
525 /* the machine needs to be mutable */
526 AutoMutableStateDependency adep(mParent);
527 if (FAILED(adep.rc())) return adep.rc();
528
529 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
530
531 if (mData->mInternalNetwork != aInternalNetwork)
532 {
533 /* if an empty/null string is to be set, internal networking must be
534 * turned off */
535 if ( (aInternalNetwork == NULL || *aInternalNetwork == '\0')
536 && mData->mAttachmentType == NetworkAttachmentType_Internal)
537 {
538 return setError(E_FAIL,
539 tr("Empty or null internal network name is not valid"));
540 }
541
542 mData.backup();
543 mData->mInternalNetwork = aInternalNetwork;
544
545 m_fModified = true;
546 // leave the lock before informing callbacks
547 alock.release();
548
549 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
550 mParent->setModified(Machine::IsModified_NetworkAdapters);
551 mlock.release();
552
553 /* When changing the internal network, adapt the CFGM logic to make this
554 * change immediately effect and to notify the guest that the network
555 * might have changed, therefore changeAdapter=TRUE. */
556 mParent->onNetworkAdapterChange(this, TRUE);
557 }
558
559 return S_OK;
560}
561
562STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
563{
564 CheckComArgOutPointerValid(aNATNetwork);
565
566 AutoCaller autoCaller(this);
567 if (FAILED(autoCaller.rc())) return autoCaller.rc();
568
569 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
570
571 mData->mNATNetwork.cloneTo(aNATNetwork);
572
573 return S_OK;
574}
575
576STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork)
577{
578 Bstr bstrEmpty("");
579 if (!aNATNetwork)
580 aNATNetwork = bstrEmpty.raw();
581
582 AutoCaller autoCaller(this);
583 if (FAILED(autoCaller.rc())) return autoCaller.rc();
584
585 /* the machine needs to be mutable */
586 AutoMutableStateDependency adep(mParent);
587 if (FAILED(adep.rc())) return adep.rc();
588
589 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
590
591 if (mData->mNATNetwork != aNATNetwork)
592 {
593 mData.backup();
594 mData->mNATNetwork = aNATNetwork;
595
596 m_fModified = true;
597 // leave the lock before informing callbacks
598 alock.release();
599
600 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
601 mParent->setModified(Machine::IsModified_NetworkAdapters);
602 mlock.release();
603
604 /* Changing the NAT network isn't allowed during runtime, therefore
605 * no immediate replug in CFGM logic => changeAdapter=FALSE */
606 mParent->onNetworkAdapterChange(this, FALSE);
607 }
608
609 return S_OK;
610}
611
612STDMETHODIMP NetworkAdapter::COMGETTER(VDENetwork) (BSTR *aVDENetwork)
613{
614#if defined(VBOX_WITH_VDE)
615 CheckComArgOutPointerValid(aVDENetwork);
616
617 AutoCaller autoCaller(this);
618 if (FAILED(autoCaller.rc())) return autoCaller.rc();
619
620 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
621
622 mData->mVDENetwork.cloneTo(aVDENetwork);
623
624 return S_OK;
625#else
626 NOREF(aVDENetwork);
627 return E_NOTIMPL;
628#endif
629}
630
631STDMETHODIMP NetworkAdapter::COMSETTER(VDENetwork) (IN_BSTR aVDENetwork)
632{
633#if defined(VBOX_WITH_VDE)
634 Bstr bstrEmpty("");
635 if (!aVDENetwork)
636 aVDENetwork = bstrEmpty.raw();
637
638 AutoCaller autoCaller(this);
639 if (FAILED(autoCaller.rc())) return autoCaller.rc();
640
641 /* the machine needs to be mutable */
642 AutoMutableStateDependency adep (mParent);
643 if (FAILED(adep.rc())) return adep.rc();
644
645 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
646
647 if (mData->mVDENetwork != aVDENetwork)
648 {
649 mData.backup();
650 mData->mVDENetwork = aVDENetwork;
651
652 /* leave the lock before informing callbacks */
653 alock.release();
654
655 mParent->onNetworkAdapterChange (this, FALSE);
656 }
657
658 return S_OK;
659#else
660 NOREF(aVDENetwork);
661 return E_NOTIMPL;
662#endif
663}
664
665STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
666{
667 CheckComArgOutPointerValid(aConnected);
668
669 AutoCaller autoCaller(this);
670 if (FAILED(autoCaller.rc())) return autoCaller.rc();
671
672 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
673
674 *aConnected = mData->mCableConnected;
675
676 return S_OK;
677}
678
679STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
680{
681 AutoCaller autoCaller(this);
682 if (FAILED(autoCaller.rc())) return autoCaller.rc();
683
684 /* the machine needs to be mutable */
685 AutoMutableStateDependency adep(mParent);
686 if (FAILED(adep.rc())) return adep.rc();
687
688 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
689
690 if (aConnected != mData->mCableConnected)
691 {
692 mData.backup();
693 mData->mCableConnected = aConnected;
694
695 m_fModified = true;
696 // leave the lock before informing callbacks
697 alock.release();
698
699 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
700 mParent->setModified(Machine::IsModified_NetworkAdapters);
701 mlock.release();
702
703 /* No change in CFGM logic => changeAdapter=FALSE. */
704 mParent->onNetworkAdapterChange(this, FALSE);
705 }
706
707 return S_OK;
708}
709
710STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
711{
712 CheckComArgOutPointerValid(aSpeed);
713
714 AutoCaller autoCaller(this);
715 if (FAILED(autoCaller.rc())) return autoCaller.rc();
716
717 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
718
719 *aSpeed = mData->mLineSpeed;
720
721 return S_OK;
722}
723
724STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
725{
726 AutoCaller autoCaller(this);
727 if (FAILED(autoCaller.rc())) return autoCaller.rc();
728
729 /* the machine needs to be mutable */
730 AutoMutableStateDependency adep(mParent);
731 if (FAILED(adep.rc())) return adep.rc();
732
733 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
734
735 if (aSpeed != mData->mLineSpeed)
736 {
737 mData.backup();
738 mData->mLineSpeed = aSpeed;
739
740 m_fModified = true;
741 // leave the lock before informing callbacks
742 alock.release();
743
744 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
745 mParent->setModified(Machine::IsModified_NetworkAdapters);
746 mlock.release();
747
748 /* No change in CFGM logic => changeAdapter=FALSE. */
749 mParent->onNetworkAdapterChange(this, FALSE);
750 }
751
752 return S_OK;
753}
754
755STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthLimit) (ULONG *aLimit)
756{
757 CheckComArgOutPointerValid(aLimit);
758
759 AutoCaller autoCaller(this);
760 if (FAILED(autoCaller.rc())) return autoCaller.rc();
761
762 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
763
764 *aLimit = mData->mBandwidthLimit;
765 return S_OK;
766}
767
768STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthLimit) (ULONG aLimit)
769{
770 AutoCaller autoCaller(this);
771 if (FAILED(autoCaller.rc())) return autoCaller.rc();
772
773 /* the machine doesn't need to be mutable */
774
775 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
776
777 if (aLimit != mData->mBandwidthLimit)
778 {
779 mData.backup();
780 mData->mBandwidthLimit = aLimit;
781
782 m_fModified = true;
783 // leave the lock before informing callbacks
784 alock.release();
785
786 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
787 mParent->setModified(Machine::IsModified_NetworkAdapters);
788 mlock.release();
789
790 /* No change in CFGM logic => changeAdapter=FALSE. */
791 mParent->onNetworkAdapterChange(this, FALSE);
792 }
793 return S_OK;
794}
795
796STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
797{
798 CheckComArgOutPointerValid(aEnabled);
799
800 AutoCaller autoCaller(this);
801 if (FAILED(autoCaller.rc())) return autoCaller.rc();
802
803 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
804
805 *aEnabled = mData->mTraceEnabled;
806 return S_OK;
807}
808
809STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
810{
811 AutoCaller autoCaller(this);
812 if (FAILED(autoCaller.rc())) return autoCaller.rc();
813
814 /* the machine needs to be mutable */
815 AutoMutableStateDependency adep(mParent);
816 if (FAILED(adep.rc())) return adep.rc();
817
818 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
819
820 if (aEnabled != mData->mTraceEnabled)
821 {
822 mData.backup();
823 mData->mTraceEnabled = aEnabled;
824
825 m_fModified = true;
826 // leave the lock before informing callbacks
827 alock.release();
828
829 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
830 mParent->setModified(Machine::IsModified_NetworkAdapters);
831 mlock.release();
832
833 /* Adapt the CFGM logic changeAdapter=TRUE */
834 mParent->onNetworkAdapterChange(this, TRUE);
835 }
836
837 return S_OK;
838}
839
840STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
841{
842 CheckComArgOutPointerValid(aTraceFile);
843
844 AutoCaller autoCaller(this);
845 if (FAILED(autoCaller.rc())) return autoCaller.rc();
846
847 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
848
849 mData->mTraceFile.cloneTo(aTraceFile);
850
851 return S_OK;
852}
853
854STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
855{
856 AutoCaller autoCaller(this);
857 if (FAILED(autoCaller.rc())) return autoCaller.rc();
858
859 /* the machine needs to be mutable */
860 AutoMutableStateDependency adep(mParent);
861 if (FAILED(adep.rc())) return adep.rc();
862
863 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
864
865 if (mData->mTraceFile != aTraceFile)
866 {
867 mData.backup();
868 mData->mTraceFile = aTraceFile;
869
870 m_fModified = true;
871 // leave the lock before informing callbacks
872 alock.release();
873
874 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
875 mParent->setModified(Machine::IsModified_NetworkAdapters);
876 mlock.release();
877
878 /* No change in CFGM logic => changeAdapter=FALSE. */
879 mParent->onNetworkAdapterChange(this, FALSE);
880 }
881
882 return S_OK;
883}
884
885STDMETHODIMP NetworkAdapter::COMGETTER(NatDriver) (INATEngine **aNatDriver)
886{
887 CheckComArgOutPointerValid(aNatDriver);
888
889 AutoCaller autoCaller(this);
890 if (FAILED(autoCaller.rc())) return autoCaller.rc();
891
892 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
893
894 mNATEngine.queryInterfaceTo(aNatDriver);
895
896 return S_OK;
897}
898
899STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority) (ULONG *aBootPriority)
900{
901 CheckComArgOutPointerValid(aBootPriority);
902
903 AutoCaller autoCaller(this);
904 if (FAILED(autoCaller.rc())) return autoCaller.rc();
905
906 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
907
908 *aBootPriority = mData->mBootPriority;
909
910 return S_OK;
911}
912
913STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority) (ULONG aBootPriority)
914{
915 AutoCaller autoCaller(this);
916 if (FAILED(autoCaller.rc())) return autoCaller.rc();
917
918 /* the machine needs to be mutable */
919 AutoMutableStateDependency adep(mParent);
920 if (FAILED(adep.rc())) return adep.rc();
921
922 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
923
924 if (aBootPriority != mData->mBootPriority)
925 {
926 mData.backup();
927 mData->mBootPriority = aBootPriority;
928
929 m_fModified = true;
930 // leave the lock before informing callbacks
931 alock.release();
932
933 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
934 mParent->setModified(Machine::IsModified_NetworkAdapters);
935 mlock.release();
936
937 /* No change in CFGM logic => changeAdapter=FALSE. */
938 mParent->onNetworkAdapterChange(this, FALSE);
939 }
940
941 return S_OK;
942}
943
944// INetworkAdapter methods
945////////////////////////////////////////////////////////////////////////////////
946
947STDMETHODIMP NetworkAdapter::AttachToNAT()
948{
949 AutoCaller autoCaller(this);
950 if (FAILED(autoCaller.rc())) return autoCaller.rc();
951
952 /* the machine needs to be mutable */
953 AutoMutableStateDependency adep(mParent);
954 if (FAILED(adep.rc())) return adep.rc();
955
956 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
957
958 if (mData->mAttachmentType != NetworkAttachmentType_NAT)
959 {
960 mData.backup();
961
962 // Commented this for now as it resets the parameter mData->mNATNetwork
963 // which is essential while changing the Attachment dynamically.
964 //detach();
965
966 mData->mAttachmentType = NetworkAttachmentType_NAT;
967
968 m_fModified = true;
969 // leave the lock before informing callbacks
970 alock.release();
971
972 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
973 mParent->setModified(Machine::IsModified_NetworkAdapters);
974 mlock.release();
975
976 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
977 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
978 if (FAILED(rc))
979 {
980 /* If changing the attachment failed then we can't assume
981 * that the previous attachment will attach correctly
982 * and thus return error along with detaching all
983 * attachments.
984 */
985 Detach();
986 return rc;
987 }
988 }
989
990 return S_OK;
991}
992
993STDMETHODIMP NetworkAdapter::AttachToBridgedInterface()
994{
995 AutoCaller autoCaller(this);
996 if (FAILED(autoCaller.rc())) return autoCaller.rc();
997
998 /* the machine needs to be mutable */
999 AutoMutableStateDependency adep(mParent);
1000 if (FAILED(adep.rc())) return adep.rc();
1001
1002 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1003
1004 /* don't do anything if we're already host interface attached */
1005 if (mData->mAttachmentType != NetworkAttachmentType_Bridged)
1006 {
1007 mData.backup();
1008
1009 /* first detach the current attachment */
1010 // Commented this for now as it reset the parameter mData->mHostInterface
1011 // which is essential while changing the Attachment dynamically.
1012 //detach();
1013
1014 mData->mAttachmentType = NetworkAttachmentType_Bridged;
1015
1016 m_fModified = true;
1017 // leave the lock before informing callbacks
1018 alock.release();
1019
1020 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1021 mParent->setModified(Machine::IsModified_NetworkAdapters);
1022 mlock.release();
1023
1024 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1025 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1026 if (FAILED(rc))
1027 {
1028 /* If changing the attachment failed then we can't assume that the
1029 * previous attachment will attach correctly and thus return error
1030 * along with detaching all attachments.
1031 */
1032 Detach();
1033 return rc;
1034 }
1035 }
1036
1037 return S_OK;
1038}
1039
1040STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
1041{
1042 AutoCaller autoCaller(this);
1043 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1044
1045 /* the machine needs to be mutable */
1046 AutoMutableStateDependency adep(mParent);
1047 if (FAILED(adep.rc())) return adep.rc();
1048
1049 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1050
1051 /* don't do anything if we're already internal network attached */
1052 if (mData->mAttachmentType != NetworkAttachmentType_Internal)
1053 {
1054 mData.backup();
1055
1056 /* first detach the current attachment */
1057 // Commented this for now as it reset the parameter mData->mInternalNetwork
1058 // which is essential while changing the Attachment dynamically.
1059 //detach();
1060
1061 /* there must an internal network name */
1062 if (mData->mInternalNetwork.isEmpty())
1063 {
1064 LogRel (("Internal network name not defined, "
1065 "setting to default \"intnet\"\n"));
1066 mData->mInternalNetwork = "intnet";
1067 }
1068
1069 mData->mAttachmentType = NetworkAttachmentType_Internal;
1070
1071 m_fModified = true;
1072 // leave the lock before informing callbacks
1073 alock.release();
1074
1075 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1076 mParent->setModified(Machine::IsModified_NetworkAdapters);
1077 mlock.release();
1078
1079 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1080 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1081 if (FAILED(rc))
1082 {
1083 /* If changing the attachment failed then we can't assume
1084 * that the previous attachment will attach correctly
1085 * and thus return error along with detaching all
1086 * attachments.
1087 */
1088 Detach();
1089 return rc;
1090 }
1091 }
1092
1093 return S_OK;
1094}
1095
1096STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface()
1097{
1098 AutoCaller autoCaller(this);
1099 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1100
1101 /* the machine needs to be mutable */
1102 AutoMutableStateDependency adep(mParent);
1103 if (FAILED(adep.rc())) return adep.rc();
1104
1105 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1106
1107 /* don't do anything if we're already host interface attached */
1108 if (mData->mAttachmentType != NetworkAttachmentType_HostOnly)
1109 {
1110 mData.backup();
1111
1112 /* first detach the current attachment */
1113 // Commented this for now as it reset the parameter mData->mHostInterface
1114 // which is essential while changing the Attachment dynamically.
1115 //detach();
1116
1117 mData->mAttachmentType = NetworkAttachmentType_HostOnly;
1118
1119 m_fModified = true;
1120 // leave the lock before informing callbacks
1121 alock.release();
1122
1123 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1124 mParent->setModified(Machine::IsModified_NetworkAdapters);
1125 mlock.release();
1126
1127 /* Adapt the CFGM logic and notify the guest => changeAdpater=TRUE. */
1128 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1129 if (FAILED(rc))
1130 {
1131 /* If changing the attachment failed then we can't assume
1132 * that the previous attachment will attach correctly
1133 * and thus return error along with detaching all
1134 * attachments.
1135 */
1136 Detach();
1137 return rc;
1138 }
1139 }
1140
1141 return S_OK;
1142}
1143
1144STDMETHODIMP NetworkAdapter::AttachToVDE()
1145{
1146#if defined(VBOX_WITH_VDE)
1147 AutoCaller autoCaller(this);
1148 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1149
1150 /* the machine needs to be mutable */
1151 AutoMutableStateDependency adep (mParent);
1152 if (FAILED(adep.rc())) return adep.rc();
1153
1154 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1155
1156 /* don't do anything if we're already host interface attached */
1157 if (mData->mAttachmentType != NetworkAttachmentType_VDE)
1158 {
1159 mData.backup();
1160
1161 /* first detach the current attachment */
1162 // Commented this for now as it reset the parameter mData->mHostInterface
1163 // which is essential while changing the Attachment dynamically.
1164 //detach();
1165
1166 mData->mAttachmentType = NetworkAttachmentType_VDE;
1167
1168 /* leave the lock before informing callbacks */
1169 alock.release();
1170
1171 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
1172 if (FAILED (rc))
1173 {
1174 /* If changing the attachment failed then we can't assume
1175 * that the previous attachment will attach correctly
1176 * and thus return error along with detaching all
1177 * attachments.
1178 */
1179 Detach();
1180 return rc;
1181 }
1182 }
1183
1184 return S_OK;
1185#else /* !VBOX_WITH_VDE */
1186 return E_NOTIMPL;
1187#endif
1188}
1189
1190STDMETHODIMP NetworkAdapter::Detach()
1191{
1192 AutoCaller autoCaller(this);
1193 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1194
1195 /* the machine needs to be mutable */
1196 AutoMutableStateDependency adep(mParent);
1197 if (FAILED(adep.rc())) return adep.rc();
1198
1199 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1200
1201 if (mData->mAttachmentType != NetworkAttachmentType_Null)
1202 {
1203 mData.backup();
1204
1205 detach();
1206
1207 m_fModified = true;
1208 // leave the lock before informing callbacks
1209 alock.release();
1210
1211 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1212 mParent->setModified(Machine::IsModified_NetworkAdapters);
1213 mlock.release();
1214
1215 /* adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1216 mParent->onNetworkAdapterChange(this, TRUE);
1217 }
1218
1219 return S_OK;
1220}
1221
1222// public methods only for internal purposes
1223////////////////////////////////////////////////////////////////////////////////
1224
1225/**
1226 * Loads settings from the given adapter node.
1227 * May be called once right after this object creation.
1228 *
1229 * @param aAdapterNode <Adapter> node.
1230 *
1231 * @note Locks this object for writing.
1232 */
1233HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
1234{
1235 AutoCaller autoCaller(this);
1236 AssertComRCReturnRC(autoCaller.rc());
1237
1238 /* Note: we assume that the default values for attributes of optional
1239 * nodes are assigned in the Data::Data() constructor and don't do it
1240 * here. It implies that this method may only be called after constructing
1241 * a new BIOSSettings object while all its data fields are in the default
1242 * values. Exceptions are fields whose creation time defaults don't match
1243 * values that should be applied when these fields are not explicitly set
1244 * in the settings file (for backwards compatibility reasons). This takes
1245 * place when a setting of a newly created object must default to A while
1246 * the same setting of an object loaded from the old settings file must
1247 * default to B. */
1248
1249 HRESULT rc = S_OK;
1250
1251 mData->mAdapterType = data.type;
1252 mData->mEnabled = data.fEnabled;
1253 /* MAC address (can be null) */
1254 rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress).raw());
1255 if (FAILED(rc)) return rc;
1256 /* cable (required) */
1257 mData->mCableConnected = data.fCableConnected;
1258 /* line speed (defaults to 100 Mbps) */
1259 mData->mLineSpeed = data.ulLineSpeed;
1260 /* tracing (defaults to false) */
1261 mData->mTraceEnabled = data.fTraceEnabled;
1262 mData->mTraceFile = data.strTraceFile;
1263 /* boot priority (defaults to 0, i.e. lowest) */
1264 mData->mBootPriority = data.ulBootPriority;
1265 /* Bandwidth limit in Mbps. */
1266 mData->mBandwidthLimit = data.ulBandwidthLimit;
1267
1268 switch (data.mode)
1269 {
1270 case NetworkAttachmentType_NAT:
1271 mNATEngine->loadSettings(data.nat);
1272 rc = AttachToNAT();
1273 if (FAILED(rc)) return rc;
1274 break;
1275
1276 case NetworkAttachmentType_Bridged:
1277 rc = COMSETTER(HostInterface)(Bstr(data.strName).raw());
1278 if (FAILED(rc)) return rc;
1279 rc = AttachToBridgedInterface();
1280 if (FAILED(rc)) return rc;
1281 break;
1282
1283 case NetworkAttachmentType_Internal:
1284 mData->mInternalNetwork = data.strName;
1285 Assert(!mData->mInternalNetwork.isEmpty());
1286
1287 rc = AttachToInternalNetwork();
1288 if (FAILED(rc)) return rc;
1289 break;
1290
1291 case NetworkAttachmentType_HostOnly:
1292#if defined(VBOX_WITH_NETFLT)
1293 rc = COMSETTER(HostInterface)(Bstr(data.strName).raw());
1294 if (FAILED(rc)) return rc;
1295#endif
1296 rc = AttachToHostOnlyInterface();
1297 if (FAILED(rc)) return rc;
1298 break;
1299
1300#if defined(VBOX_WITH_VDE)
1301 case NetworkAttachmentType_VDE:
1302 mData->mVDENetwork = data.strName;
1303 rc = AttachToVDE();
1304 if (FAILED(rc)) return rc;
1305 break;
1306#endif
1307
1308 case NetworkAttachmentType_Null:
1309 rc = Detach();
1310 if (FAILED(rc)) return rc;
1311 break;
1312 }
1313 if (data.fHasDisabledNAT)
1314 mNATEngine->loadSettings(data.nat);
1315
1316 // after loading settings, we are no longer different from the XML on disk
1317 m_fModified = false;
1318
1319 return S_OK;
1320}
1321
1322/**
1323 * Saves settings to the given adapter node.
1324 *
1325 * Note that the given Adapter node is completely empty on input.
1326 *
1327 * @param aAdapterNode <Adapter> node.
1328 *
1329 * @note Locks this object for reading.
1330 */
1331HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
1332{
1333 AutoCaller autoCaller(this);
1334 AssertComRCReturnRC(autoCaller.rc());
1335
1336 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1337
1338 data.fEnabled = !!mData->mEnabled;
1339 data.strMACAddress = mData->mMACAddress;
1340 data.fCableConnected = !!mData->mCableConnected;
1341
1342 data.ulLineSpeed = mData->mLineSpeed;
1343
1344 data.fTraceEnabled = !!mData->mTraceEnabled;
1345
1346 data.strTraceFile = mData->mTraceFile;
1347
1348 data.ulBootPriority = mData->mBootPriority;
1349
1350 data.ulBandwidthLimit = mData->mBandwidthLimit;
1351
1352 data.type = mData->mAdapterType;
1353
1354 switch (data.mode = mData->mAttachmentType)
1355 {
1356 case NetworkAttachmentType_Null:
1357 data.strName.setNull();
1358 break;
1359
1360 case NetworkAttachmentType_NAT:
1361 data.fHasDisabledNAT = 0;
1362 mNATEngine->commit();
1363 mNATEngine->saveSettings(data.nat);
1364 break;
1365
1366 case NetworkAttachmentType_Bridged:
1367 data.strName = mData->mHostInterface;
1368 break;
1369
1370 case NetworkAttachmentType_Internal:
1371 data.strName = mData->mInternalNetwork;
1372 break;
1373
1374 case NetworkAttachmentType_HostOnly:
1375 data.strName = mData->mHostInterface;
1376 break;
1377
1378#if defined(VBOX_WITH_VDE)
1379 case NetworkAttachmentType_VDE:
1380 data.strName = mData->mVDENetwork;
1381 break;
1382#endif
1383 }
1384
1385 if (data.mode != NetworkAttachmentType_NAT)
1386 {
1387 data.fHasDisabledNAT = 1; /* ??? */
1388 mNATEngine->commit();
1389 mNATEngine->saveSettings(data.nat);
1390 }
1391
1392 // after saving settings, we are no longer different from the XML on disk
1393 m_fModified = false;
1394
1395 return S_OK;
1396}
1397
1398/**
1399 * Returns true if any setter method has modified settings of this instance.
1400 * @return
1401 */
1402bool NetworkAdapter::isModified() {
1403 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1404 bool fChanged = m_fModified;
1405 fChanged |= (mData->mAdapterType == NetworkAttachmentType_NAT? mNATEngine->isModified() : false);
1406 return fChanged;
1407}
1408
1409/**
1410 * @note Locks this object for writing.
1411 */
1412void NetworkAdapter::rollback()
1413{
1414 /* sanity */
1415 AutoCaller autoCaller(this);
1416 AssertComRCReturnVoid(autoCaller.rc());
1417
1418 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1419
1420 mData.rollback();
1421}
1422
1423/**
1424 * @note Locks this object for writing, together with the peer object (also
1425 * for writing) if there is one.
1426 */
1427void NetworkAdapter::commit()
1428{
1429 /* sanity */
1430 AutoCaller autoCaller(this);
1431 AssertComRCReturnVoid (autoCaller.rc());
1432
1433 /* sanity too */
1434 AutoCaller peerCaller (mPeer);
1435 AssertComRCReturnVoid (peerCaller.rc());
1436
1437 /* lock both for writing since we modify both (mPeer is "master" so locked
1438 * first) */
1439 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1440
1441 if (mData.isBackedUp())
1442 {
1443 mData.commit();
1444 if (mPeer)
1445 {
1446 /* attach new data to the peer and reshare it */
1447 mPeer->mData.attach (mData);
1448 }
1449 }
1450}
1451
1452/**
1453 * @note Locks this object for writing, together with the peer object
1454 * represented by @a aThat (locked for reading).
1455 */
1456void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1457{
1458 AssertReturnVoid (aThat != NULL);
1459
1460 /* sanity */
1461 AutoCaller autoCaller(this);
1462 AssertComRCReturnVoid (autoCaller.rc());
1463
1464 /* sanity too */
1465 AutoCaller thatCaller (aThat);
1466 AssertComRCReturnVoid (thatCaller.rc());
1467
1468 /* peer is not modified, lock it for reading (aThat is "master" so locked
1469 * first) */
1470 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1471 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1472
1473 /* this will back up current data */
1474 mData.assignCopy (aThat->mData);
1475}
1476
1477void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
1478{
1479 AssertReturnVoid (aOsType != NULL);
1480
1481 /* sanity */
1482 AutoCaller autoCaller(this);
1483 AssertComRCReturnVoid (autoCaller.rc());
1484
1485 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1486
1487 bool e1000enabled = false;
1488#ifdef VBOX_WITH_E1000
1489 e1000enabled = true;
1490#endif // VBOX_WITH_E1000
1491
1492 NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1493
1494 /* Set default network adapter for this OS type */
1495 if (defaultType == NetworkAdapterType_I82540EM ||
1496 defaultType == NetworkAdapterType_I82543GC ||
1497 defaultType == NetworkAdapterType_I82545EM)
1498 {
1499 if (e1000enabled) mData->mAdapterType = defaultType;
1500 }
1501 else mData->mAdapterType = defaultType;
1502
1503 /* Enable and connect the first one adapter to the NAT */
1504 if (mData->mSlot == 0)
1505 {
1506 mData->mEnabled = true;
1507 mData->mAttachmentType = NetworkAttachmentType_NAT;
1508 mData->mCableConnected = true;
1509 }
1510}
1511
1512// private methods
1513////////////////////////////////////////////////////////////////////////////////
1514
1515/**
1516 * Worker routine for detach handling. No locking, no notifications.
1517
1518 * @note Must be called from under the object's write lock.
1519 */
1520void NetworkAdapter::detach()
1521{
1522 AssertReturnVoid (isWriteLockOnCurrentThread());
1523
1524 switch (mData->mAttachmentType)
1525 {
1526 case NetworkAttachmentType_Null:
1527 {
1528 /* nothing to do here */
1529 break;
1530 }
1531 case NetworkAttachmentType_NAT:
1532 {
1533 break;
1534 }
1535 case NetworkAttachmentType_Bridged:
1536 {
1537 /* reset handle and device name */
1538 mData->mHostInterface = "";
1539 break;
1540 }
1541 case NetworkAttachmentType_Internal:
1542 {
1543 mData->mInternalNetwork.setNull();
1544 break;
1545 }
1546 case NetworkAttachmentType_HostOnly:
1547 {
1548#if defined(VBOX_WITH_NETFLT)
1549 /* reset handle and device name */
1550 mData->mHostInterface = "";
1551#endif
1552 break;
1553 }
1554 }
1555
1556 mData->mAttachmentType = NetworkAttachmentType_Null;
1557}
1558
1559/**
1560 * Generates a new unique MAC address based on our vendor ID and
1561 * parts of a GUID.
1562 *
1563 * @note Must be called from under the object's write lock or within the init
1564 * span.
1565 */
1566void NetworkAdapter::generateMACAddress()
1567{
1568 /*
1569 * Our strategy is as follows: the first three bytes are our fixed
1570 * vendor ID (080027). The remaining 3 bytes will be taken from the
1571 * start of a GUID. This is a fairly safe algorithm.
1572 */
1573 char strMAC[13];
1574 Guid guid;
1575 guid.create();
1576 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1577 guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]);
1578 LogFlowThisFunc(("generated MAC: '%s'\n", strMAC));
1579 mData->mMACAddress = strMAC;
1580}
1581/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette