VirtualBox

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

Last change on this file since 72899 was 72482, checked in by vboxsync, 7 years ago

Main/NetworkAdapter: allow arbitrary network names for disabled adapters

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