VirtualBox

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

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

Main/*: From now on any valid UTF8 string is considered a valid guest OS type. Of course not all of them are known, so the API clients must be prepared to deal with not having a matching IGuestOSType object.
Frontends/VBoxManage+VBoxShell: adjust to deal with the change

  • 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 72919 2018-07-05 14:44:31Z 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;
1236 if (aOsType)
1237 defaultType = aOsType->i_networkAdapterType();
1238 else
1239 {
1240#ifdef VBOX_WITH_E1000
1241 defaultType = NetworkAdapterType_I82540EM;
1242#else
1243 defaultType = NetworkAdapterType_Am79C973A;
1244#endif
1245 }
1246
1247
1248 /* Set default network adapter for this OS type */
1249 if (defaultType == NetworkAdapterType_I82540EM ||
1250 defaultType == NetworkAdapterType_I82543GC ||
1251 defaultType == NetworkAdapterType_I82545EM)
1252 {
1253 if (e1000enabled)
1254 mData->type = defaultType;
1255 }
1256 else
1257 mData->type = defaultType;
1258
1259 /* Enable the first one adapter and set it to NAT */
1260 /** @todo r=klaus remove this long term, since a newly created VM should
1261 * have no additional hardware components unless configured either
1262 * explicitly or through Machine::applyDefaults. */
1263 if (aOsType && mData->ulSlot == 0)
1264 {
1265 mData->fEnabled = true;
1266 if (mData->strMACAddress.isEmpty())
1267 i_generateMACAddress();
1268 mData->mode = NetworkAttachmentType_NAT;
1269 }
1270 mData->fCableConnected = true;
1271}
1272
1273bool NetworkAdapter::i_hasDefaults()
1274{
1275 /* sanity */
1276 AutoCaller autoCaller(this);
1277 AssertComRCReturn(autoCaller.rc(), true);
1278
1279 ComObjPtr<GuestOSType> pGuestOSType;
1280 HRESULT rc = mParent->i_getVirtualBox()->i_findGuestOSType(mParent->i_getOSTypeId(),
1281 pGuestOSType);
1282 if (FAILED(rc))
1283 return false;
1284
1285 NetworkAdapterType_T defaultType = pGuestOSType->i_networkAdapterType();
1286
1287 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1288
1289 if ( !mData->fEnabled
1290 && mData->strMACAddress.isEmpty()
1291 && mData->type == defaultType
1292 && mData->fCableConnected
1293 && mData->ulLineSpeed == 0
1294 && mData->enmPromiscModePolicy == NetworkAdapterPromiscModePolicy_Deny
1295 && mData->mode == NetworkAttachmentType_Null
1296 && mData->strBridgedName.isEmpty()
1297 && mData->strInternalNetworkName.isEmpty()
1298 && mData->strHostOnlyName.isEmpty()
1299 && mData->strNATNetworkName.isEmpty()
1300 && mData->strGenericDriver.isEmpty()
1301 && mData->genericProperties.size() == 0)
1302 {
1303 /* Could be default, check NAT defaults. */
1304 return mNATEngine->i_hasDefaults();
1305 }
1306
1307 return false;
1308}
1309
1310ComObjPtr<NetworkAdapter> NetworkAdapter::i_getPeer()
1311{
1312 return mPeer;
1313}
1314
1315
1316// private methods
1317////////////////////////////////////////////////////////////////////////////////
1318
1319/**
1320 * Generates a new unique MAC address based on our vendor ID and
1321 * parts of a GUID.
1322 *
1323 * @note Must be called from under the object's write lock or within the init
1324 * span.
1325 */
1326void NetworkAdapter::i_generateMACAddress()
1327{
1328 Utf8Str mac;
1329 Host::i_generateMACAddress(mac);
1330 LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str()));
1331 mData->strMACAddress = mac;
1332}
1333
1334HRESULT NetworkAdapter::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
1335{
1336 LogFlowThisFuncEnter();
1337
1338 HRESULT hrc = S_OK;
1339
1340 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1341
1342 if (mData->strBandwidthGroup.isNotEmpty())
1343 {
1344 ComObjPtr<BandwidthGroup> pBwGroup;
1345 hrc = mParent->i_getBandwidthGroup(mData->strBandwidthGroup, pBwGroup, true /* fSetError */);
1346
1347 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1348 * of the group was checked when it was attached. */
1349 if (SUCCEEDED(hrc))
1350 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
1351 }
1352
1353 LogFlowThisFuncLeave();
1354 return hrc;
1355}
1356
1357HRESULT NetworkAdapter::setBandwidthGroup(const ComPtr<IBandwidthGroup> &aBandwidthGroup)
1358{
1359 LogFlowThisFuncEnter();
1360
1361 /* the machine needs to be mutable */
1362 AutoMutableOrSavedStateDependency adep(mParent);
1363 if (FAILED(adep.rc())) return adep.rc();
1364
1365 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1366
1367 IBandwidthGroup *iBw = aBandwidthGroup;
1368 Utf8Str strBwGroup;
1369 if (aBandwidthGroup)
1370 strBwGroup = static_cast<BandwidthGroup *>(iBw)->i_getName();
1371
1372 if (mData->strBandwidthGroup != strBwGroup)
1373 {
1374 ComObjPtr<BandwidthGroup> pBwGroup;
1375 if (!strBwGroup.isEmpty())
1376 {
1377 HRESULT hrc = mParent->i_getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
1378 NOREF(hrc);
1379 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1380 of the group was checked when it was attached. */
1381 }
1382
1383 i_updateBandwidthGroup(pBwGroup);
1384
1385 // leave the lock before informing callbacks
1386 alock.release();
1387
1388 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1389 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
1390 mlock.release();
1391
1392 /** @todo changeAdapter=???. */
1393 mParent->i_onNetworkAdapterChange(this, FALSE);
1394 }
1395
1396 LogFlowThisFuncLeave();
1397 return S_OK;
1398}
1399
1400void NetworkAdapter::i_updateBandwidthGroup(BandwidthGroup *aBwGroup)
1401{
1402 LogFlowThisFuncEnter();
1403 Assert(isWriteLockOnCurrentThread());
1404
1405 ComObjPtr<BandwidthGroup> pOldBwGroup;
1406 if (!mData->strBandwidthGroup.isEmpty())
1407 {
1408 HRESULT hrc = mParent->i_getBandwidthGroup(mData->strBandwidthGroup, pOldBwGroup, false /* fSetError */);
1409 NOREF(hrc);
1410 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of
1411 the group was checked when it was attached. */
1412 }
1413
1414 mData.backup();
1415 if (!pOldBwGroup.isNull())
1416 {
1417 pOldBwGroup->i_release();
1418 mData->strBandwidthGroup = Utf8Str::Empty;
1419 }
1420
1421 if (aBwGroup)
1422 {
1423 mData->strBandwidthGroup = aBwGroup->i_getName();
1424 aBwGroup->i_reference();
1425 }
1426
1427 LogFlowThisFuncLeave();
1428}
1429
1430
1431HRESULT NetworkAdapter::i_switchFromNatNetworking(const com::Utf8Str &networkName)
1432{
1433 HRESULT hrc;
1434 MachineState_T state;
1435
1436 hrc = mParent->COMGETTER(State)(&state);
1437 if (FAILED(hrc))
1438 return hrc;
1439
1440 if ( state == MachineState_Running
1441 || state == MachineState_Paused)
1442 {
1443 Bstr bstrName;
1444 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1445 LogRel(("VM '%ls' stops using NAT network '%s'\n", bstrName.raw(), networkName.c_str()));
1446 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefDec(Bstr(networkName).raw());
1447 if (natCount == -1)
1448 return E_INVALIDARG; /* no such network */
1449 }
1450
1451 return S_OK;
1452}
1453
1454
1455HRESULT NetworkAdapter::i_switchToNatNetworking(const com::Utf8Str &aNatNetworkName)
1456{
1457 HRESULT hrc;
1458 MachineState_T state;
1459
1460 hrc = mParent->COMGETTER(State)(&state);
1461 if (FAILED(hrc))
1462 return hrc;
1463
1464 if ( state == MachineState_Running
1465 || state == MachineState_Paused)
1466 {
1467 Bstr bstrName;
1468 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1469 LogRel(("VM '%ls' starts using NAT network '%s'\n", bstrName.raw(), aNatNetworkName.c_str()));
1470 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefInc(Bstr(aNatNetworkName).raw());
1471 if (natCount == -1)
1472 return E_INVALIDARG; /* not found */
1473 }
1474
1475 return S_OK;
1476}
1477/* 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