VirtualBox

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

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

Main/NetworkAdapter: Bandwidth group minor fixes (#5582)

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