VirtualBox

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

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

Copyright year updates by scm.

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