VirtualBox

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

Last change on this file since 61009 was 61009, checked in by vboxsync, 9 years ago

Main: big settings cleanup and writing optimization. Moved constructors/equality/default checks into the .cpp file, and write only settings which aren't at the default value. Greatly reduces the effort needed to write everything out, especially when a lot of snapshots have to be dealt with. Move the storage controllers to the hardware settings, where they always belonged. No change to the XML file (yet). Lots of settings related cleanups in the API code.

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