VirtualBox

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

Last change on this file since 36128 was 36105, checked in by vboxsync, 14 years ago

Main: properly save the promiscous mode

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 46.2 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 36105 2011-02-28 18:00:41Z 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 BaseFinalConstruct();
49}
50
51void NetworkAdapter::FinalRelease()
52{
53 uninit();
54 BaseFinalRelease();
55}
56
57// public initializer/uninitializer for internal purposes only
58////////////////////////////////////////////////////////////////////////////////
59
60/**
61 * Initializes the network adapter object.
62 *
63 * @param aParent Handle of the parent object.
64 */
65HRESULT NetworkAdapter::init(Machine *aParent, ULONG aSlot)
66{
67 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
68
69 ComAssertRet(aParent, E_INVALIDARG);
70 ComAssertRet(aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
71
72 /* Enclose the state transition NotReady->InInit->Ready */
73 AutoInitSpan autoInitSpan(this);
74 AssertReturn(autoInitSpan.isOk(), E_FAIL);
75
76 unconst(mParent) = aParent;
77 unconst(mNATEngine).createObject();
78 mNATEngine->init(aParent, this);
79 /* mPeer is left null */
80
81 m_fModified = false;
82
83 mData.allocate();
84
85 /* initialize data */
86 mData->mSlot = aSlot;
87
88 /* Default limit is not capped/unlimited. */
89 mData->mBandwidthLimit = 0;
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, this, 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, this, 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.isEmpty(), 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.raw();
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 notify 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 notify 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.raw();
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.raw();
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
755
756STDMETHODIMP NetworkAdapter::COMGETTER(PromiscModePolicy)(NetworkAdapterPromiscModePolicy_T *aPromiscModePolicy)
757{
758 CheckComArgOutPointerValid(aPromiscModePolicy);
759
760 AutoCaller autoCaller(this);
761 HRESULT hrc = autoCaller.rc();
762 if (SUCCEEDED(hrc))
763 {
764 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
765 *aPromiscModePolicy = mData->mPromiscModePolicy;
766 }
767 return hrc;
768}
769
770STDMETHODIMP NetworkAdapter::COMSETTER(PromiscModePolicy)(NetworkAdapterPromiscModePolicy_T aPromiscModePolicy)
771{
772 switch (aPromiscModePolicy)
773 {
774 case NetworkAdapterPromiscModePolicy_Deny:
775 case NetworkAdapterPromiscModePolicy_AllowNetwork:
776 case NetworkAdapterPromiscModePolicy_AllowAll:
777 break;
778 default:
779 return setError(E_INVALIDARG, tr("Invalid promiscuous mode policy (%d)"), aPromiscModePolicy);
780 }
781
782 AutoCaller autoCaller(this);
783 HRESULT hrc = autoCaller.rc();
784
785 if (SUCCEEDED(hrc))
786 {
787 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
788 if (aPromiscModePolicy != mData->mPromiscModePolicy)
789 {
790 mData.backup();
791 mData->mPromiscModePolicy = aPromiscModePolicy;
792 m_fModified = true;
793
794 alock.release();
795 mParent->setModifiedLock(Machine::IsModified_NetworkAdapters);
796 mParent->onNetworkAdapterChange(this, TRUE);
797 }
798 }
799
800 return hrc;
801}
802
803STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthLimit) (ULONG *aLimit)
804{
805 CheckComArgOutPointerValid(aLimit);
806
807 AutoCaller autoCaller(this);
808 if (FAILED(autoCaller.rc())) return autoCaller.rc();
809
810 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
811
812 *aLimit = mData->mBandwidthLimit;
813 return S_OK;
814}
815
816STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthLimit) (ULONG aLimit)
817{
818 AutoCaller autoCaller(this);
819 if (FAILED(autoCaller.rc())) return autoCaller.rc();
820
821 /* the machine doesn't need to be mutable */
822
823 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
824
825 if (aLimit != mData->mBandwidthLimit)
826 {
827 mData.backup();
828 mData->mBandwidthLimit = aLimit;
829
830 m_fModified = true;
831 // leave the lock before informing callbacks
832 alock.release();
833
834 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
835 mParent->setModified(Machine::IsModified_NetworkAdapters);
836 mlock.release();
837
838 /* No change in CFGM logic => changeAdapter=FALSE. */
839 mParent->onNetworkAdapterChange(this, FALSE);
840 }
841 return S_OK;
842}
843
844STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
845{
846 CheckComArgOutPointerValid(aEnabled);
847
848 AutoCaller autoCaller(this);
849 if (FAILED(autoCaller.rc())) return autoCaller.rc();
850
851 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
852
853 *aEnabled = mData->mTraceEnabled;
854 return S_OK;
855}
856
857STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
858{
859 AutoCaller autoCaller(this);
860 if (FAILED(autoCaller.rc())) return autoCaller.rc();
861
862 /* the machine needs to be mutable */
863 AutoMutableStateDependency adep(mParent);
864 if (FAILED(adep.rc())) return adep.rc();
865
866 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
867
868 if (aEnabled != mData->mTraceEnabled)
869 {
870 mData.backup();
871 mData->mTraceEnabled = aEnabled;
872
873 m_fModified = true;
874 // leave the lock before informing callbacks
875 alock.release();
876
877 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
878 mParent->setModified(Machine::IsModified_NetworkAdapters);
879 mlock.release();
880
881 /* Adapt the CFGM logic changeAdapter=TRUE */
882 mParent->onNetworkAdapterChange(this, TRUE);
883 }
884
885 return S_OK;
886}
887
888STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
889{
890 CheckComArgOutPointerValid(aTraceFile);
891
892 AutoCaller autoCaller(this);
893 if (FAILED(autoCaller.rc())) return autoCaller.rc();
894
895 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
896
897 mData->mTraceFile.cloneTo(aTraceFile);
898
899 return S_OK;
900}
901
902STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
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->mTraceFile != aTraceFile)
914 {
915 mData.backup();
916 mData->mTraceFile = aTraceFile;
917
918 m_fModified = true;
919 // leave the lock before informing callbacks
920 alock.release();
921
922 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
923 mParent->setModified(Machine::IsModified_NetworkAdapters);
924 mlock.release();
925
926 /* No change in CFGM logic => changeAdapter=FALSE. */
927 mParent->onNetworkAdapterChange(this, FALSE);
928 }
929
930 return S_OK;
931}
932
933STDMETHODIMP NetworkAdapter::COMGETTER(NatDriver) (INATEngine **aNatDriver)
934{
935 CheckComArgOutPointerValid(aNatDriver);
936
937 AutoCaller autoCaller(this);
938 if (FAILED(autoCaller.rc())) return autoCaller.rc();
939
940 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
941
942 mNATEngine.queryInterfaceTo(aNatDriver);
943
944 return S_OK;
945}
946
947STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority) (ULONG *aBootPriority)
948{
949 CheckComArgOutPointerValid(aBootPriority);
950
951 AutoCaller autoCaller(this);
952 if (FAILED(autoCaller.rc())) return autoCaller.rc();
953
954 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
955
956 *aBootPriority = mData->mBootPriority;
957
958 return S_OK;
959}
960
961STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority) (ULONG aBootPriority)
962{
963 AutoCaller autoCaller(this);
964 if (FAILED(autoCaller.rc())) return autoCaller.rc();
965
966 /* the machine needs to be mutable */
967 AutoMutableStateDependency adep(mParent);
968 if (FAILED(adep.rc())) return adep.rc();
969
970 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
971
972 if (aBootPriority != mData->mBootPriority)
973 {
974 mData.backup();
975 mData->mBootPriority = aBootPriority;
976
977 m_fModified = true;
978 // leave the lock before informing callbacks
979 alock.release();
980
981 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
982 mParent->setModified(Machine::IsModified_NetworkAdapters);
983 mlock.release();
984
985 /* No change in CFGM logic => changeAdapter=FALSE. */
986 mParent->onNetworkAdapterChange(this, FALSE);
987 }
988
989 return S_OK;
990}
991
992// INetworkAdapter methods
993////////////////////////////////////////////////////////////////////////////////
994
995STDMETHODIMP NetworkAdapter::AttachToNAT()
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 if (mData->mAttachmentType != NetworkAttachmentType_NAT)
1007 {
1008 mData.backup();
1009
1010 // Commented this for now as it resets the parameter mData->mNATNetwork
1011 // which is essential while changing the Attachment dynamically.
1012 //detach();
1013
1014 mData->mAttachmentType = NetworkAttachmentType_NAT;
1015
1016 m_fModified = true;
1017 // leave the lock before informing callbacks
1018 alock.release();
1019
1020 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1021 mParent->setModified(Machine::IsModified_NetworkAdapters);
1022 mlock.release();
1023
1024 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1025 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1026 if (FAILED(rc))
1027 {
1028 /* If changing the attachment failed then we can't assume
1029 * that the previous attachment will attach correctly
1030 * and thus return error along with detaching all
1031 * attachments.
1032 */
1033 Detach();
1034 return rc;
1035 }
1036 }
1037
1038 return S_OK;
1039}
1040
1041STDMETHODIMP NetworkAdapter::AttachToBridgedInterface()
1042{
1043 AutoCaller autoCaller(this);
1044 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1045
1046 /* the machine needs to be mutable */
1047 AutoMutableStateDependency adep(mParent);
1048 if (FAILED(adep.rc())) return adep.rc();
1049
1050 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1051
1052 /* don't do anything if we're already host interface attached */
1053 if (mData->mAttachmentType != NetworkAttachmentType_Bridged)
1054 {
1055 mData.backup();
1056
1057 /* first detach the current attachment */
1058 // Commented this for now as it reset the parameter mData->mHostInterface
1059 // which is essential while changing the Attachment dynamically.
1060 //detach();
1061
1062 mData->mAttachmentType = NetworkAttachmentType_Bridged;
1063
1064 m_fModified = true;
1065 // leave the lock before informing callbacks
1066 alock.release();
1067
1068 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1069 mParent->setModified(Machine::IsModified_NetworkAdapters);
1070 mlock.release();
1071
1072 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1073 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1074 if (FAILED(rc))
1075 {
1076 /* If changing the attachment failed then we can't assume that the
1077 * previous attachment will attach correctly and thus return error
1078 * along with detaching all attachments.
1079 */
1080 Detach();
1081 return rc;
1082 }
1083 }
1084
1085 return S_OK;
1086}
1087
1088STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
1089{
1090 AutoCaller autoCaller(this);
1091 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1092
1093 /* the machine needs to be mutable */
1094 AutoMutableStateDependency adep(mParent);
1095 if (FAILED(adep.rc())) return adep.rc();
1096
1097 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1098
1099 /* don't do anything if we're already internal network attached */
1100 if (mData->mAttachmentType != NetworkAttachmentType_Internal)
1101 {
1102 mData.backup();
1103
1104 /* first detach the current attachment */
1105 // Commented this for now as it reset the parameter mData->mInternalNetwork
1106 // which is essential while changing the Attachment dynamically.
1107 //detach();
1108
1109 /* there must an internal network name */
1110 if (mData->mInternalNetwork.isEmpty())
1111 {
1112 LogRel (("Internal network name not defined, "
1113 "setting to default \"intnet\"\n"));
1114 mData->mInternalNetwork = "intnet";
1115 }
1116
1117 mData->mAttachmentType = NetworkAttachmentType_Internal;
1118
1119 m_fModified = true;
1120 // leave the lock before informing callbacks
1121 alock.release();
1122
1123 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1124 mParent->setModified(Machine::IsModified_NetworkAdapters);
1125 mlock.release();
1126
1127 /* Adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1128 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1129 if (FAILED(rc))
1130 {
1131 /* If changing the attachment failed then we can't assume
1132 * that the previous attachment will attach correctly
1133 * and thus return error along with detaching all
1134 * attachments.
1135 */
1136 Detach();
1137 return rc;
1138 }
1139 }
1140
1141 return S_OK;
1142}
1143
1144STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface()
1145{
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_HostOnly)
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_HostOnly;
1166
1167 m_fModified = true;
1168 // leave the lock before informing callbacks
1169 alock.release();
1170
1171 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1172 mParent->setModified(Machine::IsModified_NetworkAdapters);
1173 mlock.release();
1174
1175 /* Adapt the CFGM logic and notify the guest => changeAdpater=TRUE. */
1176 HRESULT rc = mParent->onNetworkAdapterChange(this, TRUE);
1177 if (FAILED(rc))
1178 {
1179 /* If changing the attachment failed then we can't assume
1180 * that the previous attachment will attach correctly
1181 * and thus return error along with detaching all
1182 * attachments.
1183 */
1184 Detach();
1185 return rc;
1186 }
1187 }
1188
1189 return S_OK;
1190}
1191
1192STDMETHODIMP NetworkAdapter::AttachToVDE()
1193{
1194#if defined(VBOX_WITH_VDE)
1195 AutoCaller autoCaller(this);
1196 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1197
1198 /* the machine needs to be mutable */
1199 AutoMutableStateDependency adep (mParent);
1200 if (FAILED(adep.rc())) return adep.rc();
1201
1202 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1203
1204 /* don't do anything if we're already host interface attached */
1205 if (mData->mAttachmentType != NetworkAttachmentType_VDE)
1206 {
1207 mData.backup();
1208
1209 /* first detach the current attachment */
1210 // Commented this for now as it reset the parameter mData->mHostInterface
1211 // which is essential while changing the Attachment dynamically.
1212 //detach();
1213
1214 mData->mAttachmentType = NetworkAttachmentType_VDE;
1215
1216 /* leave the lock before informing callbacks */
1217 alock.release();
1218
1219 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
1220 if (FAILED (rc))
1221 {
1222 /* If changing the attachment failed then we can't assume
1223 * that the previous attachment will attach correctly
1224 * and thus return error along with detaching all
1225 * attachments.
1226 */
1227 Detach();
1228 return rc;
1229 }
1230 }
1231
1232 return S_OK;
1233#else /* !VBOX_WITH_VDE */
1234 return E_NOTIMPL;
1235#endif
1236}
1237
1238STDMETHODIMP NetworkAdapter::Detach()
1239{
1240 AutoCaller autoCaller(this);
1241 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1242
1243 /* the machine needs to be mutable */
1244 AutoMutableStateDependency adep(mParent);
1245 if (FAILED(adep.rc())) return adep.rc();
1246
1247 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1248
1249 if (mData->mAttachmentType != NetworkAttachmentType_Null)
1250 {
1251 mData.backup();
1252
1253 detach();
1254
1255 m_fModified = true;
1256 // leave the lock before informing callbacks
1257 alock.release();
1258
1259 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, no need to lock
1260 mParent->setModified(Machine::IsModified_NetworkAdapters);
1261 mlock.release();
1262
1263 /* adapt the CFGM logic and notify the guest => changeAdapter=TRUE. */
1264 mParent->onNetworkAdapterChange(this, TRUE);
1265 }
1266
1267 return S_OK;
1268}
1269
1270// public methods only for internal purposes
1271////////////////////////////////////////////////////////////////////////////////
1272
1273/**
1274 * Loads settings from the given adapter node.
1275 * May be called once right after this object creation.
1276 *
1277 * @param aAdapterNode <Adapter> node.
1278 *
1279 * @note Locks this object for writing.
1280 */
1281HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
1282{
1283 AutoCaller autoCaller(this);
1284 AssertComRCReturnRC(autoCaller.rc());
1285
1286 /* Note: we assume that the default values for attributes of optional
1287 * nodes are assigned in the Data::Data() constructor and don't do it
1288 * here. It implies that this method may only be called after constructing
1289 * a new BIOSSettings object while all its data fields are in the default
1290 * values. Exceptions are fields whose creation time defaults don't match
1291 * values that should be applied when these fields are not explicitly set
1292 * in the settings file (for backwards compatibility reasons). This takes
1293 * place when a setting of a newly created object must default to A while
1294 * the same setting of an object loaded from the old settings file must
1295 * default to B. */
1296
1297 HRESULT rc = S_OK;
1298
1299 mData->mAdapterType = data.type;
1300 mData->mEnabled = data.fEnabled;
1301 /* MAC address (can be null) */
1302 rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress).raw());
1303 if (FAILED(rc)) return rc;
1304 /* cable (required) */
1305 mData->mCableConnected = data.fCableConnected;
1306 /* line speed (defaults to 100 Mbps) */
1307 mData->mLineSpeed = data.ulLineSpeed;
1308 mData->mPromiscModePolicy = data.enmPromiscModePolicy;
1309 /* tracing (defaults to false) */
1310 mData->mTraceEnabled = data.fTraceEnabled;
1311 mData->mTraceFile = data.strTraceFile;
1312 /* boot priority (defaults to 0, i.e. lowest) */
1313 mData->mBootPriority = data.ulBootPriority;
1314 /* Bandwidth limit in Mbps. */
1315 mData->mBandwidthLimit = data.ulBandwidthLimit;
1316
1317 switch (data.mode)
1318 {
1319 case NetworkAttachmentType_NAT:
1320 mNATEngine->loadSettings(data.nat);
1321 rc = AttachToNAT();
1322 if (FAILED(rc)) return rc;
1323 break;
1324
1325 case NetworkAttachmentType_Bridged:
1326 rc = COMSETTER(HostInterface)(Bstr(data.strName).raw());
1327 if (FAILED(rc)) return rc;
1328 rc = AttachToBridgedInterface();
1329 if (FAILED(rc)) return rc;
1330 break;
1331
1332 case NetworkAttachmentType_Internal:
1333 mData->mInternalNetwork = data.strName;
1334 Assert(!mData->mInternalNetwork.isEmpty());
1335
1336 rc = AttachToInternalNetwork();
1337 if (FAILED(rc)) return rc;
1338 break;
1339
1340 case NetworkAttachmentType_HostOnly:
1341#if defined(VBOX_WITH_NETFLT)
1342 rc = COMSETTER(HostInterface)(Bstr(data.strName).raw());
1343 if (FAILED(rc)) return rc;
1344#endif
1345 rc = AttachToHostOnlyInterface();
1346 if (FAILED(rc)) return rc;
1347 break;
1348
1349#if defined(VBOX_WITH_VDE)
1350 case NetworkAttachmentType_VDE:
1351 mData->mVDENetwork = data.strName;
1352 rc = AttachToVDE();
1353 if (FAILED(rc)) return rc;
1354 break;
1355#endif
1356
1357 case NetworkAttachmentType_Null:
1358 rc = Detach();
1359 if (FAILED(rc)) return rc;
1360 break;
1361 }
1362 if (data.fHasDisabledNAT)
1363 mNATEngine->loadSettings(data.nat);
1364
1365 // after loading settings, we are no longer different from the XML on disk
1366 m_fModified = false;
1367
1368 return S_OK;
1369}
1370
1371/**
1372 * Saves settings to the given adapter node.
1373 *
1374 * Note that the given Adapter node is completely empty on input.
1375 *
1376 * @param aAdapterNode <Adapter> node.
1377 *
1378 * @note Locks this object for reading.
1379 */
1380HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
1381{
1382 AutoCaller autoCaller(this);
1383 AssertComRCReturnRC(autoCaller.rc());
1384
1385 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1386
1387 data.fEnabled = !!mData->mEnabled;
1388 data.strMACAddress = mData->mMACAddress;
1389 data.fCableConnected = !!mData->mCableConnected;
1390
1391 data.enmPromiscModePolicy = mData->mPromiscModePolicy;
1392 data.ulLineSpeed = mData->mLineSpeed;
1393
1394 data.fTraceEnabled = !!mData->mTraceEnabled;
1395
1396 data.strTraceFile = mData->mTraceFile;
1397
1398 data.ulBootPriority = mData->mBootPriority;
1399
1400 data.ulBandwidthLimit = mData->mBandwidthLimit;
1401
1402 data.type = mData->mAdapterType;
1403
1404 switch (data.mode = mData->mAttachmentType)
1405 {
1406 case NetworkAttachmentType_Null:
1407 data.strName.setNull();
1408 break;
1409
1410 case NetworkAttachmentType_NAT:
1411 data.fHasDisabledNAT = 0;
1412 mNATEngine->commit();
1413 mNATEngine->saveSettings(data.nat);
1414 break;
1415
1416 case NetworkAttachmentType_Bridged:
1417 data.strName = mData->mHostInterface;
1418 break;
1419
1420 case NetworkAttachmentType_Internal:
1421 data.strName = mData->mInternalNetwork;
1422 break;
1423
1424 case NetworkAttachmentType_HostOnly:
1425 data.strName = mData->mHostInterface;
1426 break;
1427
1428#if defined(VBOX_WITH_VDE)
1429 case NetworkAttachmentType_VDE:
1430 data.strName = mData->mVDENetwork;
1431 break;
1432#endif
1433 }
1434
1435 if (data.mode != NetworkAttachmentType_NAT)
1436 {
1437 data.fHasDisabledNAT = 1; /* ??? */
1438 mNATEngine->commit();
1439 mNATEngine->saveSettings(data.nat);
1440 }
1441
1442 // after saving settings, we are no longer different from the XML on disk
1443 m_fModified = false;
1444
1445 return S_OK;
1446}
1447
1448/**
1449 * Returns true if any setter method has modified settings of this instance.
1450 * @return
1451 */
1452bool NetworkAdapter::isModified() {
1453 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1454 bool fChanged = m_fModified;
1455 fChanged |= (mData->mAdapterType == NetworkAttachmentType_NAT? mNATEngine->isModified() : false);
1456 return fChanged;
1457}
1458
1459/**
1460 * @note Locks this object for writing.
1461 */
1462void NetworkAdapter::rollback()
1463{
1464 /* sanity */
1465 AutoCaller autoCaller(this);
1466 AssertComRCReturnVoid(autoCaller.rc());
1467
1468 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1469
1470 mData.rollback();
1471}
1472
1473/**
1474 * @note Locks this object for writing, together with the peer object (also
1475 * for writing) if there is one.
1476 */
1477void NetworkAdapter::commit()
1478{
1479 /* sanity */
1480 AutoCaller autoCaller(this);
1481 AssertComRCReturnVoid (autoCaller.rc());
1482
1483 /* sanity too */
1484 AutoCaller peerCaller (mPeer);
1485 AssertComRCReturnVoid (peerCaller.rc());
1486
1487 /* lock both for writing since we modify both (mPeer is "master" so locked
1488 * first) */
1489 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
1490
1491 if (mData.isBackedUp())
1492 {
1493 mData.commit();
1494 if (mPeer)
1495 {
1496 /* attach new data to the peer and reshare it */
1497 mPeer->mData.attach (mData);
1498 }
1499 }
1500}
1501
1502/**
1503 * @note Locks this object for writing, together with the peer object
1504 * represented by @a aThat (locked for reading).
1505 */
1506void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1507{
1508 AssertReturnVoid (aThat != NULL);
1509
1510 /* sanity */
1511 AutoCaller autoCaller(this);
1512 AssertComRCReturnVoid (autoCaller.rc());
1513
1514 /* sanity too */
1515 AutoCaller thatCaller (aThat);
1516 AssertComRCReturnVoid (thatCaller.rc());
1517
1518 /* peer is not modified, lock it for reading (aThat is "master" so locked
1519 * first) */
1520 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1521 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1522
1523 /* this will back up current data */
1524 mData.assignCopy (aThat->mData);
1525}
1526
1527void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
1528{
1529 AssertReturnVoid (aOsType != NULL);
1530
1531 /* sanity */
1532 AutoCaller autoCaller(this);
1533 AssertComRCReturnVoid (autoCaller.rc());
1534
1535 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1536
1537 bool e1000enabled = false;
1538#ifdef VBOX_WITH_E1000
1539 e1000enabled = true;
1540#endif // VBOX_WITH_E1000
1541
1542 NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1543
1544 /* Set default network adapter for this OS type */
1545 if (defaultType == NetworkAdapterType_I82540EM ||
1546 defaultType == NetworkAdapterType_I82543GC ||
1547 defaultType == NetworkAdapterType_I82545EM)
1548 {
1549 if (e1000enabled) mData->mAdapterType = defaultType;
1550 }
1551 else mData->mAdapterType = defaultType;
1552
1553 /* Enable and connect the first one adapter to the NAT */
1554 if (mData->mSlot == 0)
1555 {
1556 mData->mEnabled = true;
1557 mData->mAttachmentType = NetworkAttachmentType_NAT;
1558 mData->mCableConnected = true;
1559 }
1560}
1561
1562// private methods
1563////////////////////////////////////////////////////////////////////////////////
1564
1565/**
1566 * Worker routine for detach handling. No locking, no notifications.
1567
1568 * @note Must be called from under the object's write lock.
1569 */
1570void NetworkAdapter::detach()
1571{
1572 AssertReturnVoid (isWriteLockOnCurrentThread());
1573
1574 switch (mData->mAttachmentType)
1575 {
1576 case NetworkAttachmentType_Null:
1577 {
1578 /* nothing to do here */
1579 break;
1580 }
1581 case NetworkAttachmentType_NAT:
1582 {
1583 break;
1584 }
1585 case NetworkAttachmentType_Bridged:
1586 {
1587 /* reset handle and device name */
1588 mData->mHostInterface = "";
1589 break;
1590 }
1591 case NetworkAttachmentType_Internal:
1592 {
1593 mData->mInternalNetwork.setNull();
1594 break;
1595 }
1596 case NetworkAttachmentType_HostOnly:
1597 {
1598#if defined(VBOX_WITH_NETFLT)
1599 /* reset handle and device name */
1600 mData->mHostInterface = "";
1601#endif
1602 break;
1603 }
1604 }
1605
1606 mData->mAttachmentType = NetworkAttachmentType_Null;
1607}
1608
1609/**
1610 * Generates a new unique MAC address based on our vendor ID and
1611 * parts of a GUID.
1612 *
1613 * @note Must be called from under the object's write lock or within the init
1614 * span.
1615 */
1616void NetworkAdapter::generateMACAddress()
1617{
1618 /*
1619 * Our strategy is as follows: the first three bytes are our fixed
1620 * vendor ID (080027). The remaining 3 bytes will be taken from the
1621 * start of a GUID. This is a fairly safe algorithm.
1622 */
1623 char strMAC[13];
1624 Guid guid;
1625 guid.create();
1626 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1627 guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]);
1628 LogFlowThisFunc(("generated MAC: '%s'\n", strMAC));
1629 mData->mMACAddress = strMAC;
1630}
1631/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette