VirtualBox

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

Last change on this file since 98715 was 98292, checked in by vboxsync, 23 months ago

Main/src-server: rc -> hrc/vrc. Enabled scm rc checks. bugref:10223

  • 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 98292 2023-01-25 01:14:53Z 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.hrc());
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.hrc());
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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 hrc = 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 && hrc == 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 hrc = 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 hrc = 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 hrc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
395 }
396
397 if (SUCCEEDED(hrc))
398 mData->strMACAddress = aMACAddress;
399 }
400 }
401
402 return hrc;
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.hrc())) return adep.hrc();
410
411 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
412 mData.backup();
413
414 HRESULT hrc = i_updateMacAddress(aMACAddress);
415 if (SUCCEEDED(hrc))
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 hrc;
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
504
505 Bstr canonicalName = aBridgedInterface;
506#ifdef RT_OS_DARWIN
507 com::SafeIfaceArray<IHostNetworkInterface> hostNetworkInterfaces;
508 ComPtr<IHost> host;
509 HRESULT hrc = mParent->i_getVirtualBox()->COMGETTER(Host)(host.asOutParam());
510 if (SUCCEEDED(hrc))
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc())) return adep.hrc();
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.hrc());
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 /* MAC address (can be null) */
1215 HRESULT hrc = i_updateMacAddress(data.strMACAddress);
1216 if (FAILED(hrc)) return hrc;
1217
1218 mData.assignCopy(&data);
1219
1220 if (mData->strBandwidthGroup.isNotEmpty())
1221 {
1222 ComObjPtr<BandwidthGroup> group;
1223 hrc = bwctl->i_getBandwidthGroupByName(data.strBandwidthGroup, group, true);
1224 if (FAILED(hrc)) return hrc;
1225 group->i_reference();
1226 }
1227
1228 // Load NAT engine settings.
1229 mNATEngine->i_loadSettings(data.nat);
1230
1231 // leave the lock before setting attachment type
1232 alock.release();
1233
1234 hrc = COMSETTER(AttachmentType)(data.mode);
1235 if (FAILED(hrc)) return hrc;
1236
1237 return S_OK;
1238}
1239
1240/**
1241 * Saves settings to the given adapter node.
1242 *
1243 * Note that the given Adapter node is completely empty on input.
1244 *
1245 * @param data Configuration settings.
1246 *
1247 * @note Locks this object for reading.
1248 */
1249HRESULT NetworkAdapter::i_saveSettings(settings::NetworkAdapter &data)
1250{
1251 AutoCaller autoCaller(this);
1252 AssertComRCReturnRC(autoCaller.hrc());
1253
1254 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1255
1256 data = *mData.data();
1257
1258 mNATEngine->i_saveSettings(data.nat);
1259
1260 return S_OK;
1261}
1262
1263/**
1264 * Returns true if any setter method has modified settings of this instance.
1265 * @return
1266 */
1267bool NetworkAdapter::i_isModified()
1268{
1269 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1270
1271 bool fChanged = mData.isBackedUp();
1272 fChanged |= mNATEngine->i_isModified();
1273 return fChanged;
1274}
1275
1276/**
1277 * @note Locks this object for writing.
1278 */
1279void NetworkAdapter::i_rollback()
1280{
1281 /* sanity */
1282 AutoCaller autoCaller(this);
1283 AssertComRCReturnVoid(autoCaller.hrc());
1284
1285 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1286
1287 mNATEngine->i_rollback();
1288
1289 mData.rollback();
1290}
1291
1292/**
1293 * @note Locks this object for writing, together with the peer object (also
1294 * for writing) if there is one.
1295 */
1296void NetworkAdapter::i_commit()
1297{
1298 /* sanity */
1299 AutoCaller autoCaller(this);
1300 AssertComRCReturnVoid(autoCaller.hrc());
1301
1302 /* sanity too */
1303 AutoCaller peerCaller(mPeer);
1304 AssertComRCReturnVoid(peerCaller.hrc());
1305
1306 /* lock both for writing since we modify both (mPeer is "master" so locked
1307 * first) */
1308 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1309
1310 mNATEngine->i_commit();
1311
1312 if (mData.isBackedUp())
1313 {
1314 mData.commit();
1315 if (mPeer)
1316 {
1317 /* attach new data to the peer and reshare it */
1318 mPeer->mData.attach(mData);
1319 }
1320 }
1321}
1322
1323/**
1324 * @note Locks this object for writing, together with the peer object
1325 * represented by @a aThat (locked for reading).
1326 */
1327void NetworkAdapter::i_copyFrom(NetworkAdapter *aThat)
1328{
1329 AssertReturnVoid(aThat != NULL);
1330
1331 /* sanity */
1332 AutoCaller autoCaller(this);
1333 AssertComRCReturnVoid(autoCaller.hrc());
1334
1335 /* sanity too */
1336 AutoCaller thatCaller(aThat);
1337 AssertComRCReturnVoid(thatCaller.hrc());
1338
1339 mNATEngine->i_copyFrom(aThat->mNATEngine);
1340
1341 /* peer is not modified, lock it for reading (aThat is "master" so locked
1342 * first) */
1343 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1344 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1345
1346 /* this will back up current data */
1347 mData.assignCopy(aThat->mData);
1348
1349}
1350
1351/**
1352 * Applies the defaults for this network adapter.
1353 *
1354 * @note This method currently assumes that the object is in the state after
1355 * calling init(), it does not set defaults from an arbitrary state.
1356 */
1357void NetworkAdapter::i_applyDefaults(GuestOSType *aOsType)
1358{
1359 /* sanity */
1360 AutoCaller autoCaller(this);
1361 AssertComRCReturnVoid(autoCaller.hrc());
1362
1363 mNATEngine->i_applyDefaults();
1364
1365 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1366
1367 bool e1000enabled = false;
1368#ifdef VBOX_WITH_E1000
1369 e1000enabled = true;
1370#endif // VBOX_WITH_E1000
1371
1372 NetworkAdapterType_T defaultType;
1373 if (aOsType)
1374 defaultType = aOsType->i_networkAdapterType();
1375 else
1376 {
1377#ifdef VBOX_WITH_E1000
1378 defaultType = NetworkAdapterType_I82540EM;
1379#else
1380 defaultType = NetworkAdapterType_Am79C973A;
1381#endif
1382 }
1383
1384
1385 /* Set default network adapter for this OS type */
1386 if (defaultType == NetworkAdapterType_I82540EM ||
1387 defaultType == NetworkAdapterType_I82543GC ||
1388 defaultType == NetworkAdapterType_I82545EM)
1389 {
1390 if (e1000enabled)
1391 mData->type = defaultType;
1392 }
1393 else
1394 mData->type = defaultType;
1395
1396 /* Enable the first one adapter and set it to NAT */
1397 /** @todo r=klaus remove this long term, since a newly created VM should
1398 * have no additional hardware components unless configured either
1399 * explicitly or through Machine::applyDefaults. */
1400 if (aOsType && mData->ulSlot == 0)
1401 {
1402 mData->fEnabled = true;
1403 if (mData->strMACAddress.isEmpty())
1404 i_generateMACAddress();
1405 mData->mode = NetworkAttachmentType_NAT;
1406 }
1407 mData->fCableConnected = true;
1408}
1409
1410bool NetworkAdapter::i_hasDefaults()
1411{
1412 /* sanity */
1413 AutoCaller autoCaller(this);
1414 AssertComRCReturn(autoCaller.hrc(), true);
1415
1416 ComObjPtr<GuestOSType> pGuestOSType;
1417 HRESULT hrc = mParent->i_getVirtualBox()->i_findGuestOSType(mParent->i_getOSTypeId(), pGuestOSType);
1418 if (FAILED(hrc))
1419 return false;
1420
1421 NetworkAdapterType_T defaultType = pGuestOSType->i_networkAdapterType();
1422
1423 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1424
1425 if ( !mData->fEnabled
1426 && mData->strMACAddress.isEmpty()
1427 && mData->type == defaultType
1428 && mData->fCableConnected
1429 && mData->ulLineSpeed == 0
1430 && mData->enmPromiscModePolicy == NetworkAdapterPromiscModePolicy_Deny
1431 && mData->mode == NetworkAttachmentType_Null
1432 && mData->strBridgedName.isEmpty()
1433 && mData->strInternalNetworkName.isEmpty()
1434 && mData->strHostOnlyName.isEmpty()
1435 && mData->strNATNetworkName.isEmpty()
1436 && mData->strGenericDriver.isEmpty()
1437 && mData->genericProperties.size() == 0)
1438 {
1439 /* Could be default, check NAT defaults. */
1440 return mNATEngine->i_hasDefaults();
1441 }
1442
1443 return false;
1444}
1445
1446ComObjPtr<NetworkAdapter> NetworkAdapter::i_getPeer()
1447{
1448 return mPeer;
1449}
1450
1451
1452// private methods
1453////////////////////////////////////////////////////////////////////////////////
1454
1455/**
1456 * Generates a new unique MAC address based on our vendor ID and
1457 * parts of a GUID.
1458 *
1459 * @note Must be called from under the object's write lock or within the init
1460 * span.
1461 */
1462void NetworkAdapter::i_generateMACAddress()
1463{
1464 Utf8Str mac;
1465 Host::i_generateMACAddress(mac);
1466 LogFlowThisFunc(("generated MAC: '%s'\n", mac.c_str()));
1467 mData->strMACAddress = mac;
1468}
1469
1470HRESULT NetworkAdapter::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
1471{
1472 LogFlowThisFuncEnter();
1473
1474 HRESULT hrc = S_OK;
1475
1476 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1477
1478 if (mData->strBandwidthGroup.isNotEmpty())
1479 {
1480 ComObjPtr<BandwidthGroup> pBwGroup;
1481 hrc = mParent->i_getBandwidthGroup(mData->strBandwidthGroup, pBwGroup, true /* fSetError */);
1482
1483 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1484 * of the group was checked when it was attached. */
1485 if (SUCCEEDED(hrc))
1486 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
1487 }
1488
1489 LogFlowThisFuncLeave();
1490 return hrc;
1491}
1492
1493HRESULT NetworkAdapter::setBandwidthGroup(const ComPtr<IBandwidthGroup> &aBandwidthGroup)
1494{
1495 LogFlowThisFuncEnter();
1496
1497 /* the machine needs to be mutable */
1498 AutoMutableOrSavedStateDependency adep(mParent);
1499 if (FAILED(adep.hrc())) return adep.hrc();
1500
1501 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1502
1503 IBandwidthGroup *iBw = aBandwidthGroup;
1504 Utf8Str strBwGroup;
1505 if (aBandwidthGroup)
1506 strBwGroup = static_cast<BandwidthGroup *>(iBw)->i_getName();
1507
1508 if (mData->strBandwidthGroup != strBwGroup)
1509 {
1510 ComObjPtr<BandwidthGroup> pBwGroup;
1511 if (!strBwGroup.isEmpty())
1512 {
1513 HRESULT hrc = mParent->i_getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
1514 NOREF(hrc);
1515 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence
1516 of the group was checked when it was attached. */
1517 }
1518
1519 i_updateBandwidthGroup(pBwGroup);
1520
1521 // leave the lock before informing callbacks
1522 alock.release();
1523
1524 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
1525 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
1526 mlock.release();
1527
1528 /** @todo changeAdapter=???. */
1529 mParent->i_onNetworkAdapterChange(this, FALSE);
1530 }
1531
1532 LogFlowThisFuncLeave();
1533 return S_OK;
1534}
1535
1536void NetworkAdapter::i_updateBandwidthGroup(BandwidthGroup *aBwGroup)
1537{
1538 LogFlowThisFuncEnter();
1539 Assert(isWriteLockOnCurrentThread());
1540
1541 ComObjPtr<BandwidthGroup> pOldBwGroup;
1542 if (!mData->strBandwidthGroup.isEmpty())
1543 {
1544 HRESULT hrc = mParent->i_getBandwidthGroup(mData->strBandwidthGroup, pOldBwGroup, false /* fSetError */);
1545 NOREF(hrc);
1546 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of
1547 the group was checked when it was attached. */
1548 }
1549
1550 mData.backup();
1551 if (!pOldBwGroup.isNull())
1552 {
1553 pOldBwGroup->i_release();
1554 mData->strBandwidthGroup = Utf8Str::Empty;
1555 }
1556
1557 if (aBwGroup)
1558 {
1559 mData->strBandwidthGroup = aBwGroup->i_getName();
1560 aBwGroup->i_reference();
1561 }
1562
1563 LogFlowThisFuncLeave();
1564}
1565
1566
1567HRESULT NetworkAdapter::i_switchFromNatNetworking(const com::Utf8Str &networkName)
1568{
1569 HRESULT hrc;
1570 MachineState_T state;
1571
1572 hrc = mParent->COMGETTER(State)(&state);
1573 if (FAILED(hrc))
1574 return hrc;
1575
1576 if ( state == MachineState_Running
1577 || state == MachineState_Paused)
1578 {
1579 Bstr bstrName;
1580 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1581 LogRel(("VM '%ls' stops using NAT network '%s'\n", bstrName.raw(), networkName.c_str()));
1582 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefDec(Bstr(networkName).raw());
1583 if (natCount == -1)
1584 return E_INVALIDARG; /* no such network */
1585 }
1586
1587 return S_OK;
1588}
1589
1590
1591HRESULT NetworkAdapter::i_switchToNatNetworking(const com::Utf8Str &aNatNetworkName)
1592{
1593 HRESULT hrc;
1594 MachineState_T state;
1595
1596 hrc = mParent->COMGETTER(State)(&state);
1597 if (FAILED(hrc))
1598 return hrc;
1599
1600 if ( state == MachineState_Running
1601 || state == MachineState_Paused)
1602 {
1603 Bstr bstrName;
1604 hrc = mParent->COMGETTER(Name)(bstrName.asOutParam());
1605 LogRel(("VM '%ls' starts using NAT network '%s'\n", bstrName.raw(), aNatNetworkName.c_str()));
1606 int natCount = mParent->i_getVirtualBox()->i_natNetworkRefInc(Bstr(aNatNetworkName).raw());
1607 if (natCount == -1)
1608 return E_INVALIDARG; /* not found */
1609 }
1610
1611 return S_OK;
1612}
1613/* 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