VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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