VirtualBox

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

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

Main/NetworkAdapter: fix MAC address generation when applying settings defaults (forgotten case)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.0 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 61034 2016-05-18 12:16:21Z 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 if (mData->mMACAddress.isEmpty())
1252 i_generateMACAddress();
1253 mData->mAttachmentType = NetworkAttachmentType_NAT;
1254 }
1255 mData->mCableConnected = true;
1256}
1257
1258ComObjPtr<NetworkAdapter> NetworkAdapter::i_getPeer()
1259{
1260 return mPeer;
1261}
1262
1263
1264// private methods
1265////////////////////////////////////////////////////////////////////////////////
1266
1267/**
1268 * Generates a new unique MAC address based on our vendor ID and
1269 * parts of a GUID.
1270 *
1271 * @note Must be called from under the object's write lock or within the init
1272 * span.
1273 */
1274void NetworkAdapter::i_generateMACAddress()
1275{
1276 Utf8Str mac;
1277 Host::i_generateMACAddress(mac);
1278 LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str()));
1279 mData->mMACAddress = mac;
1280}
1281
1282HRESULT NetworkAdapter::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
1283{
1284 LogFlowThisFuncEnter();
1285
1286 HRESULT hrc = S_OK;
1287
1288 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1289
1290 if (mData->mBandwidthGroup.isNotEmpty())
1291 {
1292 ComObjPtr<BandwidthGroup> pBwGroup;
1293 hrc = mParent->i_getBandwidthGroup(mData->mBandwidthGroup, pBwGroup, true /* fSetError */);
1294
1295 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1296 * of the group was checked when it was attached. */
1297 if (SUCCEEDED(hrc))
1298 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
1299 }
1300
1301 LogFlowThisFuncLeave();
1302 return hrc;
1303}
1304
1305HRESULT NetworkAdapter::setBandwidthGroup(const ComPtr<IBandwidthGroup> &aBandwidthGroup)
1306{
1307 LogFlowThisFuncEnter();
1308
1309 /* the machine needs to be mutable */
1310 AutoMutableOrSavedStateDependency adep(mParent);
1311 if (FAILED(adep.rc())) return adep.rc();
1312
1313 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1314
1315 IBandwidthGroup *iBw = aBandwidthGroup;
1316 Utf8Str strBwGroup;
1317 if (aBandwidthGroup)
1318 strBwGroup = static_cast<BandwidthGroup *>(iBw)->i_getName();
1319
1320 if (mData->mBandwidthGroup != strBwGroup)
1321 {
1322 ComObjPtr<BandwidthGroup> pBwGroup;
1323 if (!strBwGroup.isEmpty())
1324 {
1325 HRESULT hrc = mParent->i_getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
1326 NOREF(hrc);
1327 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1328 of the group was checked when it was attached. */
1329 }
1330
1331 i_updateBandwidthGroup(pBwGroup);
1332
1333 // leave the lock before informing callbacks
1334 alock.release();
1335
1336 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1337 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
1338 mlock.release();
1339
1340 /* TODO: changeAdapter=???. */
1341 mParent->i_onNetworkAdapterChange(this, FALSE);
1342 }
1343
1344 LogFlowThisFuncLeave();
1345 return S_OK;
1346}
1347
1348void NetworkAdapter::i_updateBandwidthGroup(BandwidthGroup *aBwGroup)
1349{
1350 LogFlowThisFuncEnter();
1351 Assert(isWriteLockOnCurrentThread());
1352
1353 ComObjPtr<BandwidthGroup> pOldBwGroup;
1354 if (!mData->mBandwidthGroup.isEmpty())
1355 {
1356 HRESULT hrc = mParent->i_getBandwidthGroup(mData->mBandwidthGroup, pOldBwGroup, false /* fSetError */);
1357 NOREF(hrc);
1358 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of
1359 the group was checked when it was attached. */
1360 }
1361
1362 mData.backup();
1363 if (!pOldBwGroup.isNull())
1364 {
1365 pOldBwGroup->i_release();
1366 mData->mBandwidthGroup = Utf8Str::Empty;
1367 }
1368
1369 if (aBwGroup)
1370 {
1371 mData->mBandwidthGroup = aBwGroup->i_getName();
1372 aBwGroup->i_reference();
1373 }
1374
1375 LogFlowThisFuncLeave();
1376}
1377
1378
1379HRESULT NetworkAdapter::i_checkAndSwitchFromNatNetworking(com::Utf8Str networkName)
1380{
1381 HRESULT hrc;
1382 MachineState_T state;
1383
1384 hrc = mParent->COMGETTER(State)(&state);
1385 if (FAILED(hrc))
1386 return hrc;
1387
1388 if ( state == MachineState_Running
1389 || state == MachineState_Paused)
1390 {
1391 Bstr bstrName;
1392 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1393 LogRel(("VM '%ls' stops using NAT network '%s'\n", bstrName.raw(), networkName.c_str()));
1394 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefDec(Bstr(networkName).raw());
1395 if (natCount == -1)
1396 return E_INVALIDARG; /* no such network */
1397 }
1398
1399 return S_OK;
1400}
1401
1402
1403HRESULT NetworkAdapter::i_switchToNatNetworking(const com::Utf8Str &aNatNetworkName)
1404{
1405 HRESULT hrc;
1406 MachineState_T state;
1407
1408 hrc = mParent->COMGETTER(State)(&state);
1409 if (FAILED(hrc))
1410 return hrc;
1411
1412 if ( state == MachineState_Running
1413 || state == MachineState_Paused)
1414 {
1415 Bstr bstrName;
1416 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1417 LogRel(("VM '%ls' starts using NAT network '%s'\n", bstrName.raw(), aNatNetworkName.c_str()));
1418 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefInc(Bstr(aNatNetworkName).raw());
1419 if (natCount == -1)
1420 return E_INVALIDARG; /* not found */
1421 }
1422
1423 return S_OK;
1424}
1425/* 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