VirtualBox

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

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

Work around inability of XPCOM to handle enums starting with a digit.

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