VirtualBox

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

Last change on this file since 79812 was 76592, checked in by vboxsync, 6 years ago

Main: Don't use Logging.h.

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