VirtualBox

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

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

NetworkAdapter::COMSETTER(AttachmentType): makes disabled network switch, acting as it was intended in r98680. (disabled).

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