VirtualBox

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

Last change on this file since 92996 was 92996, checked in by vboxsync, 3 years ago

virtio-net works on linux in local testing, and virtio-scsi works on windows. Integrating the switchover to make DevVirtioNet_1_0.cpp the 'virtio-net' option in the Virtual Network Controller list.

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