VirtualBox

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

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

Main/idl: new method IHost::generateMACAddress, including implementation

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

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