VirtualBox

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

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

Devices: bugref:9932 DrvVMNet and host-only network initial implementation

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