VirtualBox

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

Last change on this file since 40490 was 40490, checked in by vboxsync, 13 years ago

Main/NetworkAdapter: use the non-peer reference after commit, and not the peer one which would be the default behavior. The peer reference will become invalid after the session is closed

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

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