VirtualBox

source: vbox/trunk/src/VBox/Main/NetworkAdapterImpl.cpp@ 28406

Last change on this file since 28406 was 28406, checked in by vboxsync, 15 years ago

Devices, Main, FE/Qt: re-committed support for VDE virtual network switches for Linux and FreeBSD hosts. Contributed by Renzo Davoli, VirtualSquare, University of Bologna

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