VirtualBox

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

Last change on this file since 45434 was 42825, checked in by vboxsync, 12 years ago

Main/Machine+NetworkAdapter: properly fix resizing of vector containing network adapters, previously it wasn't handling commit correctly. xtracker 5997

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