VirtualBox

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

Last change on this file since 34079 was 33825, checked in by vboxsync, 14 years ago

Main,NAT: Managing port-forwarding at runtime. (xTracker/#4835).

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