VirtualBox

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

Last change on this file since 81422 was 81422, checked in by vboxsync, 5 years ago

OCI: (bugref:9469) cloud network integration concept (disabled in Config.kmk).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.4 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 81422 2019-10-21 18:04:10Z 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::getCloudNetwork(com::Utf8Str &aCloudNetwork)
727{
728#ifdef VBOX_WITH_CLOUD_NET
729 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
730
731 aCloudNetwork = mData->strCloudNetworkName;
732
733 return S_OK;
734#else /* !VBOX_WITH_CLOUD_NET */
735 NOREF(aCloudNetwork);
736 return E_NOTIMPL;
737#endif /* !VBOX_WITH_CLOUD_NET */
738}
739
740HRESULT NetworkAdapter::setCloudNetwork(const com::Utf8Str &aCloudNetwork)
741{
742#ifdef VBOX_WITH_CLOUD_NET
743 /* the machine needs to be mutable */
744 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
745 if (FAILED(adep.rc())) return adep.rc();
746
747 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
748
749 if (mData->strCloudNetworkName != aCloudNetwork)
750 {
751 /* if an empty/null string is to be set, Cloud networking must be
752 * turned off */
753 if ( aCloudNetwork.isEmpty()
754 && mData->fEnabled
755 && mData->mode == NetworkAttachmentType_Cloud)
756 {
757 return setError(E_FAIL,
758 tr("Empty or null Cloud network name is not valid"));
759 }
760 mData.backup();
761 mData->strCloudNetworkName = aCloudNetwork;
762
763 // leave the lock before informing callbacks
764 alock.release();
765
766#if 0
767 // @todo Implement dynamic re-attachment of cloud network
768 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
769 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
770 mlock.release();
771
772 /* When changing the internal network, adapt the CFGM logic to make this
773 * change immediately effect and to notify the guest that the network
774 * might have changed, therefore changeAdapter=TRUE. */
775 mParent->i_onNetworkAdapterChange(this, TRUE);
776#else
777 mParent->i_onNetworkAdapterChange(this, FALSE);
778#endif
779 }
780 return S_OK;
781#else /* !VBOX_WITH_CLOUD_NET */
782 NOREF(aCloudNetwork);
783 return E_NOTIMPL;
784#endif /* !VBOX_WITH_CLOUD_NET */
785}
786
787
788HRESULT NetworkAdapter::getCableConnected(BOOL *aConnected)
789{
790 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
791
792 *aConnected = mData->fCableConnected;
793
794 return S_OK;
795}
796
797
798HRESULT NetworkAdapter::setCableConnected(BOOL aConnected)
799{
800 /* the machine needs to be mutable */
801 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
802 if (FAILED(adep.rc())) return adep.rc();
803
804 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
805
806 if (RT_BOOL(aConnected) != mData->fCableConnected)
807 {
808 mData.backup();
809 mData->fCableConnected = RT_BOOL(aConnected);
810
811 // leave the lock before informing callbacks
812 alock.release();
813
814 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
815 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
816 mlock.release();
817
818 /* No change in CFGM logic => changeAdapter=FALSE. */
819 mParent->i_onNetworkAdapterChange(this, FALSE);
820 }
821
822 return S_OK;
823}
824
825
826HRESULT NetworkAdapter::getLineSpeed(ULONG *aSpeed)
827{
828 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
829
830 *aSpeed = mData->ulLineSpeed;
831
832 return S_OK;
833}
834
835HRESULT NetworkAdapter::setLineSpeed(ULONG aSpeed)
836{
837 /* the machine needs to be mutable */
838 AutoMutableStateDependency adep(mParent);
839 if (FAILED(adep.rc())) return adep.rc();
840
841 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
842
843 if (aSpeed != mData->ulLineSpeed)
844 {
845 mData.backup();
846 mData->ulLineSpeed = aSpeed;
847
848 // leave the lock before informing callbacks
849 alock.release();
850
851 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
852 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
853 mlock.release();
854
855 /* No change in CFGM logic => changeAdapter=FALSE. */
856 mParent->i_onNetworkAdapterChange(this, FALSE);
857 }
858
859 return S_OK;
860}
861
862HRESULT NetworkAdapter::getPromiscModePolicy(NetworkAdapterPromiscModePolicy_T *aPromiscModePolicy)
863{
864 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
865
866 *aPromiscModePolicy = mData->enmPromiscModePolicy;
867
868 return S_OK;
869}
870
871HRESULT NetworkAdapter::setPromiscModePolicy(NetworkAdapterPromiscModePolicy_T aPromiscModePolicy)
872{
873 /* the machine needs to be mutable */
874 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
875 if (FAILED(adep.rc())) return adep.rc();
876
877 switch (aPromiscModePolicy)
878 {
879 case NetworkAdapterPromiscModePolicy_Deny:
880 case NetworkAdapterPromiscModePolicy_AllowNetwork:
881 case NetworkAdapterPromiscModePolicy_AllowAll:
882 break;
883 default:
884 return setError(E_INVALIDARG, tr("Invalid promiscuous mode policy (%d)"), aPromiscModePolicy);
885 }
886
887 AutoCaller autoCaller(this);
888 HRESULT hrc = autoCaller.rc();
889
890 if (SUCCEEDED(hrc))
891 {
892 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
893 if (aPromiscModePolicy != mData->enmPromiscModePolicy)
894 {
895 mData.backup();
896 mData->enmPromiscModePolicy = aPromiscModePolicy;
897
898 alock.release();
899 mParent->i_setModifiedLock(Machine::IsModified_NetworkAdapters);
900 mParent->i_onNetworkAdapterChange(this, TRUE);
901 }
902 }
903
904 return hrc;
905}
906
907
908HRESULT NetworkAdapter::getTraceEnabled(BOOL *aEnabled)
909{
910
911 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
912
913 *aEnabled = mData->fTraceEnabled;
914
915 return S_OK;
916}
917
918HRESULT NetworkAdapter::setTraceEnabled(BOOL aEnabled)
919{
920 /* the machine needs to be mutable */
921 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
922 if (FAILED(adep.rc())) return adep.rc();
923
924 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
925
926 if (RT_BOOL(aEnabled) != mData->fTraceEnabled)
927 {
928 mData.backup();
929 mData->fTraceEnabled = RT_BOOL(aEnabled);
930
931 // leave the lock before informing callbacks
932 alock.release();
933
934 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
935 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
936 mlock.release();
937
938 /* Adapt the CFGM logic changeAdapter=TRUE */
939 mParent->i_onNetworkAdapterChange(this, TRUE);
940 }
941
942 return S_OK;
943}
944
945HRESULT NetworkAdapter::getTraceFile(com::Utf8Str &aTraceFile)
946{
947 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
948
949 aTraceFile = mData->strTraceFile;
950
951 return S_OK;
952}
953
954
955HRESULT NetworkAdapter::setTraceFile(const com::Utf8Str &aTraceFile)
956{
957 /* the machine needs to be mutable */
958 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
959 if (FAILED(adep.rc())) return adep.rc();
960
961 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
962
963 if (mData->strTraceFile != aTraceFile)
964 {
965 mData.backup();
966 mData->strTraceFile = aTraceFile;
967
968 // leave the lock before informing callbacks
969 alock.release();
970
971 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
972 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
973 mlock.release();
974
975 /* We change the 'File' => changeAdapter=TRUE. */
976 mParent->i_onNetworkAdapterChange(this, TRUE);
977 }
978
979 return S_OK;
980}
981
982HRESULT NetworkAdapter::getNATEngine(ComPtr<INATEngine> &aNATEngine)
983{
984 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
985
986 aNATEngine = mNATEngine;
987
988 return S_OK;
989}
990
991HRESULT NetworkAdapter::getBootPriority(ULONG *aBootPriority)
992{
993 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
994
995 *aBootPriority = mData->ulBootPriority;
996
997 return S_OK;
998}
999
1000HRESULT NetworkAdapter::setBootPriority(ULONG aBootPriority)
1001{
1002 /* the machine needs to be mutable */
1003 AutoMutableStateDependency adep(mParent);
1004 if (FAILED(adep.rc())) return adep.rc();
1005
1006 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1007
1008 if (aBootPriority != mData->ulBootPriority)
1009 {
1010 mData.backup();
1011 mData->ulBootPriority = aBootPriority;
1012
1013 // leave the lock before informing callbacks
1014 alock.release();
1015
1016 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1017 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
1018 mlock.release();
1019
1020 /* No change in CFGM logic => changeAdapter=FALSE. */
1021 mParent->i_onNetworkAdapterChange(this, FALSE);
1022 }
1023
1024 return S_OK;
1025}
1026
1027// wrapped INetworkAdapter methods
1028////////////////////////////////////////////////////////////////////////////////
1029
1030HRESULT NetworkAdapter::getProperty(const com::Utf8Str &aKey, com::Utf8Str &aValue)
1031{
1032 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1033 aValue = "";
1034 settings::StringsMap::const_iterator it = mData->genericProperties.find(aKey);
1035 if (it != mData->genericProperties.end())
1036 aValue = it->second; // source is a Utf8Str
1037
1038 return S_OK;
1039}
1040
1041HRESULT NetworkAdapter::setProperty(const com::Utf8Str &aKey, const com::Utf8Str &aValue)
1042{
1043 LogFlowThisFunc(("\n"));
1044 /* The machine needs to be mutable. */
1045 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
1046 if (FAILED(adep.rc())) return adep.rc();
1047 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1048 bool fGenericChange = (mData->mode == NetworkAttachmentType_Generic);
1049 /* Generic properties processing.
1050 * Look up the old value first; if nothing's changed then do nothing.
1051 */
1052 Utf8Str strOldValue;
1053 settings::StringsMap::const_iterator it = mData->genericProperties.find(aKey);
1054 if (it != mData->genericProperties.end())
1055 strOldValue = it->second;
1056
1057 if (strOldValue != aValue)
1058 {
1059 if (aValue.isEmpty())
1060 mData->genericProperties.erase(aKey);
1061 else
1062 mData->genericProperties[aKey] = aValue;
1063
1064 /* leave the lock before informing callbacks */
1065 alock.release();
1066
1067 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1068 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
1069 mlock.release();
1070
1071 /* Avoid deadlock when the event triggers a call to a method of this
1072 * interface. */
1073 adep.release();
1074
1075 mParent->i_onNetworkAdapterChange(this, fGenericChange);
1076 }
1077
1078 return S_OK;
1079}
1080
1081HRESULT NetworkAdapter::getProperties(const com::Utf8Str &aNames,
1082 std::vector<com::Utf8Str> &aReturnNames,
1083 std::vector<com::Utf8Str> &aReturnValues)
1084{
1085 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1086
1087 /// @todo make use of aNames according to the documentation
1088 NOREF(aNames);
1089 aReturnNames.resize(mData->genericProperties.size());
1090 aReturnValues.resize(mData->genericProperties.size());
1091
1092 size_t i = 0;
1093
1094 for (settings::StringsMap::const_iterator it = mData->genericProperties.begin();
1095 it != mData->genericProperties.end();
1096 ++it, ++i)
1097 {
1098 aReturnNames[i] = it->first;
1099 aReturnValues[i] = it->second;
1100 }
1101
1102 return S_OK;
1103}
1104
1105
1106
1107// public methods only for internal purposes
1108////////////////////////////////////////////////////////////////////////////////
1109
1110/**
1111 * Loads settings from the given adapter node.
1112 * May be called once right after this object creation.
1113 *
1114 * @param bwctl bandwidth control object.
1115 * @param data Configuration settings.
1116 *
1117 * @note Locks this object for writing.
1118 */
1119HRESULT NetworkAdapter::i_loadSettings(BandwidthControl *bwctl,
1120 const settings::NetworkAdapter &data)
1121{
1122 AutoCaller autoCaller(this);
1123 AssertComRCReturnRC(autoCaller.rc());
1124
1125 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1126
1127 /* Note: we assume that the default values for attributes of optional
1128 * nodes are assigned in the Data::Data() constructor and don't do it
1129 * here. It implies that this method may only be called after constructing
1130 * a new BIOSSettings object while all its data fields are in the default
1131 * values. Exceptions are fields whose creation time defaults don't match
1132 * values that should be applied when these fields are not explicitly set
1133 * in the settings file (for backwards compatibility reasons). This takes
1134 * place when a setting of a newly created object must default to A while
1135 * the same setting of an object loaded from the old settings file must
1136 * default to B. */
1137
1138 HRESULT rc = S_OK;
1139
1140 /* MAC address (can be null) */
1141 rc = i_updateMacAddress(data.strMACAddress);
1142 if (FAILED(rc)) return rc;
1143
1144 mData.assignCopy(&data);
1145
1146 if (mData->strBandwidthGroup.isNotEmpty())
1147 {
1148 ComObjPtr<BandwidthGroup> group;
1149 rc = bwctl->i_getBandwidthGroupByName(data.strBandwidthGroup, group, true);
1150 if (FAILED(rc)) return rc;
1151 group->i_reference();
1152 }
1153
1154 // Load NAT engine settings.
1155 mNATEngine->i_loadSettings(data.nat);
1156
1157 // leave the lock before setting attachment type
1158 alock.release();
1159
1160 rc = COMSETTER(AttachmentType)(data.mode);
1161 if (FAILED(rc)) return rc;
1162
1163 return S_OK;
1164}
1165
1166/**
1167 * Saves settings to the given adapter node.
1168 *
1169 * Note that the given Adapter node is completely empty on input.
1170 *
1171 * @param data Configuration settings.
1172 *
1173 * @note Locks this object for reading.
1174 */
1175HRESULT NetworkAdapter::i_saveSettings(settings::NetworkAdapter &data)
1176{
1177 AutoCaller autoCaller(this);
1178 AssertComRCReturnRC(autoCaller.rc());
1179
1180 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1181
1182 data = *mData.data();
1183
1184 mNATEngine->i_saveSettings(data.nat);
1185
1186 return S_OK;
1187}
1188
1189/**
1190 * Returns true if any setter method has modified settings of this instance.
1191 * @return
1192 */
1193bool NetworkAdapter::i_isModified()
1194{
1195 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1196
1197 bool fChanged = mData.isBackedUp();
1198 fChanged |= mNATEngine->i_isModified();
1199 return fChanged;
1200}
1201
1202/**
1203 * @note Locks this object for writing.
1204 */
1205void NetworkAdapter::i_rollback()
1206{
1207 /* sanity */
1208 AutoCaller autoCaller(this);
1209 AssertComRCReturnVoid(autoCaller.rc());
1210
1211 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1212
1213 mNATEngine->i_rollback();
1214
1215 mData.rollback();
1216}
1217
1218/**
1219 * @note Locks this object for writing, together with the peer object (also
1220 * for writing) if there is one.
1221 */
1222void NetworkAdapter::i_commit()
1223{
1224 /* sanity */
1225 AutoCaller autoCaller(this);
1226 AssertComRCReturnVoid(autoCaller.rc());
1227
1228 /* sanity too */
1229 AutoCaller peerCaller(mPeer);
1230 AssertComRCReturnVoid(peerCaller.rc());
1231
1232 /* lock both for writing since we modify both (mPeer is "master" so locked
1233 * first) */
1234 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1235
1236 mNATEngine->i_commit();
1237
1238 if (mData.isBackedUp())
1239 {
1240 mData.commit();
1241 if (mPeer)
1242 {
1243 /* attach new data to the peer and reshare it */
1244 mPeer->mData.attach(mData);
1245 }
1246 }
1247}
1248
1249/**
1250 * @note Locks this object for writing, together with the peer object
1251 * represented by @a aThat (locked for reading).
1252 */
1253void NetworkAdapter::i_copyFrom(NetworkAdapter *aThat)
1254{
1255 AssertReturnVoid(aThat != NULL);
1256
1257 /* sanity */
1258 AutoCaller autoCaller(this);
1259 AssertComRCReturnVoid(autoCaller.rc());
1260
1261 /* sanity too */
1262 AutoCaller thatCaller(aThat);
1263 AssertComRCReturnVoid(thatCaller.rc());
1264
1265 mNATEngine->i_copyFrom(aThat->mNATEngine);
1266
1267 /* peer is not modified, lock it for reading (aThat is "master" so locked
1268 * first) */
1269 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1270 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1271
1272 /* this will back up current data */
1273 mData.assignCopy(aThat->mData);
1274
1275}
1276
1277/**
1278 * Applies the defaults for this network adapter.
1279 *
1280 * @note This method currently assumes that the object is in the state after
1281 * calling init(), it does not set defaults from an arbitrary state.
1282 */
1283void NetworkAdapter::i_applyDefaults(GuestOSType *aOsType)
1284{
1285 /* sanity */
1286 AutoCaller autoCaller(this);
1287 AssertComRCReturnVoid(autoCaller.rc());
1288
1289 mNATEngine->i_applyDefaults();
1290
1291 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1292
1293 bool e1000enabled = false;
1294#ifdef VBOX_WITH_E1000
1295 e1000enabled = true;
1296#endif // VBOX_WITH_E1000
1297
1298 NetworkAdapterType_T defaultType;
1299 if (aOsType)
1300 defaultType = aOsType->i_networkAdapterType();
1301 else
1302 {
1303#ifdef VBOX_WITH_E1000
1304 defaultType = NetworkAdapterType_I82540EM;
1305#else
1306 defaultType = NetworkAdapterType_Am79C973A;
1307#endif
1308 }
1309
1310
1311 /* Set default network adapter for this OS type */
1312 if (defaultType == NetworkAdapterType_I82540EM ||
1313 defaultType == NetworkAdapterType_I82543GC ||
1314 defaultType == NetworkAdapterType_I82545EM)
1315 {
1316 if (e1000enabled)
1317 mData->type = defaultType;
1318 }
1319 else
1320 mData->type = defaultType;
1321
1322 /* Enable the first one adapter and set it to NAT */
1323 /** @todo r=klaus remove this long term, since a newly created VM should
1324 * have no additional hardware components unless configured either
1325 * explicitly or through Machine::applyDefaults. */
1326 if (aOsType && mData->ulSlot == 0)
1327 {
1328 mData->fEnabled = true;
1329 if (mData->strMACAddress.isEmpty())
1330 i_generateMACAddress();
1331 mData->mode = NetworkAttachmentType_NAT;
1332 }
1333 mData->fCableConnected = true;
1334}
1335
1336bool NetworkAdapter::i_hasDefaults()
1337{
1338 /* sanity */
1339 AutoCaller autoCaller(this);
1340 AssertComRCReturn(autoCaller.rc(), true);
1341
1342 ComObjPtr<GuestOSType> pGuestOSType;
1343 HRESULT rc = mParent->i_getVirtualBox()->i_findGuestOSType(mParent->i_getOSTypeId(),
1344 pGuestOSType);
1345 if (FAILED(rc))
1346 return false;
1347
1348 NetworkAdapterType_T defaultType = pGuestOSType->i_networkAdapterType();
1349
1350 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1351
1352 if ( !mData->fEnabled
1353 && mData->strMACAddress.isEmpty()
1354 && mData->type == defaultType
1355 && mData->fCableConnected
1356 && mData->ulLineSpeed == 0
1357 && mData->enmPromiscModePolicy == NetworkAdapterPromiscModePolicy_Deny
1358 && mData->mode == NetworkAttachmentType_Null
1359 && mData->strBridgedName.isEmpty()
1360 && mData->strInternalNetworkName.isEmpty()
1361 && mData->strHostOnlyName.isEmpty()
1362 && mData->strNATNetworkName.isEmpty()
1363 && mData->strGenericDriver.isEmpty()
1364 && mData->genericProperties.size() == 0)
1365 {
1366 /* Could be default, check NAT defaults. */
1367 return mNATEngine->i_hasDefaults();
1368 }
1369
1370 return false;
1371}
1372
1373ComObjPtr<NetworkAdapter> NetworkAdapter::i_getPeer()
1374{
1375 return mPeer;
1376}
1377
1378
1379// private methods
1380////////////////////////////////////////////////////////////////////////////////
1381
1382/**
1383 * Generates a new unique MAC address based on our vendor ID and
1384 * parts of a GUID.
1385 *
1386 * @note Must be called from under the object's write lock or within the init
1387 * span.
1388 */
1389void NetworkAdapter::i_generateMACAddress()
1390{
1391 Utf8Str mac;
1392 Host::i_generateMACAddress(mac);
1393 LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str()));
1394 mData->strMACAddress = mac;
1395}
1396
1397HRESULT NetworkAdapter::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
1398{
1399 LogFlowThisFuncEnter();
1400
1401 HRESULT hrc = S_OK;
1402
1403 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1404
1405 if (mData->strBandwidthGroup.isNotEmpty())
1406 {
1407 ComObjPtr<BandwidthGroup> pBwGroup;
1408 hrc = mParent->i_getBandwidthGroup(mData->strBandwidthGroup, pBwGroup, true /* fSetError */);
1409
1410 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1411 * of the group was checked when it was attached. */
1412 if (SUCCEEDED(hrc))
1413 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
1414 }
1415
1416 LogFlowThisFuncLeave();
1417 return hrc;
1418}
1419
1420HRESULT NetworkAdapter::setBandwidthGroup(const ComPtr<IBandwidthGroup> &aBandwidthGroup)
1421{
1422 LogFlowThisFuncEnter();
1423
1424 /* the machine needs to be mutable */
1425 AutoMutableOrSavedStateDependency adep(mParent);
1426 if (FAILED(adep.rc())) return adep.rc();
1427
1428 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1429
1430 IBandwidthGroup *iBw = aBandwidthGroup;
1431 Utf8Str strBwGroup;
1432 if (aBandwidthGroup)
1433 strBwGroup = static_cast<BandwidthGroup *>(iBw)->i_getName();
1434
1435 if (mData->strBandwidthGroup != strBwGroup)
1436 {
1437 ComObjPtr<BandwidthGroup> pBwGroup;
1438 if (!strBwGroup.isEmpty())
1439 {
1440 HRESULT hrc = mParent->i_getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
1441 NOREF(hrc);
1442 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1443 of the group was checked when it was attached. */
1444 }
1445
1446 i_updateBandwidthGroup(pBwGroup);
1447
1448 // leave the lock before informing callbacks
1449 alock.release();
1450
1451 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1452 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
1453 mlock.release();
1454
1455 /** @todo changeAdapter=???. */
1456 mParent->i_onNetworkAdapterChange(this, FALSE);
1457 }
1458
1459 LogFlowThisFuncLeave();
1460 return S_OK;
1461}
1462
1463void NetworkAdapter::i_updateBandwidthGroup(BandwidthGroup *aBwGroup)
1464{
1465 LogFlowThisFuncEnter();
1466 Assert(isWriteLockOnCurrentThread());
1467
1468 ComObjPtr<BandwidthGroup> pOldBwGroup;
1469 if (!mData->strBandwidthGroup.isEmpty())
1470 {
1471 HRESULT hrc = mParent->i_getBandwidthGroup(mData->strBandwidthGroup, pOldBwGroup, false /* fSetError */);
1472 NOREF(hrc);
1473 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of
1474 the group was checked when it was attached. */
1475 }
1476
1477 mData.backup();
1478 if (!pOldBwGroup.isNull())
1479 {
1480 pOldBwGroup->i_release();
1481 mData->strBandwidthGroup = Utf8Str::Empty;
1482 }
1483
1484 if (aBwGroup)
1485 {
1486 mData->strBandwidthGroup = aBwGroup->i_getName();
1487 aBwGroup->i_reference();
1488 }
1489
1490 LogFlowThisFuncLeave();
1491}
1492
1493
1494HRESULT NetworkAdapter::i_switchFromNatNetworking(const com::Utf8Str &networkName)
1495{
1496 HRESULT hrc;
1497 MachineState_T state;
1498
1499 hrc = mParent->COMGETTER(State)(&state);
1500 if (FAILED(hrc))
1501 return hrc;
1502
1503 if ( state == MachineState_Running
1504 || state == MachineState_Paused)
1505 {
1506 Bstr bstrName;
1507 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1508 LogRel(("VM '%ls' stops using NAT network '%s'\n", bstrName.raw(), networkName.c_str()));
1509 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefDec(Bstr(networkName).raw());
1510 if (natCount == -1)
1511 return E_INVALIDARG; /* no such network */
1512 }
1513
1514 return S_OK;
1515}
1516
1517
1518HRESULT NetworkAdapter::i_switchToNatNetworking(const com::Utf8Str &aNatNetworkName)
1519{
1520 HRESULT hrc;
1521 MachineState_T state;
1522
1523 hrc = mParent->COMGETTER(State)(&state);
1524 if (FAILED(hrc))
1525 return hrc;
1526
1527 if ( state == MachineState_Running
1528 || state == MachineState_Paused)
1529 {
1530 Bstr bstrName;
1531 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1532 LogRel(("VM '%ls' starts using NAT network '%s'\n", bstrName.raw(), aNatNetworkName.c_str()));
1533 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefInc(Bstr(aNatNetworkName).raw());
1534 if (natCount == -1)
1535 return E_INVALIDARG; /* not found */
1536 }
1537
1538 return S_OK;
1539}
1540/* 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