VirtualBox

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

Last change on this file since 98110 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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