VirtualBox

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

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

NetworkAdapterImpl.cpp: revert r89338 (partly). No need to touch NAT network ref counts on bridged, host-only and internal network touch.

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