VirtualBox

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

Last change on this file since 49871 was 49871, checked in by vboxsync, 11 years ago

6813 - User server side API wrapper code in all interfaces.. stage 4 rev 1

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.9 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 49871 2013-12-10 16:49:59Z 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.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#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 NetworkAttachmentType_T oldAttachmentType = mData->mAttachmentType;
487 mData->mAttachmentType = aAttachmentType;
488
489 m_fModified = true;
490 // leave the lock before informing callbacks
491 alock.release();
492
493 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
494 mParent->setModified(Machine::IsModified_NetworkAdapters);
495 mlock.release();
496
497 if (oldAttachmentType == NetworkAttachmentType_NATNetwork)
498 checkAndSwitchFromNatNetworking(mData->mNATNetwork.raw());
499
500 if (aAttachmentType == NetworkAttachmentType_NATNetwork)
501 switchToNatNetworking(mData->mNATNetwork.raw());
502
503 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
504 mParent->onNetworkAdapterChange(this, TRUE);
505 }
506
507 return S_OK;
508}
509
510STDMETHODIMP NetworkAdapter::COMGETTER(BridgedInterface)(BSTR *aBridgedInterface)
511{
512 CheckComArgOutPointerValid(aBridgedInterface);
513
514 AutoCaller autoCaller(this);
515 if (FAILED(autoCaller.rc())) return autoCaller.rc();
516
517 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
518
519 mData->mBridgedInterface.cloneTo(aBridgedInterface);
520
521 return S_OK;
522}
523
524STDMETHODIMP NetworkAdapter::COMSETTER(BridgedInterface)(IN_BSTR aBridgedInterface)
525{
526 Bstr bstrEmpty("");
527 if (!aBridgedInterface)
528 aBridgedInterface = bstrEmpty.raw();
529
530 AutoCaller autoCaller(this);
531 if (FAILED(autoCaller.rc())) return autoCaller.rc();
532
533 /* the machine needs to be mutable */
534 AutoMutableStateDependency adep(mParent);
535 if (FAILED(adep.rc())) return adep.rc();
536
537 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
538
539 if (mData->mBridgedInterface != aBridgedInterface)
540 {
541 /* if an empty/null string is to be set, bridged interface must be
542 * turned off */
543 if ( (aBridgedInterface == NULL || *aBridgedInterface == '\0')
544 && mData->mAttachmentType == NetworkAttachmentType_Bridged)
545 {
546 return setError(E_FAIL,
547 tr("Empty or null bridged interface name is not valid"));
548 }
549
550 mData.backup();
551 mData->mBridgedInterface = aBridgedInterface;
552
553 m_fModified = true;
554 // leave the lock before informing callbacks
555 alock.release();
556
557 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
558 mParent->setModified(Machine::IsModified_NetworkAdapters);
559 mlock.release();
560
561 /* When changing the host adapter, adapt the CFGM logic to make this
562 * change immediately effect and to notify the guest that the network
563 * might have changed, therefore changeAdapter=TRUE. */
564 mParent->onNetworkAdapterChange(this, TRUE);
565 }
566
567 return S_OK;
568}
569
570STDMETHODIMP NetworkAdapter::COMGETTER(HostOnlyInterface)(BSTR *aHostOnlyInterface)
571{
572 CheckComArgOutPointerValid(aHostOnlyInterface);
573
574 AutoCaller autoCaller(this);
575 if (FAILED(autoCaller.rc())) return autoCaller.rc();
576
577 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
578
579 mData->mHostOnlyInterface.cloneTo(aHostOnlyInterface);
580
581 return S_OK;
582}
583
584STDMETHODIMP NetworkAdapter::COMSETTER(HostOnlyInterface)(IN_BSTR aHostOnlyInterface)
585{
586 Bstr bstrEmpty("");
587 if (!aHostOnlyInterface)
588 aHostOnlyInterface = bstrEmpty.raw();
589
590 AutoCaller autoCaller(this);
591 if (FAILED(autoCaller.rc())) return autoCaller.rc();
592
593 /* the machine needs to be mutable */
594 AutoMutableStateDependency adep(mParent);
595 if (FAILED(adep.rc())) return adep.rc();
596
597 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
598
599 if (mData->mHostOnlyInterface != aHostOnlyInterface)
600 {
601 /* if an empty/null string is to be set, host only interface must be
602 * turned off */
603 if ( (aHostOnlyInterface == NULL || *aHostOnlyInterface == '\0')
604 && mData->mAttachmentType == NetworkAttachmentType_HostOnly)
605 {
606 return setError(E_FAIL,
607 tr("Empty or null host only interface name is not valid"));
608 }
609
610 mData.backup();
611 mData->mHostOnlyInterface = aHostOnlyInterface;
612
613 m_fModified = true;
614 // leave the lock before informing callbacks
615 alock.release();
616
617 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
618 mParent->setModified(Machine::IsModified_NetworkAdapters);
619 mlock.release();
620
621 /* When changing the host adapter, adapt the CFGM logic to make this
622 * change immediately effect and to notify the guest that the network
623 * might have changed, therefore changeAdapter=TRUE. */
624 mParent->onNetworkAdapterChange(this, TRUE);
625 }
626
627 return S_OK;
628}
629
630STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork)(BSTR *aInternalNetwork)
631{
632 CheckComArgOutPointerValid(aInternalNetwork);
633
634 AutoCaller autoCaller(this);
635 if (FAILED(autoCaller.rc())) return autoCaller.rc();
636
637 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
638
639 mData->mInternalNetwork.cloneTo(aInternalNetwork);
640
641 return S_OK;
642}
643
644STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork)(IN_BSTR aInternalNetwork)
645{
646 AutoCaller autoCaller(this);
647 if (FAILED(autoCaller.rc())) return autoCaller.rc();
648
649 /* the machine needs to be mutable */
650 AutoMutableStateDependency adep(mParent);
651 if (FAILED(adep.rc())) return adep.rc();
652
653 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
654
655 if (mData->mInternalNetwork != aInternalNetwork)
656 {
657 /* if an empty/null string is to be set, internal networking must be
658 * turned off */
659 if ( (aInternalNetwork == NULL || *aInternalNetwork == '\0')
660 && mData->mAttachmentType == NetworkAttachmentType_Internal)
661 {
662 return setError(E_FAIL,
663 tr("Empty or null internal network name is not valid"));
664 }
665
666 mData.backup();
667 mData->mInternalNetwork = aInternalNetwork;
668
669 m_fModified = true;
670 // leave the lock before informing callbacks
671 alock.release();
672
673 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
674 mParent->setModified(Machine::IsModified_NetworkAdapters);
675 mlock.release();
676
677 /* When changing the internal network, adapt the CFGM logic to make this
678 * change immediately effect and to notify the guest that the network
679 * might have changed, therefore changeAdapter=TRUE. */
680 mParent->onNetworkAdapterChange(this, TRUE);
681 }
682
683 return S_OK;
684}
685
686STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork)(BSTR *aNATNetwork)
687{
688 CheckComArgOutPointerValid(aNATNetwork);
689
690 AutoCaller autoCaller(this);
691 if (FAILED(autoCaller.rc())) return autoCaller.rc();
692
693 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
694
695 mData->mNATNetwork.cloneTo(aNATNetwork);
696
697 return S_OK;
698}
699
700STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork)(IN_BSTR aNATNetwork)
701{
702 Bstr bstrEmpty("");
703 if (!aNATNetwork)
704 aNATNetwork = bstrEmpty.raw();
705
706 AutoCaller autoCaller(this);
707 if (FAILED(autoCaller.rc())) return autoCaller.rc();
708
709 /* the machine needs to be mutable */
710 AutoMutableStateDependency adep(mParent);
711 if (FAILED(adep.rc())) return adep.rc();
712
713 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
714
715 if (mData->mNATNetwork != aNATNetwork)
716 {
717
718 /* if an empty/null string is to be set, host only interface must be
719 * turned off */
720 if ( (aNATNetwork == NULL || *aNATNetwork == '\0')
721 && mData->mAttachmentType == NetworkAttachmentType_NATNetwork)
722 {
723 return setError(E_FAIL,
724 tr("Empty or null NAT network name is not valid"));
725 }
726
727 mData.backup();
728
729 Bstr oldNatNetworkName = mData->mNATNetwork;
730 mData->mNATNetwork = aNATNetwork;
731
732 m_fModified = true;
733 // leave the lock before informing callbacks
734 alock.release();
735
736 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
737 mParent->setModified(Machine::IsModified_NetworkAdapters);
738 mlock.release();
739
740 checkAndSwitchFromNatNetworking(oldNatNetworkName.raw());
741
742 switchToNatNetworking(aNATNetwork);
743
744 /* When changing the host adapter, adapt the CFGM logic to make this
745 * change immediately effect and to notify the guest that the network
746 * might have changed, therefore changeAdapter=TRUE. */
747 mParent->onNetworkAdapterChange(this, TRUE);
748 }
749
750 return S_OK;
751}
752
753STDMETHODIMP NetworkAdapter::COMGETTER(GenericDriver)(BSTR *aGenericDriver)
754{
755 CheckComArgOutPointerValid(aGenericDriver);
756
757 AutoCaller autoCaller(this);
758 if (FAILED(autoCaller.rc())) return autoCaller.rc();
759
760 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
761
762 mData->mGenericDriver.cloneTo(aGenericDriver);
763
764 return S_OK;
765}
766
767STDMETHODIMP NetworkAdapter::COMSETTER(GenericDriver)(IN_BSTR aGenericDriver)
768{
769 Bstr bstrEmpty("");
770 if (!aGenericDriver)
771 aGenericDriver = bstrEmpty.raw();
772
773 AutoCaller autoCaller(this);
774 if (FAILED(autoCaller.rc())) return autoCaller.rc();
775
776 /* the machine needs to be mutable */
777 AutoMutableStateDependency adep(mParent);
778 if (FAILED(adep.rc())) return adep.rc();
779
780 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
781
782 if (mData->mGenericDriver != aGenericDriver)
783 {
784 mData.backup();
785 mData->mGenericDriver = aGenericDriver;
786
787 /* leave the lock before informing callbacks */
788 alock.release();
789
790 mParent->onNetworkAdapterChange(this, FALSE);
791 }
792
793 return S_OK;
794}
795
796STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected)(BOOL *aConnected)
797{
798 CheckComArgOutPointerValid(aConnected);
799
800 AutoCaller autoCaller(this);
801 if (FAILED(autoCaller.rc())) return autoCaller.rc();
802
803 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
804
805 *aConnected = mData->mCableConnected;
806
807 return S_OK;
808}
809
810STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected)(BOOL aConnected)
811{
812 AutoCaller autoCaller(this);
813 if (FAILED(autoCaller.rc())) return autoCaller.rc();
814
815 /* the machine needs to be mutable */
816 AutoMutableStateDependency adep(mParent);
817 if (FAILED(adep.rc())) return adep.rc();
818
819 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
820
821 if (aConnected != mData->mCableConnected)
822 {
823 mData.backup();
824 mData->mCableConnected = aConnected;
825
826 m_fModified = true;
827 // leave the lock before informing callbacks
828 alock.release();
829
830 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
831 mParent->setModified(Machine::IsModified_NetworkAdapters);
832 mlock.release();
833
834 /* No change in CFGM logic => changeAdapter=FALSE. */
835 mParent->onNetworkAdapterChange(this, FALSE);
836 }
837
838 return S_OK;
839}
840
841STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed)(ULONG *aSpeed)
842{
843 CheckComArgOutPointerValid(aSpeed);
844
845 AutoCaller autoCaller(this);
846 if (FAILED(autoCaller.rc())) return autoCaller.rc();
847
848 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
849
850 *aSpeed = mData->mLineSpeed;
851
852 return S_OK;
853}
854
855STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed)(ULONG aSpeed)
856{
857 AutoCaller autoCaller(this);
858 if (FAILED(autoCaller.rc())) return autoCaller.rc();
859
860 /* the machine needs to be mutable */
861 AutoMutableStateDependency adep(mParent);
862 if (FAILED(adep.rc())) return adep.rc();
863
864 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
865
866 if (aSpeed != mData->mLineSpeed)
867 {
868 mData.backup();
869 mData->mLineSpeed = aSpeed;
870
871 m_fModified = true;
872 // leave the lock before informing callbacks
873 alock.release();
874
875 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
876 mParent->setModified(Machine::IsModified_NetworkAdapters);
877 mlock.release();
878
879 /* No change in CFGM logic => changeAdapter=FALSE. */
880 mParent->onNetworkAdapterChange(this, FALSE);
881 }
882
883 return S_OK;
884}
885
886
887STDMETHODIMP NetworkAdapter::COMGETTER(PromiscModePolicy)(NetworkAdapterPromiscModePolicy_T *aPromiscModePolicy)
888{
889 CheckComArgOutPointerValid(aPromiscModePolicy);
890
891 AutoCaller autoCaller(this);
892 HRESULT hrc = autoCaller.rc();
893 if (SUCCEEDED(hrc))
894 {
895 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
896 *aPromiscModePolicy = mData->mPromiscModePolicy;
897 }
898 return hrc;
899}
900
901STDMETHODIMP NetworkAdapter::COMSETTER(PromiscModePolicy)(NetworkAdapterPromiscModePolicy_T aPromiscModePolicy)
902{
903 switch (aPromiscModePolicy)
904 {
905 case NetworkAdapterPromiscModePolicy_Deny:
906 case NetworkAdapterPromiscModePolicy_AllowNetwork:
907 case NetworkAdapterPromiscModePolicy_AllowAll:
908 break;
909 default:
910 return setError(E_INVALIDARG, tr("Invalid promiscuous mode policy (%d)"), aPromiscModePolicy);
911 }
912
913 AutoCaller autoCaller(this);
914 HRESULT hrc = autoCaller.rc();
915
916 if (SUCCEEDED(hrc))
917 {
918 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
919 if (aPromiscModePolicy != mData->mPromiscModePolicy)
920 {
921 mData.backup();
922 mData->mPromiscModePolicy = aPromiscModePolicy;
923 m_fModified = true;
924
925 alock.release();
926 mParent->setModifiedLock(Machine::IsModified_NetworkAdapters);
927 mParent->onNetworkAdapterChange(this, TRUE);
928 }
929 }
930
931 return hrc;
932}
933
934STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled)(BOOL *aEnabled)
935{
936 CheckComArgOutPointerValid(aEnabled);
937
938 AutoCaller autoCaller(this);
939 if (FAILED(autoCaller.rc())) return autoCaller.rc();
940
941 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
942
943 *aEnabled = mData->mTraceEnabled;
944 return S_OK;
945}
946
947STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled)(BOOL aEnabled)
948{
949 AutoCaller autoCaller(this);
950 if (FAILED(autoCaller.rc())) return autoCaller.rc();
951
952 /* the machine needs to be mutable */
953 AutoMutableStateDependency adep(mParent);
954 if (FAILED(adep.rc())) return adep.rc();
955
956 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
957
958 if (aEnabled != mData->mTraceEnabled)
959 {
960 mData.backup();
961 mData->mTraceEnabled = aEnabled;
962
963 m_fModified = true;
964 // leave the lock before informing callbacks
965 alock.release();
966
967 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
968 mParent->setModified(Machine::IsModified_NetworkAdapters);
969 mlock.release();
970
971 /* Adapt the CFGM logic changeAdapter=TRUE */
972 mParent->onNetworkAdapterChange(this, TRUE);
973 }
974
975 return S_OK;
976}
977
978STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile)(BSTR *aTraceFile)
979{
980 CheckComArgOutPointerValid(aTraceFile);
981
982 AutoCaller autoCaller(this);
983 if (FAILED(autoCaller.rc())) return autoCaller.rc();
984
985 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
986
987 mData->mTraceFile.cloneTo(aTraceFile);
988
989 return S_OK;
990}
991
992STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile)(IN_BSTR aTraceFile)
993{
994 AutoCaller autoCaller(this);
995 if (FAILED(autoCaller.rc())) return autoCaller.rc();
996
997 /* the machine needs to be mutable */
998 AutoMutableStateDependency adep(mParent);
999 if (FAILED(adep.rc())) return adep.rc();
1000
1001 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1002
1003 if (mData->mTraceFile != aTraceFile)
1004 {
1005 mData.backup();
1006 mData->mTraceFile = aTraceFile;
1007
1008 m_fModified = true;
1009 // leave the lock before informing callbacks
1010 alock.release();
1011
1012 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1013 mParent->setModified(Machine::IsModified_NetworkAdapters);
1014 mlock.release();
1015
1016 /* No change in CFGM logic => changeAdapter=FALSE. */
1017 mParent->onNetworkAdapterChange(this, FALSE);
1018 }
1019
1020 return S_OK;
1021}
1022
1023STDMETHODIMP NetworkAdapter::COMGETTER(NATEngine)(INATEngine **aNATEngine)
1024{
1025 CheckComArgOutPointerValid(aNATEngine);
1026
1027 AutoCaller autoCaller(this);
1028 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1029
1030 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1031
1032 mNATEngine.queryInterfaceTo(aNATEngine);
1033
1034 return S_OK;
1035}
1036
1037STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority)(ULONG *aBootPriority)
1038{
1039 CheckComArgOutPointerValid(aBootPriority);
1040
1041 AutoCaller autoCaller(this);
1042 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1043
1044 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1045
1046 *aBootPriority = mData->mBootPriority;
1047
1048 return S_OK;
1049}
1050
1051STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority)(ULONG aBootPriority)
1052{
1053 AutoCaller autoCaller(this);
1054 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1055
1056 /* the machine needs to be mutable */
1057 AutoMutableStateDependency adep(mParent);
1058 if (FAILED(adep.rc())) return adep.rc();
1059
1060 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1061
1062 if (aBootPriority != mData->mBootPriority)
1063 {
1064 mData.backup();
1065 mData->mBootPriority = aBootPriority;
1066
1067 m_fModified = true;
1068 // leave the lock before informing callbacks
1069 alock.release();
1070
1071 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1072 mParent->setModified(Machine::IsModified_NetworkAdapters);
1073 mlock.release();
1074
1075 /* No change in CFGM logic => changeAdapter=FALSE. */
1076 mParent->onNetworkAdapterChange(this, FALSE);
1077 }
1078
1079 return S_OK;
1080}
1081
1082// INetworkAdapter methods
1083////////////////////////////////////////////////////////////////////////////////
1084
1085STDMETHODIMP NetworkAdapter::GetProperty(IN_BSTR aKey, BSTR *aValue)
1086{
1087 CheckComArgOutPointerValid(aValue);
1088
1089 AutoCaller autoCaller(this);
1090 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1091
1092 Bstr key = aKey;
1093 Bstr value;
1094
1095 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1096
1097 Utf8Str strKey(key);
1098 settings::StringsMap::const_iterator it = mData->mGenericProperties.find(strKey);
1099 if (it != mData->mGenericProperties.end())
1100 {
1101 value = it->second; // source is a Utf8Str
1102 value.cloneTo(aValue);
1103 }
1104
1105 return S_OK;
1106}
1107
1108STDMETHODIMP NetworkAdapter::SetProperty(IN_BSTR aKey, IN_BSTR aValue)
1109{
1110 LogFlowThisFunc(("\n"));
1111
1112 AutoCaller autoCaller(this);
1113 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1114
1115 /* The machine needs to be mutable. */
1116 AutoMutableStateDependency adep(mParent);
1117 if (FAILED(adep.rc())) return adep.rc();
1118
1119 Bstr key = aKey;
1120
1121 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1122
1123 bool fGenericChange = (mData->mAttachmentType == NetworkAttachmentType_Generic);
1124
1125 /* Generic properties processing.
1126 * Look up the old value first; if nothing's changed then do nothing.
1127 */
1128 Utf8Str strValue(aValue);
1129 Utf8Str strKey(aKey);
1130 Utf8Str strOldValue;
1131
1132 settings::StringsMap::const_iterator it = mData->mGenericProperties.find(strKey);
1133 if (it != mData->mGenericProperties.end())
1134 strOldValue = it->second;
1135
1136 if (strOldValue != strValue)
1137 {
1138 if (strValue.isEmpty())
1139 mData->mGenericProperties.erase(strKey);
1140 else
1141 mData->mGenericProperties[strKey] = strValue;
1142
1143 /* leave the lock before informing callbacks */
1144 alock.release();
1145
1146 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1147 mParent->setModified(Machine::IsModified_NetworkAdapters);
1148 mlock.release();
1149
1150 /* Avoid deadlock when the event triggers a call to a method of this
1151 * interface. */
1152 adep.release();
1153
1154 mParent->onNetworkAdapterChange(this, fGenericChange);
1155 }
1156
1157 return S_OK;
1158}
1159
1160STDMETHODIMP NetworkAdapter::GetProperties(IN_BSTR aNames,
1161 ComSafeArrayOut(BSTR, aReturnNames),
1162 ComSafeArrayOut(BSTR, aReturnValues))
1163{
1164 CheckComArgOutSafeArrayPointerValid(aReturnNames);
1165 CheckComArgOutSafeArrayPointerValid(aReturnValues);
1166
1167 AutoCaller autoCaller(this);
1168 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1169
1170 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1171
1172 /// @todo make use of aNames according to the documentation
1173 NOREF(aNames);
1174
1175 com::SafeArray<BSTR> names(mData->mGenericProperties.size());
1176 com::SafeArray<BSTR> values(mData->mGenericProperties.size());
1177 size_t i = 0;
1178
1179 for (settings::StringsMap::const_iterator it = mData->mGenericProperties.begin();
1180 it != mData->mGenericProperties.end();
1181 ++it)
1182 {
1183 it->first.cloneTo(&names[i]);
1184 it->second.cloneTo(&values[i]);
1185 ++i;
1186 }
1187
1188 names.detachTo(ComSafeArrayOutArg(aReturnNames));
1189 values.detachTo(ComSafeArrayOutArg(aReturnValues));
1190
1191 return S_OK;
1192}
1193
1194
1195
1196// public methods only for internal purposes
1197////////////////////////////////////////////////////////////////////////////////
1198
1199/**
1200 * Loads settings from the given adapter node.
1201 * May be called once right after this object creation.
1202 *
1203 * @param aAdapterNode <Adapter> node.
1204 *
1205 * @note Locks this object for writing.
1206 */
1207HRESULT NetworkAdapter::loadSettings(BandwidthControl *bwctl,
1208 const settings::NetworkAdapter &data)
1209{
1210 AutoCaller autoCaller(this);
1211 AssertComRCReturnRC(autoCaller.rc());
1212
1213 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1214
1215 /* Note: we assume that the default values for attributes of optional
1216 * nodes are assigned in the Data::Data() constructor and don't do it
1217 * here. It implies that this method may only be called after constructing
1218 * a new BIOSSettings object while all its data fields are in the default
1219 * values. Exceptions are fields whose creation time defaults don't match
1220 * values that should be applied when these fields are not explicitly set
1221 * in the settings file (for backwards compatibility reasons). This takes
1222 * place when a setting of a newly created object must default to A while
1223 * the same setting of an object loaded from the old settings file must
1224 * default to B. */
1225
1226 HRESULT rc = S_OK;
1227
1228 mData->mAdapterType = data.type;
1229 mData->mEnabled = data.fEnabled;
1230 /* MAC address (can be null) */
1231 rc = updateMacAddress(data.strMACAddress);
1232 if (FAILED(rc)) return rc;
1233 /* cable (required) */
1234 mData->mCableConnected = data.fCableConnected;
1235 /* line speed (defaults to 100 Mbps) */
1236 mData->mLineSpeed = data.ulLineSpeed;
1237 mData->mPromiscModePolicy = data.enmPromiscModePolicy;
1238 /* tracing (defaults to false) */
1239 mData->mTraceEnabled = data.fTraceEnabled;
1240 mData->mTraceFile = data.strTraceFile;
1241 /* boot priority (defaults to 0, i.e. lowest) */
1242 mData->mBootPriority = data.ulBootPriority;
1243 /* bandwidth group */
1244 mData->mBandwidthGroup = data.strBandwidthGroup;
1245 if (mData->mBandwidthGroup.isNotEmpty())
1246 {
1247 ComObjPtr<BandwidthGroup> group;
1248 rc = bwctl->i_getBandwidthGroupByName(data.strBandwidthGroup, group, true);
1249 if (FAILED(rc)) return rc;
1250 group->i_reference();
1251 }
1252
1253 mNATEngine->i_loadSettings(data.nat);
1254 mData->mBridgedInterface = data.strBridgedName;
1255 mData->mInternalNetwork = data.strInternalNetworkName;
1256 mData->mHostOnlyInterface = data.strHostOnlyName;
1257 mData->mGenericDriver = data.strGenericDriver;
1258 mData->mGenericProperties = data.genericProperties;
1259 mData->mNATNetwork = data.strNATNetworkName;
1260
1261 // leave the lock before setting attachment type
1262 alock.release();
1263
1264 rc = COMSETTER(AttachmentType)(data.mode);
1265 if (FAILED(rc)) return rc;
1266
1267 // after loading settings, we are no longer different from the XML on disk
1268 m_fModified = false;
1269
1270 return S_OK;
1271}
1272
1273/**
1274 * Saves settings to the given adapter node.
1275 *
1276 * Note that the given Adapter node is completely empty on input.
1277 *
1278 * @param aAdapterNode <Adapter> node.
1279 *
1280 * @note Locks this object for reading.
1281 */
1282HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
1283{
1284 AutoCaller autoCaller(this);
1285 AssertComRCReturnRC(autoCaller.rc());
1286
1287 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1288
1289 data.fEnabled = !!mData->mEnabled;
1290 data.strMACAddress = mData->mMACAddress;
1291 data.fCableConnected = !!mData->mCableConnected;
1292
1293 data.enmPromiscModePolicy = mData->mPromiscModePolicy;
1294 data.ulLineSpeed = mData->mLineSpeed;
1295
1296 data.fTraceEnabled = !!mData->mTraceEnabled;
1297
1298 data.strTraceFile = mData->mTraceFile;
1299
1300 data.ulBootPriority = mData->mBootPriority;
1301
1302 data.strBandwidthGroup = mData->mBandwidthGroup;
1303
1304 data.type = mData->mAdapterType;
1305
1306 data.mode = mData->mAttachmentType;
1307
1308 mNATEngine->i_commit();
1309 mNATEngine->i_saveSettings(data.nat);
1310
1311 data.strBridgedName = mData->mBridgedInterface;
1312
1313 data.strHostOnlyName = mData->mHostOnlyInterface;
1314
1315 data.strInternalNetworkName = mData->mInternalNetwork;
1316
1317 data.strGenericDriver = mData->mGenericDriver;
1318 data.genericProperties = mData->mGenericProperties;
1319
1320 data.strNATNetworkName = mData->mNATNetwork;
1321
1322 // after saving settings, we are no longer different from the XML on disk
1323 m_fModified = false;
1324
1325 return S_OK;
1326}
1327
1328/**
1329 * Returns true if any setter method has modified settings of this instance.
1330 * @return
1331 */
1332bool NetworkAdapter::isModified() {
1333 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1334 bool fChanged = m_fModified;
1335 fChanged |= (mData->mAdapterType == NetworkAttachmentType_NAT? mNATEngine->i_isModified() : false);
1336 return fChanged;
1337}
1338
1339/**
1340 * @note Locks this object for writing.
1341 */
1342void NetworkAdapter::rollback()
1343{
1344 /* sanity */
1345 AutoCaller autoCaller(this);
1346 AssertComRCReturnVoid(autoCaller.rc());
1347
1348 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1349
1350 mData.rollback();
1351}
1352
1353/**
1354 * @note Locks this object for writing, together with the peer object (also
1355 * for writing) if there is one.
1356 */
1357void NetworkAdapter::commit()
1358{
1359 /* sanity */
1360 AutoCaller autoCaller(this);
1361 AssertComRCReturnVoid(autoCaller.rc());
1362
1363 /* sanity too */
1364 AutoCaller peerCaller(mPeer);
1365 AssertComRCReturnVoid(peerCaller.rc());
1366
1367 /* lock both for writing since we modify both (mPeer is "master" so locked
1368 * first) */
1369 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1370
1371 if (mData.isBackedUp())
1372 {
1373 mData.commit();
1374 if (mPeer)
1375 {
1376 /* attach new data to the peer and reshare it */
1377 mPeer->mData.attach(mData);
1378 }
1379 }
1380}
1381
1382/**
1383 * @note Locks this object for writing, together with the peer object
1384 * represented by @a aThat (locked for reading).
1385 */
1386void NetworkAdapter::copyFrom(NetworkAdapter *aThat)
1387{
1388 AssertReturnVoid(aThat != NULL);
1389
1390 /* sanity */
1391 AutoCaller autoCaller(this);
1392 AssertComRCReturnVoid(autoCaller.rc());
1393
1394 /* sanity too */
1395 AutoCaller thatCaller(aThat);
1396 AssertComRCReturnVoid(thatCaller.rc());
1397
1398 /* peer is not modified, lock it for reading (aThat is "master" so locked
1399 * first) */
1400 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1401 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1402
1403 /* this will back up current data */
1404 mData.assignCopy(aThat->mData);
1405}
1406
1407void NetworkAdapter::applyDefaults(GuestOSType *aOsType)
1408{
1409 AssertReturnVoid(aOsType != NULL);
1410
1411 /* sanity */
1412 AutoCaller autoCaller(this);
1413 AssertComRCReturnVoid(autoCaller.rc());
1414
1415 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1416
1417 bool e1000enabled = false;
1418#ifdef VBOX_WITH_E1000
1419 e1000enabled = true;
1420#endif // VBOX_WITH_E1000
1421
1422 NetworkAdapterType_T defaultType = aOsType->i_networkAdapterType();
1423
1424 /* Set default network adapter for this OS type */
1425 if (defaultType == NetworkAdapterType_I82540EM ||
1426 defaultType == NetworkAdapterType_I82543GC ||
1427 defaultType == NetworkAdapterType_I82545EM)
1428 {
1429 if (e1000enabled) mData->mAdapterType = defaultType;
1430 }
1431 else mData->mAdapterType = defaultType;
1432
1433 /* Enable and connect the first one adapter to the NAT */
1434 if (mData->mSlot == 0)
1435 {
1436 mData->mEnabled = true;
1437 mData->mAttachmentType = NetworkAttachmentType_NAT;
1438 mData->mCableConnected = true;
1439 }
1440}
1441
1442ComObjPtr<NetworkAdapter> NetworkAdapter::getPeer()
1443{
1444 return mPeer;
1445}
1446
1447
1448// private methods
1449////////////////////////////////////////////////////////////////////////////////
1450
1451/**
1452 * Generates a new unique MAC address based on our vendor ID and
1453 * parts of a GUID.
1454 *
1455 * @note Must be called from under the object's write lock or within the init
1456 * span.
1457 */
1458void NetworkAdapter::generateMACAddress()
1459{
1460 Utf8Str mac;
1461 Host::i_generateMACAddress(mac);
1462 LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str()));
1463 mData->mMACAddress = mac;
1464}
1465
1466STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthGroup)(IBandwidthGroup **aBwGroup)
1467{
1468 LogFlowThisFuncEnter();
1469 CheckComArgOutPointerValid(aBwGroup);
1470
1471 HRESULT hrc = S_OK;
1472
1473 AutoCaller autoCaller(this);
1474 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1475
1476 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1477
1478 if (mData->mBandwidthGroup.isNotEmpty())
1479 {
1480 ComObjPtr<BandwidthGroup> pBwGroup;
1481 hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pBwGroup, true /* fSetError */);
1482
1483 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
1484
1485 if (SUCCEEDED(hrc))
1486 pBwGroup.queryInterfaceTo(aBwGroup);
1487 }
1488
1489 LogFlowThisFuncLeave();
1490 return hrc;
1491}
1492
1493STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthGroup)(IBandwidthGroup *aBwGroup)
1494{
1495 LogFlowThisFuncEnter();
1496
1497 AutoCaller autoCaller(this);
1498 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1499
1500 /* the machine needs to be mutable */
1501 AutoMutableStateDependency adep(mParent);
1502 if (FAILED(adep.rc())) return adep.rc();
1503
1504 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1505
1506 Utf8Str strBwGroup;
1507 if (aBwGroup)
1508 strBwGroup = static_cast<BandwidthGroup*>(aBwGroup)->i_getName();
1509 if (mData->mBandwidthGroup != strBwGroup)
1510 {
1511 ComObjPtr<BandwidthGroup> pBwGroup;
1512 if (!strBwGroup.isEmpty())
1513 {
1514 HRESULT hrc = mParent->getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
1515 NOREF(hrc);
1516 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
1517 }
1518
1519 updateBandwidthGroup(pBwGroup);
1520
1521 m_fModified = true;
1522 // leave the lock before informing callbacks
1523 alock.release();
1524
1525 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1526 mParent->setModified(Machine::IsModified_NetworkAdapters);
1527 mlock.release();
1528
1529 /* TODO: changeAdapter=???. */
1530 mParent->onNetworkAdapterChange(this, FALSE);
1531 }
1532
1533 LogFlowThisFuncLeave();
1534 return S_OK;
1535}
1536
1537void NetworkAdapter::updateBandwidthGroup(BandwidthGroup *aBwGroup)
1538{
1539 LogFlowThisFuncEnter();
1540 Assert(isWriteLockOnCurrentThread());
1541
1542 ComObjPtr<BandwidthGroup> pOldBwGroup;
1543 if (!mData->mBandwidthGroup.isEmpty())
1544 {
1545 HRESULT hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pOldBwGroup, false /* fSetError */);
1546 NOREF(hrc);
1547 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
1548 }
1549
1550 mData.backup();
1551 if (!pOldBwGroup.isNull())
1552 {
1553 pOldBwGroup->i_release();
1554 mData->mBandwidthGroup = Utf8Str::Empty;
1555 }
1556
1557 if (aBwGroup)
1558 {
1559 mData->mBandwidthGroup = aBwGroup->i_getName();
1560 aBwGroup->i_reference();
1561 }
1562
1563 LogFlowThisFuncLeave();
1564}
1565
1566
1567HRESULT NetworkAdapter::checkAndSwitchFromNatNetworking(IN_BSTR networkName)
1568{
1569 MachineState_T state;
1570
1571 HRESULT hrc = mParent->COMGETTER(State)(&state);
1572 if (FAILED(hrc))
1573 return hrc;
1574
1575 if (state == MachineState_Running)
1576 {
1577 Bstr bstrName;
1578 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1579 LogRel(("VM '%ls' stops using NAT network '%ls'\n", bstrName.raw(), networkName));
1580 int natCount = mParent->getVirtualBox()->natNetworkRefDec(networkName);
1581 if (natCount == -1)
1582 return E_INVALIDARG; /* no such network */
1583 }
1584
1585 return S_OK;
1586}
1587
1588
1589HRESULT NetworkAdapter::switchToNatNetworking(IN_BSTR aNatNetworkName)
1590{
1591 MachineState_T state;
1592
1593 HRESULT hrc = mParent->COMGETTER(State)(&state);
1594 if (FAILED(hrc))
1595 return hrc;
1596
1597 if (state == MachineState_Running)
1598 {
1599 Bstr bstrName;
1600 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1601 LogRel(("VM '%ls' starts using NAT network '%ls'\n", bstrName.raw(), aNatNetworkName));
1602 int natCount = mParent->getVirtualBox()->natNetworkRefInc(aNatNetworkName);
1603 if (natCount == -1)
1604 return E_INVALIDARG; /* not found */
1605 }
1606
1607 return S_OK;
1608}
1609/* 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