VirtualBox

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

Last change on this file since 54883 was 54840, checked in by vboxsync, 10 years ago

Main/NetworkAdapter: adapt to new, more precise state checks

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