VirtualBox

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

Last change on this file since 48538 was 48538, checked in by vboxsync, 11 years ago

Main/NetworkAdapter+Machine+Appliance+SystemProperties+Medium+Console+Settings+IDL: make NAT networking a separate network attachment type which improves the user experience, store the necessary settings, plus changing the design of the methods which will move images and entire VMs, they lacked a progress object
Frontends/VirtualBox: adapted fully, can configure NAT networks with proper drop down list support
Frontends/VBoxManage: also supports NAT networks completely, and adds the long missing code to list intnets

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