VirtualBox

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

Last change on this file since 42719 was 42551, checked in by vboxsync, 12 years ago

Main: big API naming cleanup, use all caps acronyms everywhere, including SDK docs
Frontends/VBoxManage: implement guestcontrol execute for new API, disabled by default

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.1 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 42551 2012-08-02 16:44:39Z vboxsync $ */
2/** @file
3 * Implementation of INetworkAdapter in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2006-2012 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#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(NATEngine)(INATEngine **aNATEngine)
959{
960 CheckComArgOutPointerValid(aNATEngine);
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(aNATEngine);
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 mData->mBandwidthGroup = data.strBandwidthGroup;
1180 if (mData->mBandwidthGroup.isNotEmpty())
1181 {
1182 ComObjPtr<BandwidthGroup> group;
1183 rc = bwctl->getBandwidthGroupByName(data.strBandwidthGroup, group, true);
1184 if (FAILED(rc)) return rc;
1185 group->reference();
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 data.strBandwidthGroup = mData->mBandwidthGroup;
1237
1238 data.type = mData->mAdapterType;
1239
1240 data.mode = mData->mAttachmentType;
1241
1242 mNATEngine->commit();
1243 mNATEngine->saveSettings(data.nat);
1244
1245 data.strBridgedName = mData->mBridgedInterface;
1246
1247 data.strHostOnlyName = mData->mHostOnlyInterface;
1248
1249 data.strInternalNetworkName = mData->mInternalNetwork;
1250
1251 data.strGenericDriver = mData->mGenericDriver;
1252 data.genericProperties = mData->mGenericProperties;
1253
1254 // after saving settings, we are no longer different from the XML on disk
1255 m_fModified = false;
1256
1257 return S_OK;
1258}
1259
1260/**
1261 * Returns true if any setter method has modified settings of this instance.
1262 * @return
1263 */
1264bool NetworkAdapter::isModified() {
1265 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1266 bool fChanged = m_fModified;
1267 fChanged |= (mData->mAdapterType == NetworkAttachmentType_NAT? mNATEngine->isModified() : false);
1268 return fChanged;
1269}
1270
1271/**
1272 * @note Locks this object for writing.
1273 */
1274void NetworkAdapter::rollback()
1275{
1276 /* sanity */
1277 AutoCaller autoCaller(this);
1278 AssertComRCReturnVoid(autoCaller.rc());
1279
1280 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1281
1282 mData.rollback();
1283}
1284
1285/**
1286 * @note Locks this object for writing, together with the peer object (also
1287 * for writing) if there is one.
1288 */
1289void NetworkAdapter::commit()
1290{
1291 /* sanity */
1292 AutoCaller autoCaller(this);
1293 AssertComRCReturnVoid(autoCaller.rc());
1294
1295 /* sanity too */
1296 AutoCaller peerCaller(mPeer);
1297 AssertComRCReturnVoid(peerCaller.rc());
1298
1299 /* lock both for writing since we modify both (mPeer is "master" so locked
1300 * first) */
1301 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1302
1303 if (mData.isBackedUp())
1304 {
1305 mData.commit();
1306 if (mPeer)
1307 {
1308 /* attach new data to the peer and reshare it */
1309 mPeer->mData.attach(mData);
1310 }
1311 }
1312}
1313
1314/**
1315 * @note Locks this object for writing, together with the peer object
1316 * represented by @a aThat (locked for reading).
1317 */
1318void NetworkAdapter::copyFrom(NetworkAdapter *aThat)
1319{
1320 AssertReturnVoid(aThat != NULL);
1321
1322 /* sanity */
1323 AutoCaller autoCaller(this);
1324 AssertComRCReturnVoid(autoCaller.rc());
1325
1326 /* sanity too */
1327 AutoCaller thatCaller(aThat);
1328 AssertComRCReturnVoid(thatCaller.rc());
1329
1330 /* peer is not modified, lock it for reading (aThat is "master" so locked
1331 * first) */
1332 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1333 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1334
1335 /* this will back up current data */
1336 mData.assignCopy(aThat->mData);
1337}
1338
1339void NetworkAdapter::applyDefaults(GuestOSType *aOsType)
1340{
1341 AssertReturnVoid(aOsType != NULL);
1342
1343 /* sanity */
1344 AutoCaller autoCaller(this);
1345 AssertComRCReturnVoid(autoCaller.rc());
1346
1347 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1348
1349 bool e1000enabled = false;
1350#ifdef VBOX_WITH_E1000
1351 e1000enabled = true;
1352#endif // VBOX_WITH_E1000
1353
1354 NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1355
1356 /* Set default network adapter for this OS type */
1357 if (defaultType == NetworkAdapterType_I82540EM ||
1358 defaultType == NetworkAdapterType_I82543GC ||
1359 defaultType == NetworkAdapterType_I82545EM)
1360 {
1361 if (e1000enabled) mData->mAdapterType = defaultType;
1362 }
1363 else mData->mAdapterType = defaultType;
1364
1365 /* Enable and connect the first one adapter to the NAT */
1366 if (mData->mSlot == 0)
1367 {
1368 mData->mEnabled = true;
1369 mData->mAttachmentType = NetworkAttachmentType_NAT;
1370 mData->mCableConnected = true;
1371 }
1372}
1373
1374// private methods
1375////////////////////////////////////////////////////////////////////////////////
1376
1377/**
1378 * Generates a new unique MAC address based on our vendor ID and
1379 * parts of a GUID.
1380 *
1381 * @note Must be called from under the object's write lock or within the init
1382 * span.
1383 */
1384void NetworkAdapter::generateMACAddress()
1385{
1386 Utf8Str mac;
1387 Host::generateMACAddress(mac);
1388 LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str()));
1389 mData->mMACAddress = mac;
1390}
1391
1392STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthGroup)(IBandwidthGroup **aBwGroup)
1393{
1394 LogFlowThisFuncEnter();
1395 CheckComArgOutPointerValid(aBwGroup);
1396
1397 HRESULT hrc = S_OK;
1398
1399 AutoCaller autoCaller(this);
1400 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1401
1402 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1403
1404 if (mData->mBandwidthGroup.isNotEmpty())
1405 {
1406 ComObjPtr<BandwidthGroup> pBwGroup;
1407 hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pBwGroup, true /* fSetError */);
1408
1409 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
1410
1411 if (SUCCEEDED(hrc))
1412 pBwGroup.queryInterfaceTo(aBwGroup);
1413 }
1414
1415 LogFlowThisFuncLeave();
1416 return hrc;
1417}
1418
1419STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthGroup)(IBandwidthGroup *aBwGroup)
1420{
1421 LogFlowThisFuncEnter();
1422
1423 AutoCaller autoCaller(this);
1424 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1425
1426 /* the machine needs to be mutable */
1427 AutoMutableStateDependency adep(mParent);
1428 if (FAILED(adep.rc())) return adep.rc();
1429
1430 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1431
1432 Utf8Str strBwGroup;
1433 if (aBwGroup)
1434 strBwGroup = static_cast<BandwidthGroup*>(aBwGroup)->getName();
1435 if (mData->mBandwidthGroup != strBwGroup)
1436 {
1437 ComObjPtr<BandwidthGroup> pBwGroup;
1438 if (!strBwGroup.isEmpty())
1439 {
1440 HRESULT hrc = mParent->getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
1441 NOREF(hrc);
1442 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
1443 }
1444
1445 updateBandwidthGroup(pBwGroup);
1446
1447 m_fModified = true;
1448 // leave the lock before informing callbacks
1449 alock.release();
1450
1451 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1452 mParent->setModified(Machine::IsModified_NetworkAdapters);
1453 mlock.release();
1454
1455 /* TODO: changeAdapter=???. */
1456 mParent->onNetworkAdapterChange(this, FALSE);
1457 }
1458
1459 LogFlowThisFuncLeave();
1460 return S_OK;
1461}
1462
1463void NetworkAdapter::updateBandwidthGroup(BandwidthGroup *aBwGroup)
1464{
1465 LogFlowThisFuncEnter();
1466 Assert(isWriteLockOnCurrentThread());
1467
1468 ComObjPtr<BandwidthGroup> pOldBwGroup;
1469 if (!mData->mBandwidthGroup.isEmpty())
1470 {
1471 HRESULT hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pOldBwGroup, false /* fSetError */);
1472 NOREF(hrc);
1473 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
1474 }
1475
1476 mData.backup();
1477 if (!pOldBwGroup.isNull())
1478 {
1479 pOldBwGroup->release();
1480 mData->mBandwidthGroup = Utf8Str::Empty;
1481 }
1482
1483 if (aBwGroup)
1484 {
1485 mData->mBandwidthGroup = aBwGroup->getName();
1486 aBwGroup->reference();
1487 }
1488
1489 LogFlowThisFuncLeave();
1490}
1491/* 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