VirtualBox

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

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

ConsoleImpl2: Added support for attaching/detaching NetSniffer at Runtime

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.3 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 23222 2009-09-22 15:48:26Z vboxsync $ */
2/** @file
3 * Implementation of INetworkAdaptor in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "NetworkAdapterImpl.h"
23#include "Logging.h"
24#include "MachineImpl.h"
25#include "GuestOSTypeImpl.h"
26
27#include <iprt/string.h>
28#include <iprt/cpputils.h>
29
30#include <VBox/err.h>
31#include <VBox/settings.h>
32
33// constructor / destructor
34////////////////////////////////////////////////////////////////////////////////
35
36DEFINE_EMPTY_CTOR_DTOR (NetworkAdapter)
37
38HRESULT NetworkAdapter::FinalConstruct()
39{
40 return S_OK;
41}
42
43void NetworkAdapter::FinalRelease()
44{
45 uninit ();
46}
47
48// public initializer/uninitializer for internal purposes only
49////////////////////////////////////////////////////////////////////////////////
50
51/**
52 * Initializes the network adapter object.
53 *
54 * @param aParent Handle of the parent object.
55 */
56HRESULT NetworkAdapter::init (Machine *aParent, ULONG aSlot)
57{
58 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
59
60 ComAssertRet (aParent, E_INVALIDARG);
61 ComAssertRet (aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
62
63 /* Enclose the state transition NotReady->InInit->Ready */
64 AutoInitSpan autoInitSpan(this);
65 AssertReturn(autoInitSpan.isOk(), E_FAIL);
66
67 unconst(mParent) = aParent;
68 /* mPeer is left null */
69
70 mData.allocate();
71
72 /* initialize data */
73 mData->mSlot = aSlot;
74
75 /* default to Am79C973 */
76 mData->mAdapterType = NetworkAdapterType_Am79C973;
77
78 /* generate the MAC address early to guarantee it is the same both after
79 * changing some other property (i.e. after mData.backup()) and after the
80 * subsequent mData.rollback(). */
81 generateMACAddress();
82
83 /* Confirm a successful initialization */
84 autoInitSpan.setSucceeded();
85
86 return S_OK;
87}
88
89/**
90 * Initializes the network adapter object given another network adapter object
91 * (a kind of copy constructor). This object shares data with
92 * the object passed as an argument.
93 *
94 * @note This object must be destroyed before the original object
95 * it shares data with is destroyed.
96 *
97 * @note Locks @a aThat object for reading.
98 */
99HRESULT NetworkAdapter::init (Machine *aParent, NetworkAdapter *aThat)
100{
101 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
102
103 ComAssertRet (aParent && aThat, E_INVALIDARG);
104
105 /* Enclose the state transition NotReady->InInit->Ready */
106 AutoInitSpan autoInitSpan(this);
107 AssertReturn(autoInitSpan.isOk(), E_FAIL);
108
109 unconst(mParent) = aParent;
110 unconst(mPeer) = aThat;
111
112 AutoCaller thatCaller (aThat);
113 AssertComRCReturnRC(thatCaller.rc());
114
115 AutoReadLock thatLock (aThat);
116 mData.share (aThat->mData);
117
118 /* Confirm a successful initialization */
119 autoInitSpan.setSucceeded();
120
121 return S_OK;
122}
123
124/**
125 * Initializes the guest object given another guest object
126 * (a kind of copy constructor). This object makes a private copy of data
127 * of the original object passed as an argument.
128 *
129 * @note Locks @a aThat object for reading.
130 */
131HRESULT NetworkAdapter::initCopy (Machine *aParent, NetworkAdapter *aThat)
132{
133 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
134
135 ComAssertRet (aParent && aThat, E_INVALIDARG);
136
137 /* Enclose the state transition NotReady->InInit->Ready */
138 AutoInitSpan autoInitSpan(this);
139 AssertReturn(autoInitSpan.isOk(), E_FAIL);
140
141 unconst(mParent) = aParent;
142 /* mPeer is left null */
143
144 AutoCaller thatCaller (aThat);
145 AssertComRCReturnRC(thatCaller.rc());
146
147 AutoReadLock thatLock (aThat);
148 mData.attachCopy (aThat->mData);
149
150 /* Confirm a successful initialization */
151 autoInitSpan.setSucceeded();
152
153 return S_OK;
154}
155
156/**
157 * Uninitializes the instance and sets the ready flag to FALSE.
158 * Called either from FinalRelease() or by the parent when it gets destroyed.
159 */
160void NetworkAdapter::uninit()
161{
162 LogFlowThisFunc(("\n"));
163
164 /* Enclose the state transition Ready->InUninit->NotReady */
165 AutoUninitSpan autoUninitSpan(this);
166 if (autoUninitSpan.uninitDone())
167 return;
168
169 mData.free();
170
171 unconst(mPeer).setNull();
172 unconst(mParent).setNull();
173}
174
175// INetworkAdapter properties
176////////////////////////////////////////////////////////////////////////////////
177
178STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
179{
180 CheckComArgOutPointerValid(aAdapterType);
181
182 AutoCaller autoCaller(this);
183 CheckComRCReturnRC(autoCaller.rc());
184
185 AutoReadLock alock(this);
186
187 *aAdapterType = mData->mAdapterType;
188
189 return S_OK;
190}
191
192STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
193{
194 AutoCaller autoCaller(this);
195 CheckComRCReturnRC(autoCaller.rc());
196
197 /* the machine needs to be mutable */
198 Machine::AutoMutableStateDependency adep (mParent);
199 CheckComRCReturnRC(adep.rc());
200
201 AutoWriteLock alock(this);
202
203 /* make sure the value is allowed */
204 switch (aAdapterType)
205 {
206 case NetworkAdapterType_Am79C970A:
207 case NetworkAdapterType_Am79C973:
208#ifdef VBOX_WITH_E1000
209 case NetworkAdapterType_I82540EM:
210 case NetworkAdapterType_I82543GC:
211 case NetworkAdapterType_I82545EM:
212#endif
213#ifdef VBOX_WITH_VIRTIO
214 case NetworkAdapterType_Virtio:
215#endif /* VBOX_WITH_VIRTIO */
216 break;
217 default:
218 return setError (E_FAIL,
219 tr("Invalid network adapter type '%d'"),
220 aAdapterType);
221 }
222
223 if (mData->mAdapterType != aAdapterType)
224 {
225 mData.backup();
226 mData->mAdapterType = aAdapterType;
227
228 /* leave the lock before informing callbacks */
229 alock.unlock();
230
231 mParent->onNetworkAdapterChange (this, FALSE);
232 }
233
234 return S_OK;
235}
236
237STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
238{
239 CheckComArgOutPointerValid(aSlot);
240
241 AutoCaller autoCaller(this);
242 CheckComRCReturnRC(autoCaller.rc());
243
244 AutoReadLock alock(this);
245
246 *aSlot = mData->mSlot;
247
248 return S_OK;
249}
250
251STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
252{
253 CheckComArgOutPointerValid(aEnabled);
254
255 AutoCaller autoCaller(this);
256 CheckComRCReturnRC(autoCaller.rc());
257
258 AutoReadLock alock(this);
259
260 *aEnabled = mData->mEnabled;
261
262 return S_OK;
263}
264
265STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
266{
267 AutoCaller autoCaller(this);
268 CheckComRCReturnRC(autoCaller.rc());
269
270 /* the machine needs to be mutable */
271 Machine::AutoMutableStateDependency adep (mParent);
272 CheckComRCReturnRC(adep.rc());
273
274 AutoWriteLock alock(this);
275
276 if (mData->mEnabled != aEnabled)
277 {
278 mData.backup();
279 mData->mEnabled = aEnabled;
280
281 /* leave the lock before informing callbacks */
282 alock.unlock();
283
284 mParent->onNetworkAdapterChange (this, FALSE);
285 }
286
287 return S_OK;
288}
289
290STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress)
291{
292 CheckComArgOutPointerValid(aMACAddress);
293
294 AutoCaller autoCaller(this);
295 CheckComRCReturnRC(autoCaller.rc());
296
297 AutoReadLock alock(this);
298
299 ComAssertRet (!!mData->mMACAddress, E_FAIL);
300
301 mData->mMACAddress.cloneTo(aMACAddress);
302
303 return S_OK;
304}
305
306STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress)
307{
308 AutoCaller autoCaller(this);
309 CheckComRCReturnRC(autoCaller.rc());
310
311 /* the machine needs to be mutable */
312 Machine::AutoMutableStateDependency adep (mParent);
313 CheckComRCReturnRC(adep.rc());
314
315 AutoWriteLock alock(this);
316
317 HRESULT rc = S_OK;
318 bool emitChangeEvent = false;
319
320 /*
321 * Are we supposed to generate a MAC?
322 */
323 if (!aMACAddress || !*aMACAddress)
324 {
325 mData.backup();
326
327 generateMACAddress();
328 emitChangeEvent = true;
329 }
330 else
331 {
332 if (mData->mMACAddress != aMACAddress)
333 {
334 /*
335 * Verify given MAC address
336 */
337 Utf8Str macAddressUtf = aMACAddress;
338 char *macAddressStr = macAddressUtf.mutableRaw();
339 int i = 0;
340 while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK))
341 {
342 char c = *macAddressStr;
343 /* canonicalize hex digits to capital letters */
344 if (c >= 'a' && c <= 'f')
345 {
346 /** @todo the runtime lacks an ascii lower/upper conv */
347 c &= 0xdf;
348 *macAddressStr = c;
349 }
350 /* we only accept capital letters */
351 if (((c < '0') || (c > '9')) &&
352 ((c < 'A') || (c > 'F')))
353 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
354 /* the second digit must have even value for unicast addresses */
355 if ((i == 1) && (!!(c & 1) == (c >= '0' && c <= '9')))
356 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
357
358 macAddressStr++;
359 i++;
360 }
361 /* we must have parsed exactly 12 characters */
362 if (i != 12)
363 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
364
365 if (SUCCEEDED(rc))
366 {
367 mData.backup();
368
369 mData->mMACAddress = macAddressUtf;
370 emitChangeEvent = true;
371 }
372 }
373 }
374
375 if (emitChangeEvent)
376 {
377 /* leave the lock before informing callbacks */
378 alock.unlock();
379
380 mParent->onNetworkAdapterChange (this, FALSE);
381 }
382
383 return rc;
384}
385
386STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
387 NetworkAttachmentType_T *aAttachmentType)
388{
389 CheckComArgOutPointerValid(aAttachmentType);
390
391 AutoCaller autoCaller(this);
392 CheckComRCReturnRC(autoCaller.rc());
393
394 AutoReadLock alock(this);
395
396 *aAttachmentType = mData->mAttachmentType;
397
398 return S_OK;
399}
400
401STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
402{
403 CheckComArgOutPointerValid(aHostInterface);
404
405 AutoCaller autoCaller(this);
406 CheckComRCReturnRC(autoCaller.rc());
407
408 AutoReadLock alock(this);
409
410 mData->mHostInterface.cloneTo(aHostInterface);
411
412 return S_OK;
413}
414
415STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface)
416{
417 Bstr bstrEmpty("");
418 if (!aHostInterface)
419 aHostInterface = bstrEmpty;
420
421 AutoCaller autoCaller(this);
422 CheckComRCReturnRC(autoCaller.rc());
423
424 /* the machine needs to be mutable */
425 Machine::AutoMutableStateDependency adep (mParent);
426 CheckComRCReturnRC(adep.rc());
427
428 AutoWriteLock alock(this);
429
430 if (mData->mHostInterface != aHostInterface)
431 {
432 mData.backup();
433 mData->mHostInterface = aHostInterface;
434
435 /* leave the lock before informing callbacks */
436 alock.unlock();
437
438 mParent->onNetworkAdapterChange (this, FALSE);
439 }
440
441 return S_OK;
442}
443
444STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
445{
446 CheckComArgOutPointerValid(aInternalNetwork);
447
448 AutoCaller autoCaller(this);
449 CheckComRCReturnRC(autoCaller.rc());
450
451 AutoReadLock alock(this);
452
453 mData->mInternalNetwork.cloneTo(aInternalNetwork);
454
455 return S_OK;
456}
457
458STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwork)
459{
460 AutoCaller autoCaller(this);
461 CheckComRCReturnRC(autoCaller.rc());
462
463 /* the machine needs to be mutable */
464 Machine::AutoMutableStateDependency adep (mParent);
465 CheckComRCReturnRC(adep.rc());
466
467 AutoWriteLock alock(this);
468
469 if (mData->mInternalNetwork != aInternalNetwork)
470 {
471 /* if an empty/null string is to be set, internal networking must be
472 * turned off */
473 if ( (aInternalNetwork == NULL || *aInternalNetwork == '\0')
474 && mData->mAttachmentType == NetworkAttachmentType_Internal)
475 {
476 return setError (E_FAIL,
477 tr ("Empty or null internal network name is not valid"));
478 }
479
480 mData.backup();
481 mData->mInternalNetwork = aInternalNetwork;
482
483 /* leave the lock before informing callbacks */
484 alock.unlock();
485
486 mParent->onNetworkAdapterChange (this, FALSE);
487 }
488
489 return S_OK;
490}
491
492STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
493{
494 CheckComArgOutPointerValid(aNATNetwork);
495
496 AutoCaller autoCaller(this);
497 CheckComRCReturnRC(autoCaller.rc());
498
499 AutoReadLock alock(this);
500
501 mData->mNATNetwork.cloneTo(aNATNetwork);
502
503 return S_OK;
504}
505
506STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork)
507{
508 AutoCaller autoCaller(this);
509 CheckComRCReturnRC(autoCaller.rc());
510
511 /* the machine needs to be mutable */
512 Machine::AutoMutableStateDependency adep (mParent);
513 CheckComRCReturnRC(adep.rc());
514
515 AutoWriteLock alock(this);
516
517 if (mData->mNATNetwork != aNATNetwork)
518 {
519 mData.backup();
520 mData->mNATNetwork = aNATNetwork;
521
522 /* leave the lock before informing callbacks */
523 alock.unlock();
524
525 mParent->onNetworkAdapterChange (this, FALSE);
526 }
527
528 return S_OK;
529}
530
531STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
532{
533 CheckComArgOutPointerValid(aConnected);
534
535 AutoCaller autoCaller(this);
536 CheckComRCReturnRC(autoCaller.rc());
537
538 AutoReadLock alock(this);
539
540 *aConnected = mData->mCableConnected;
541
542 return S_OK;
543}
544
545STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
546{
547 AutoCaller autoCaller(this);
548 CheckComRCReturnRC(autoCaller.rc());
549
550 /* the machine needs to be mutable */
551 Machine::AutoMutableStateDependency adep (mParent);
552 CheckComRCReturnRC(adep.rc());
553
554 AutoWriteLock alock(this);
555
556 if (aConnected != mData->mCableConnected)
557 {
558 mData.backup();
559 mData->mCableConnected = aConnected;
560
561 /* leave the lock before informing callbacks */
562 alock.unlock();
563
564 mParent->onNetworkAdapterChange (this, FALSE);
565 }
566
567 return S_OK;
568}
569
570STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
571{
572 CheckComArgOutPointerValid(aSpeed);
573
574 AutoCaller autoCaller(this);
575 CheckComRCReturnRC(autoCaller.rc());
576
577 AutoReadLock alock(this);
578
579 *aSpeed = mData->mLineSpeed;
580
581 return S_OK;
582}
583
584STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
585{
586 AutoCaller autoCaller(this);
587 CheckComRCReturnRC(autoCaller.rc());
588
589 /* the machine needs to be mutable */
590 Machine::AutoMutableStateDependency adep (mParent);
591 CheckComRCReturnRC(adep.rc());
592
593 AutoWriteLock alock(this);
594
595 if (aSpeed != mData->mLineSpeed)
596 {
597 mData.backup();
598 mData->mLineSpeed = aSpeed;
599
600 /* leave the lock before informing callbacks */
601 alock.unlock();
602
603 mParent->onNetworkAdapterChange (this, FALSE);
604 }
605
606 return S_OK;
607}
608
609STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
610{
611 CheckComArgOutPointerValid(aEnabled);
612
613 AutoCaller autoCaller(this);
614 CheckComRCReturnRC(autoCaller.rc());
615
616 AutoReadLock alock(this);
617
618 *aEnabled = mData->mTraceEnabled;
619 return S_OK;
620}
621
622STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
623{
624 AutoCaller autoCaller(this);
625 CheckComRCReturnRC(autoCaller.rc());
626
627 /* the machine needs to be mutable */
628 Machine::AutoMutableStateDependency adep (mParent);
629 CheckComRCReturnRC(adep.rc());
630
631 AutoWriteLock alock(this);
632
633 if (aEnabled != mData->mTraceEnabled)
634 {
635 mData.backup();
636 mData->mTraceEnabled = aEnabled;
637
638 /* leave the lock before informing callbacks */
639 alock.unlock();
640
641 mParent->onNetworkAdapterChange (this, TRUE);
642 }
643
644 return S_OK;
645}
646
647STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
648{
649 CheckComArgOutPointerValid(aTraceFile);
650
651 AutoCaller autoCaller(this);
652 CheckComRCReturnRC(autoCaller.rc());
653
654 AutoReadLock alock(this);
655
656 mData->mTraceFile.cloneTo(aTraceFile);
657
658 return S_OK;
659}
660
661STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
662{
663 AutoCaller autoCaller(this);
664 CheckComRCReturnRC(autoCaller.rc());
665
666 /* the machine needs to be mutable */
667 Machine::AutoMutableStateDependency adep (mParent);
668 CheckComRCReturnRC(adep.rc());
669
670 AutoWriteLock alock(this);
671
672 if (mData->mTraceFile != aTraceFile)
673 {
674 mData.backup();
675 mData->mTraceFile = aTraceFile;
676
677 /* leave the lock before informing callbacks */
678 alock.unlock();
679
680 mParent->onNetworkAdapterChange (this, FALSE);
681 }
682
683 return S_OK;
684}
685
686// INetworkAdapter methods
687////////////////////////////////////////////////////////////////////////////////
688
689STDMETHODIMP NetworkAdapter::AttachToNAT()
690{
691 AutoCaller autoCaller(this);
692 CheckComRCReturnRC(autoCaller.rc());
693
694 /* the machine needs to be mutable */
695 Machine::AutoMutableStateDependency adep (mParent);
696 CheckComRCReturnRC(adep.rc());
697
698 AutoWriteLock alock(this);
699
700 if (mData->mAttachmentType != NetworkAttachmentType_NAT)
701 {
702 mData.backup();
703
704 // Commented this for now as it resets the parameter mData->mNATNetwork
705 // which is essential while changing the Attachment dynamically.
706 //detach();
707
708 mData->mAttachmentType = NetworkAttachmentType_NAT;
709
710 /* leave the lock before informing callbacks */
711 alock.unlock();
712
713 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
714 if (FAILED (rc))
715 {
716 /* If changing the attachment failed then we can't assume
717 * that the previous attachment will attach correctly
718 * and thus return error along with dettaching all
719 * attachments.
720 */
721 Detach();
722 return rc;
723 }
724 }
725
726 return S_OK;
727}
728
729STDMETHODIMP NetworkAdapter::AttachToBridgedInterface()
730{
731 AutoCaller autoCaller(this);
732 CheckComRCReturnRC(autoCaller.rc());
733
734 /* the machine needs to be mutable */
735 Machine::AutoMutableStateDependency adep (mParent);
736 CheckComRCReturnRC(adep.rc());
737
738 AutoWriteLock alock(this);
739
740 /* don't do anything if we're already host interface attached */
741 if (mData->mAttachmentType != NetworkAttachmentType_Bridged)
742 {
743 mData.backup();
744
745 /* first detach the current attachment */
746 // Commented this for now as it reset the parameter mData->mHostInterface
747 // which is essential while changing the Attachment dynamically.
748 //detach();
749
750 mData->mAttachmentType = NetworkAttachmentType_Bridged;
751
752 /* leave the lock before informing callbacks */
753 alock.unlock();
754
755 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
756 if (FAILED (rc))
757 {
758 /* If changing the attachment failed then we can't assume
759 * that the previous attachment will attach correctly
760 * and thus return error along with dettaching all
761 * attachments.
762 */
763 Detach();
764 return rc;
765 }
766 }
767
768 return S_OK;
769}
770
771STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
772{
773 AutoCaller autoCaller(this);
774 CheckComRCReturnRC(autoCaller.rc());
775
776 /* the machine needs to be mutable */
777 Machine::AutoMutableStateDependency adep (mParent);
778 CheckComRCReturnRC(adep.rc());
779
780 AutoWriteLock alock(this);
781
782 /* don't do anything if we're already internal network attached */
783 if (mData->mAttachmentType != NetworkAttachmentType_Internal)
784 {
785 mData.backup();
786
787 /* first detach the current attachment */
788 // Commented this for now as it reset the parameter mData->mInternalNetwork
789 // which is essential while changing the Attachment dynamically.
790 //detach();
791
792 /* there must an internal network name */
793 if (mData->mInternalNetwork.isEmpty())
794 {
795 LogRel (("Internal network name not defined, "
796 "setting to default \"intnet\"\n"));
797 mData->mInternalNetwork = "intnet";
798 }
799
800 mData->mAttachmentType = NetworkAttachmentType_Internal;
801
802 /* leave the lock before informing callbacks */
803 alock.unlock();
804
805 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
806 if (FAILED (rc))
807 {
808 /* If changing the attachment failed then we can't assume
809 * that the previous attachment will attach correctly
810 * and thus return error along with dettaching all
811 * attachments.
812 */
813 Detach();
814 return rc;
815 }
816 }
817
818 return S_OK;
819}
820
821STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface()
822{
823 AutoCaller autoCaller(this);
824 CheckComRCReturnRC(autoCaller.rc());
825
826 /* the machine needs to be mutable */
827 Machine::AutoMutableStateDependency adep (mParent);
828 CheckComRCReturnRC(adep.rc());
829
830 AutoWriteLock alock(this);
831
832 /* don't do anything if we're already host interface attached */
833 if (mData->mAttachmentType != NetworkAttachmentType_HostOnly)
834 {
835 mData.backup();
836
837 /* first detach the current attachment */
838 // Commented this for now as it reset the parameter mData->mHostInterface
839 // which is essential while changing the Attachment dynamically.
840 //detach();
841
842 mData->mAttachmentType = NetworkAttachmentType_HostOnly;
843
844 /* leave the lock before informing callbacks */
845 alock.unlock();
846
847 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
848 if (FAILED (rc))
849 {
850 /* If changing the attachment failed then we can't assume
851 * that the previous attachment will attach correctly
852 * and thus return error along with dettaching all
853 * attachments.
854 */
855 Detach();
856 return rc;
857 }
858 }
859
860 return S_OK;
861}
862
863STDMETHODIMP NetworkAdapter::Detach()
864{
865 AutoCaller autoCaller(this);
866 CheckComRCReturnRC(autoCaller.rc());
867
868 /* the machine needs to be mutable */
869 Machine::AutoMutableStateDependency adep (mParent);
870 CheckComRCReturnRC(adep.rc());
871
872 AutoWriteLock alock(this);
873
874 if (mData->mAttachmentType != NetworkAttachmentType_Null)
875 {
876 mData.backup();
877
878 detach();
879
880 /* leave the lock before informing callbacks */
881 alock.unlock();
882
883 mParent->onNetworkAdapterChange (this, TRUE);
884 }
885
886 return S_OK;
887}
888
889// public methods only for internal purposes
890////////////////////////////////////////////////////////////////////////////////
891
892/**
893 * Loads settings from the given adapter node.
894 * May be called once right after this object creation.
895 *
896 * @param aAdapterNode <Adapter> node.
897 *
898 * @note Locks this object for writing.
899 */
900HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
901{
902 AutoCaller autoCaller(this);
903 AssertComRCReturnRC(autoCaller.rc());
904
905 AutoWriteLock alock(this);
906
907 /* Note: we assume that the default values for attributes of optional
908 * nodes are assigned in the Data::Data() constructor and don't do it
909 * here. It implies that this method may only be called after constructing
910 * a new BIOSSettings object while all its data fields are in the default
911 * values. Exceptions are fields whose creation time defaults don't match
912 * values that should be applied when these fields are not explicitly set
913 * in the settings file (for backwards compatibility reasons). This takes
914 * place when a setting of a newly created object must default to A while
915 * the same setting of an object loaded from the old settings file must
916 * default to B. */
917
918 HRESULT rc = S_OK;
919
920 mData->mAdapterType = data.type;
921 mData->mEnabled = data.fEnabled;
922 /* MAC address (can be null) */
923 rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress));
924 CheckComRCReturnRC(rc);
925 /* cable (required) */
926 mData->mCableConnected = data.fCableConnected;
927 /* line speed (defaults to 100 Mbps) */
928 mData->mLineSpeed = data.ulLineSpeed;
929 /* tracing (defaults to false) */
930 mData->mTraceEnabled = data.fTraceEnabled;
931 mData->mTraceFile = data.strTraceFile;
932
933 switch (data.mode)
934 {
935 case NetworkAttachmentType_NAT:
936 mData->mNATNetwork = data.strName;
937 rc = AttachToNAT();
938 CheckComRCReturnRC(rc);
939 break;
940
941 case NetworkAttachmentType_Bridged:
942 rc = COMSETTER(HostInterface)(Bstr(data.strName));
943 CheckComRCReturnRC(rc);
944 rc = AttachToBridgedInterface();
945 CheckComRCReturnRC(rc);
946 break;
947
948 case NetworkAttachmentType_Internal:
949 mData->mInternalNetwork = data.strName;
950 Assert(!mData->mInternalNetwork.isNull());
951
952 rc = AttachToInternalNetwork();
953 CheckComRCReturnRC(rc);
954 break;
955
956 case NetworkAttachmentType_HostOnly:
957#if defined(VBOX_WITH_NETFLT)
958 rc = COMSETTER(HostInterface)(Bstr(data.strName));
959 CheckComRCReturnRC(rc);
960#endif
961 rc = AttachToHostOnlyInterface();
962 CheckComRCReturnRC(rc);
963 break;
964
965 case NetworkAttachmentType_Null:
966 rc = Detach();
967 CheckComRCReturnRC(rc);
968 break;
969 }
970
971 return S_OK;
972}
973
974/**
975 * Saves settings to the given adapter node.
976 *
977 * Note that the given Adapter node is comletely empty on input.
978 *
979 * @param aAdapterNode <Adapter> node.
980 *
981 * @note Locks this object for reading.
982 */
983HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
984{
985 AutoCaller autoCaller(this);
986 AssertComRCReturnRC(autoCaller.rc());
987
988 AutoReadLock alock(this);
989
990 data.fEnabled = !!mData->mEnabled;
991 data.strMACAddress = mData->mMACAddress;
992 data.fCableConnected = !!mData->mCableConnected;
993
994 data.ulLineSpeed = mData->mLineSpeed;
995
996 data.fTraceEnabled = !!mData->mTraceEnabled;
997
998 data.strTraceFile = mData->mTraceFile;
999
1000 data.type = mData->mAdapterType;
1001
1002 switch (data.mode = mData->mAttachmentType)
1003 {
1004 case NetworkAttachmentType_Null:
1005 data.strName.setNull();
1006 break;
1007
1008 case NetworkAttachmentType_NAT:
1009 data.strName = mData->mNATNetwork;
1010 break;
1011
1012 case NetworkAttachmentType_Bridged:
1013 data.strName = mData->mHostInterface;
1014 break;
1015
1016 case NetworkAttachmentType_Internal:
1017 data.strName = mData->mInternalNetwork;
1018 break;
1019
1020 case NetworkAttachmentType_HostOnly:
1021 data.strName = mData->mHostInterface;
1022 break;
1023 }
1024
1025 return S_OK;
1026}
1027
1028/**
1029 * @note Locks this object for writing.
1030 */
1031bool NetworkAdapter::rollback()
1032{
1033 /* sanity */
1034 AutoCaller autoCaller(this);
1035 AssertComRCReturn (autoCaller.rc(), false);
1036
1037 AutoWriteLock alock(this);
1038
1039 bool changed = false;
1040
1041 if (mData.isBackedUp())
1042 {
1043 /* we need to check all data to see whether anything will be changed
1044 * after rollback */
1045 changed = mData.hasActualChanges();
1046 mData.rollback();
1047 }
1048
1049 return changed;
1050}
1051
1052/**
1053 * @note Locks this object for writing, together with the peer object (also
1054 * for writing) if there is one.
1055 */
1056void NetworkAdapter::commit()
1057{
1058 /* sanity */
1059 AutoCaller autoCaller(this);
1060 AssertComRCReturnVoid (autoCaller.rc());
1061
1062 /* sanity too */
1063 AutoCaller peerCaller (mPeer);
1064 AssertComRCReturnVoid (peerCaller.rc());
1065
1066 /* lock both for writing since we modify both (mPeer is "master" so locked
1067 * first) */
1068 AutoMultiWriteLock2 alock (mPeer, this);
1069
1070 if (mData.isBackedUp())
1071 {
1072 mData.commit();
1073 if (mPeer)
1074 {
1075 /* attach new data to the peer and reshare it */
1076 mPeer->mData.attach (mData);
1077 }
1078 }
1079}
1080
1081/**
1082 * @note Locks this object for writing, together with the peer object
1083 * represented by @a aThat (locked for reading).
1084 */
1085void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1086{
1087 AssertReturnVoid (aThat != NULL);
1088
1089 /* sanity */
1090 AutoCaller autoCaller(this);
1091 AssertComRCReturnVoid (autoCaller.rc());
1092
1093 /* sanity too */
1094 AutoCaller thatCaller (aThat);
1095 AssertComRCReturnVoid (thatCaller.rc());
1096
1097 /* peer is not modified, lock it for reading (aThat is "master" so locked
1098 * first) */
1099 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
1100
1101 /* this will back up current data */
1102 mData.assignCopy (aThat->mData);
1103}
1104
1105void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
1106{
1107 AssertReturnVoid (aOsType != NULL);
1108
1109 /* sanity */
1110 AutoCaller autoCaller(this);
1111 AssertComRCReturnVoid (autoCaller.rc());
1112
1113 AutoWriteLock alock(this);
1114
1115 bool e1000enabled = false;
1116#ifdef VBOX_WITH_E1000
1117 e1000enabled = true;
1118#endif // VBOX_WITH_E1000
1119
1120 NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1121
1122 /* Set default network adapter for this OS type */
1123 if (defaultType == NetworkAdapterType_I82540EM ||
1124 defaultType == NetworkAdapterType_I82543GC ||
1125 defaultType == NetworkAdapterType_I82545EM)
1126 {
1127 if (e1000enabled) mData->mAdapterType = defaultType;
1128 }
1129 else mData->mAdapterType = defaultType;
1130
1131 /* Enable and connect the first one adapter to the NAT */
1132 if (mData->mSlot == 0)
1133 {
1134 mData->mEnabled = true;
1135 mData->mAttachmentType = NetworkAttachmentType_NAT;
1136 mData->mCableConnected = true;
1137 }
1138}
1139
1140// private methods
1141////////////////////////////////////////////////////////////////////////////////
1142
1143/**
1144 * Worker routine for detach handling. No locking, no notifications.
1145
1146 * @note Must be called from under the object's write lock.
1147 */
1148void NetworkAdapter::detach()
1149{
1150 AssertReturnVoid (isWriteLockOnCurrentThread());
1151
1152 switch (mData->mAttachmentType)
1153 {
1154 case NetworkAttachmentType_Null:
1155 {
1156 /* nothing to do here */
1157 break;
1158 }
1159 case NetworkAttachmentType_NAT:
1160 {
1161 break;
1162 }
1163 case NetworkAttachmentType_Bridged:
1164 {
1165 /* reset handle and device name */
1166 mData->mHostInterface = "";
1167 break;
1168 }
1169 case NetworkAttachmentType_Internal:
1170 {
1171 mData->mInternalNetwork.setNull();
1172 break;
1173 }
1174 case NetworkAttachmentType_HostOnly:
1175 {
1176#if defined(VBOX_WITH_NETFLT)
1177 /* reset handle and device name */
1178 mData->mHostInterface = "";
1179#endif
1180 break;
1181 }
1182 }
1183
1184 mData->mAttachmentType = NetworkAttachmentType_Null;
1185}
1186
1187/**
1188 * Generates a new unique MAC address based on our vendor ID and
1189 * parts of a GUID.
1190 *
1191 * @note Must be called from under the object's write lock or within the init
1192 * span.
1193 */
1194void NetworkAdapter::generateMACAddress()
1195{
1196 /*
1197 * Our strategy is as follows: the first three bytes are our fixed
1198 * vendor ID (080027). The remaining 3 bytes will be taken from the
1199 * start of a GUID. This is a fairly safe algorithm.
1200 */
1201 char strMAC[13];
1202 Guid guid;
1203 guid.create();
1204 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1205 guid.ptr()->au8[0], guid.ptr()->au8[1], guid.ptr()->au8[2]);
1206 LogFlowThisFunc(("generated MAC: '%s'\n", strMAC));
1207 mData->mMACAddress = strMAC;
1208}
1209/* 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