VirtualBox

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

Last change on this file since 4071 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "NetworkAdapterImpl.h"
19#include "Logging.h"
20#include "MachineImpl.h"
21
22#include <iprt/string.h>
23#include <iprt/cpputils.h>
24
25#include <VBox/err.h>
26
27// constructor / destructor
28////////////////////////////////////////////////////////////////////////////////
29
30DEFINE_EMPTY_CTOR_DTOR (NetworkAdapter)
31
32HRESULT NetworkAdapter::FinalConstruct()
33{
34 return S_OK;
35}
36
37void NetworkAdapter::FinalRelease()
38{
39 uninit ();
40}
41
42// public initializer/uninitializer for internal purposes only
43////////////////////////////////////////////////////////////////////////////////
44
45/**
46 * Initializes the network adapter object.
47 *
48 * @param aParent Handle of the parent object.
49 */
50HRESULT NetworkAdapter::init (Machine *aParent, ULONG aSlot)
51{
52 LogFlowThisFunc (("aParent=%p, aSlot=%d\n", aParent, aSlot));
53
54 ComAssertRet (aParent, E_INVALIDARG);
55 ComAssertRet (aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
56
57 /* Enclose the state transition NotReady->InInit->Ready */
58 AutoInitSpan autoInitSpan (this);
59 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
60
61 unconst (mParent) = aParent;
62 /* mPeer is left null */
63
64 mData.allocate();
65
66 /* initialize data */
67 mData->mSlot = aSlot;
68
69 /* default to Am79C973 */
70 mData->mAdapterType = NetworkAdapterType_NetworkAdapterAm79C973;
71
72 /* generate the MAC address early to guarantee it is the same both after
73 * changing some other property (i.e. after mData.backup()) and after the
74 * subsequent mData.rollback(). */
75 generateMACAddress();
76
77 /* Confirm a successful initialization */
78 autoInitSpan.setSucceeded();
79
80 return S_OK;
81}
82
83/**
84 * Initializes the network adapter object given another network adapter object
85 * (a kind of copy constructor). This object shares data with
86 * the object passed as an argument.
87 *
88 * @note This object must be destroyed before the original object
89 * it shares data with is destroyed.
90 *
91 * @note Locks @a aThat object for reading.
92 */
93HRESULT NetworkAdapter::init (Machine *aParent, NetworkAdapter *aThat)
94{
95 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
96
97 ComAssertRet (aParent && aThat, E_INVALIDARG);
98
99 /* Enclose the state transition NotReady->InInit->Ready */
100 AutoInitSpan autoInitSpan (this);
101 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
102
103 unconst (mParent) = aParent;
104 unconst (mPeer) = aThat;
105
106 AutoCaller thatCaller (aThat);
107 AssertComRCReturnRC (thatCaller.rc());
108
109 AutoReaderLock thatLock (aThat);
110 mData.share (aThat->mData);
111
112 /* Confirm a successful initialization */
113 autoInitSpan.setSucceeded();
114
115 return S_OK;
116}
117
118/**
119 * Initializes the guest object given another guest object
120 * (a kind of copy constructor). This object makes a private copy of data
121 * of the original object passed as an argument.
122 *
123 * @note Locks @a aThat object for reading.
124 */
125HRESULT NetworkAdapter::initCopy (Machine *aParent, NetworkAdapter *aThat)
126{
127 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
128
129 ComAssertRet (aParent && aThat, E_INVALIDARG);
130
131 /* Enclose the state transition NotReady->InInit->Ready */
132 AutoInitSpan autoInitSpan (this);
133 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
134
135 unconst (mParent) = aParent;
136 /* mPeer is left null */
137
138 AutoCaller thatCaller (aThat);
139 AssertComRCReturnRC (thatCaller.rc());
140
141 AutoReaderLock thatLock (aThat);
142 mData.attachCopy (aThat->mData);
143
144 /* Confirm a successful initialization */
145 autoInitSpan.setSucceeded();
146
147 return S_OK;
148}
149
150/**
151 * Uninitializes the instance and sets the ready flag to FALSE.
152 * Called either from FinalRelease() or by the parent when it gets destroyed.
153 */
154void NetworkAdapter::uninit()
155{
156 LogFlowThisFunc (("\n"));
157
158 /* Enclose the state transition Ready->InUninit->NotReady */
159 AutoUninitSpan autoUninitSpan (this);
160 if (autoUninitSpan.uninitDone())
161 return;
162
163 mData.free();
164
165 unconst (mPeer).setNull();
166 unconst (mParent).setNull();
167}
168
169// INetworkAdapter properties
170////////////////////////////////////////////////////////////////////////////////
171
172STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
173{
174 if (!aAdapterType)
175 return E_POINTER;
176
177 AutoCaller autoCaller (this);
178 CheckComRCReturnRC (autoCaller.rc());
179
180 AutoReaderLock alock (this);
181
182 *aAdapterType = mData->mAdapterType;
183
184 return S_OK;
185}
186
187STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
188{
189 AutoCaller autoCaller (this);
190 CheckComRCReturnRC (autoCaller.rc());
191
192 /* the machine needs to be mutable */
193 Machine::AutoMutableStateDependency adep (mParent);
194 CheckComRCReturnRC (adep.rc());
195
196 AutoLock alock (this);
197
198 /* make sure the value is allowed */
199 switch (aAdapterType)
200 {
201 case NetworkAdapterType_NetworkAdapterAm79C970A:
202 case NetworkAdapterType_NetworkAdapterAm79C973:
203 break;
204 default:
205 return setError (E_FAIL,
206 tr("Invalid network adapter type '%d'"),
207 aAdapterType);
208 }
209
210 if (mData->mAdapterType != aAdapterType)
211 {
212 mData.backup();
213 mData->mAdapterType = aAdapterType;
214
215 /* leave the lock before informing callbacks */
216 alock.unlock();
217
218 mParent->onNetworkAdapterChange (this);
219 }
220
221 return S_OK;
222}
223
224STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
225{
226 if (!aSlot)
227 return E_POINTER;
228
229 AutoCaller autoCaller (this);
230 CheckComRCReturnRC (autoCaller.rc());
231
232 AutoReaderLock alock (this);
233
234 *aSlot = mData->mSlot;
235
236 return S_OK;
237}
238
239STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
240{
241 if (!aEnabled)
242 return E_POINTER;
243
244 AutoCaller autoCaller (this);
245 CheckComRCReturnRC (autoCaller.rc());
246
247 AutoReaderLock alock (this);
248
249 *aEnabled = mData->mEnabled;
250
251 return S_OK;
252}
253
254STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
255{
256 AutoCaller autoCaller (this);
257 CheckComRCReturnRC (autoCaller.rc());
258
259 /* the machine needs to be mutable */
260 Machine::AutoMutableStateDependency adep (mParent);
261 CheckComRCReturnRC (adep.rc());
262
263 AutoLock alock (this);
264
265 if (mData->mEnabled != aEnabled)
266 {
267 mData.backup();
268 mData->mEnabled = aEnabled;
269
270 /* leave the lock before informing callbacks */
271 alock.unlock();
272
273 mParent->onNetworkAdapterChange (this);
274 }
275
276 return S_OK;
277}
278
279STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress)
280{
281 if (!aMACAddress)
282 return E_POINTER;
283
284 AutoCaller autoCaller (this);
285 CheckComRCReturnRC (autoCaller.rc());
286
287 AutoReaderLock alock (this);
288
289 ComAssertRet (!!mData->mMACAddress, E_FAIL);
290
291 mData->mMACAddress.cloneTo (aMACAddress);
292
293 return S_OK;
294}
295
296STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(INPTR BSTR aMACAddress)
297{
298 AutoCaller autoCaller (this);
299 CheckComRCReturnRC (autoCaller.rc());
300
301 /* the machine needs to be mutable */
302 Machine::AutoMutableStateDependency adep (mParent);
303 CheckComRCReturnRC (adep.rc());
304
305 AutoLock alock (this);
306
307 HRESULT rc = S_OK;
308 bool emitChangeEvent = false;
309
310 /*
311 * Are we supposed to generate a MAC?
312 */
313 if (!aMACAddress)
314 {
315 mData.backup();
316
317 generateMACAddress();
318 emitChangeEvent = true;
319 }
320 else
321 {
322 if (mData->mMACAddress != aMACAddress)
323 {
324 /*
325 * Verify given MAC address
326 */
327 Utf8Str macAddressUtf = aMACAddress;
328 char *macAddressStr = (char*)macAddressUtf.raw();
329 int i = 0;
330 while ((i < 12) && macAddressStr && (rc == S_OK))
331 {
332 char c = *macAddressStr;
333 /* we only accept capital letters */
334 if (((c < '0') || (c > '9')) &&
335 ((c < 'A') || (c > 'F')))
336 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
337 macAddressStr++;
338 i++;
339 }
340 /* we must have parsed exactly 12 characters */
341 if (i != 12)
342 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
343
344 if (SUCCEEDED (rc))
345 {
346 mData.backup();
347
348 mData->mMACAddress = aMACAddress;
349 emitChangeEvent = true;
350 }
351 }
352 }
353
354 if (emitChangeEvent)
355 {
356 /* leave the lock before informing callbacks */
357 alock.unlock();
358
359 mParent->onNetworkAdapterChange (this);
360 }
361
362 return rc;
363}
364
365STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
366 NetworkAttachmentType_T *aAttachmentType)
367{
368 if (!aAttachmentType)
369 return E_POINTER;
370
371 AutoCaller autoCaller (this);
372 CheckComRCReturnRC (autoCaller.rc());
373
374 AutoReaderLock alock (this);
375
376 *aAttachmentType = mData->mAttachmentType;
377
378 return S_OK;
379}
380
381STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
382{
383 if (!aHostInterface)
384 return E_POINTER;
385
386 AutoCaller autoCaller (this);
387 CheckComRCReturnRC (autoCaller.rc());
388
389 AutoReaderLock alock (this);
390
391 mData->mHostInterface.cloneTo (aHostInterface);
392
393 return S_OK;
394}
395
396STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(INPTR BSTR aHostInterface)
397{
398 /** @todo Validate input string length. r=dmik: do it in XML schema?*/
399
400#ifdef RT_OS_WINDOWS
401 // we don't allow null strings for the host interface on Win32
402 // (because the @name attribute of <HostInerface> must be always present,
403 // but can be empty).
404 if (!aHostInterface)
405 return E_INVALIDARG;
406#endif
407#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
408 // empty strings are not allowed as path names
409 if (aHostInterface && !(*aHostInterface))
410 return E_INVALIDARG;
411#endif
412
413 AutoCaller autoCaller (this);
414 CheckComRCReturnRC (autoCaller.rc());
415
416 /* the machine needs to be mutable */
417 Machine::AutoMutableStateDependency adep (mParent);
418 CheckComRCReturnRC (adep.rc());
419
420 AutoLock alock (this);
421
422 if (mData->mHostInterface != aHostInterface)
423 {
424 mData.backup();
425 mData->mHostInterface = aHostInterface;
426
427 /* leave the lock before informing callbacks */
428 alock.unlock();
429
430 mParent->onNetworkAdapterChange (this);
431 }
432
433 return S_OK;
434}
435
436#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
437
438STDMETHODIMP NetworkAdapter::COMGETTER(TAPFileDescriptor)(LONG *aTAPFileDescriptor)
439{
440 if (!aTAPFileDescriptor)
441 return E_POINTER;
442
443 AutoCaller autoCaller (this);
444 CheckComRCReturnRC (autoCaller.rc());
445
446 AutoReaderLock alock (this);
447
448 *aTAPFileDescriptor = mData->mTAPFD;
449
450 return S_OK;
451}
452
453STDMETHODIMP NetworkAdapter::COMSETTER(TAPFileDescriptor)(LONG aTAPFileDescriptor)
454{
455 /*
456 * Validate input.
457 */
458 RTFILE tapFD = aTAPFileDescriptor;
459 if (tapFD != NIL_RTFILE && (LONG)tapFD != aTAPFileDescriptor)
460 {
461 AssertMsgFailed(("Invalid file descriptor: %ld.\n", aTAPFileDescriptor));
462 return setError (E_INVALIDARG,
463 tr ("Invalid file descriptor: %ld"), aTAPFileDescriptor);
464 }
465
466 AutoCaller autoCaller (this);
467 CheckComRCReturnRC (autoCaller.rc());
468
469 /* the machine needs to be mutable */
470 Machine::AutoMutableStateDependency adep (mParent);
471 CheckComRCReturnRC (adep.rc());
472
473 AutoLock alock (this);
474
475 if (mData->mTAPFD != (RTFILE) aTAPFileDescriptor)
476 {
477 mData.backup();
478 mData->mTAPFD = aTAPFileDescriptor;
479
480 /* leave the lock before informing callbacks */
481 alock.unlock();
482
483 mParent->onNetworkAdapterChange (this);
484 }
485
486 return S_OK;
487}
488
489STDMETHODIMP NetworkAdapter::COMGETTER(TAPSetupApplication) (
490 BSTR *aTAPSetupApplication)
491{
492 if (!aTAPSetupApplication)
493 return E_POINTER;
494
495 AutoCaller autoCaller (this);
496 CheckComRCReturnRC (autoCaller.rc());
497
498 AutoReaderLock alock (this);
499
500 /* we don't have to be in TAP mode to support this call */
501 mData->mTAPSetupApplication.cloneTo (aTAPSetupApplication);
502
503 return S_OK;
504}
505
506STDMETHODIMP NetworkAdapter::COMSETTER(TAPSetupApplication) (
507 INPTR BSTR aTAPSetupApplication)
508{
509 /* empty strings are not allowed as path names */
510 if (aTAPSetupApplication && !(*aTAPSetupApplication))
511 return E_INVALIDARG;
512
513 AutoCaller autoCaller (this);
514 CheckComRCReturnRC (autoCaller.rc());
515
516 /* the machine needs to be mutable */
517 Machine::AutoMutableStateDependency adep (mParent);
518 CheckComRCReturnRC (adep.rc());
519
520 AutoLock alock (this);
521
522 if (mData->mTAPSetupApplication != aTAPSetupApplication)
523 {
524 mData.backup();
525 mData->mTAPSetupApplication = aTAPSetupApplication;
526
527 /* leave the lock before informing callbacks */
528 alock.unlock();
529
530 mParent->onNetworkAdapterChange (this);
531 }
532
533 return S_OK;
534}
535
536STDMETHODIMP NetworkAdapter::COMGETTER(TAPTerminateApplication) (
537 BSTR *aTAPTerminateApplication)
538{
539 if (!aTAPTerminateApplication)
540 return E_POINTER;
541
542 AutoCaller autoCaller (this);
543 CheckComRCReturnRC (autoCaller.rc());
544
545 AutoReaderLock alock (this);
546
547 /* we don't have to be in TAP mode to support this call */
548 mData->mTAPTerminateApplication.cloneTo(aTAPTerminateApplication);
549
550 return S_OK;
551}
552
553STDMETHODIMP NetworkAdapter::COMSETTER(TAPTerminateApplication) (
554 INPTR BSTR aTAPTerminateApplication)
555{
556 /* empty strings are not allowed as path names */
557 if (aTAPTerminateApplication && !(*aTAPTerminateApplication))
558 return E_INVALIDARG;
559
560 AutoCaller autoCaller (this);
561 CheckComRCReturnRC (autoCaller.rc());
562
563 /* the machine needs to be mutable */
564 Machine::AutoMutableStateDependency adep (mParent);
565 CheckComRCReturnRC (adep.rc());
566
567 AutoLock alock (this);
568
569 if (mData->mTAPTerminateApplication != aTAPTerminateApplication)
570 {
571 mData.backup();
572 mData->mTAPTerminateApplication = aTAPTerminateApplication;
573
574 /* leave the lock before informing callbacks */
575 alock.unlock();
576
577 mParent->onNetworkAdapterChange(this);
578 }
579
580 return S_OK;
581}
582
583#endif /* VBOX_WITH_UNIXY_TAP_NETWORKING */
584
585STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
586{
587 /* we don't allow null strings */
588 if (!aInternalNetwork)
589 return E_POINTER;
590
591 AutoCaller autoCaller (this);
592 CheckComRCReturnRC (autoCaller.rc());
593
594 AutoReaderLock alock (this);
595
596 mData->mInternalNetwork.cloneTo (aInternalNetwork);
597
598 return S_OK;
599}
600
601STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (INPTR BSTR aInternalNetwork)
602{
603 if (!aInternalNetwork)
604 return E_INVALIDARG;
605
606 AutoCaller autoCaller (this);
607 CheckComRCReturnRC (autoCaller.rc());
608
609 /* the machine needs to be mutable */
610 Machine::AutoMutableStateDependency adep (mParent);
611 CheckComRCReturnRC (adep.rc());
612
613 AutoLock alock (this);
614
615 if (mData->mInternalNetwork != aInternalNetwork)
616 {
617 /* if an empty string is to be set, internal networking must be turned off */
618 if ( (aInternalNetwork == Bstr(""))
619 && (mData->mAttachmentType = NetworkAttachmentType_InternalNetworkAttachment))
620 {
621 return setError (E_FAIL, tr ("Empty internal network name is not valid"));
622 }
623
624 mData.backup();
625 mData->mInternalNetwork = aInternalNetwork;
626
627 /* leave the lock before informing callbacks */
628 alock.unlock();
629
630 mParent->onNetworkAdapterChange (this);
631 }
632
633 return S_OK;
634}
635
636STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
637{
638 if (!aConnected)
639 return E_POINTER;
640
641 AutoCaller autoCaller (this);
642 CheckComRCReturnRC (autoCaller.rc());
643
644 AutoReaderLock alock (this);
645
646 *aConnected = mData->mCableConnected;
647
648 return S_OK;
649}
650
651STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
652{
653 AutoCaller autoCaller (this);
654 CheckComRCReturnRC (autoCaller.rc());
655
656 /* the machine needs to be mutable */
657 Machine::AutoMutableStateDependency adep (mParent);
658 CheckComRCReturnRC (adep.rc());
659
660 AutoLock alock (this);
661
662 if (aConnected != mData->mCableConnected)
663 {
664 mData.backup();
665 mData->mCableConnected = aConnected;
666
667 /* leave the lock before informing callbacks */
668 alock.unlock();
669
670 mParent->onNetworkAdapterChange (this);
671 }
672
673 return S_OK;
674}
675
676STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
677{
678 if (!aEnabled)
679 return E_POINTER;
680
681 AutoCaller autoCaller (this);
682 CheckComRCReturnRC (autoCaller.rc());
683
684 AutoReaderLock alock (this);
685
686 *aEnabled = mData->mTraceEnabled;
687 return S_OK;
688}
689
690STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
691{
692 AutoCaller autoCaller (this);
693 CheckComRCReturnRC (autoCaller.rc());
694
695 /* the machine needs to be mutable */
696 Machine::AutoMutableStateDependency adep (mParent);
697 CheckComRCReturnRC (adep.rc());
698
699 AutoLock alock (this);
700
701 if (aEnabled != mData->mTraceEnabled)
702 {
703 mData.backup();
704 mData->mTraceEnabled = aEnabled;
705
706 /* leave the lock before informing callbacks */
707 alock.unlock();
708
709 mParent->onNetworkAdapterChange (this);
710 }
711
712 return S_OK;
713}
714
715STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
716{
717 if (!aTraceFile)
718 return E_POINTER;
719
720 AutoCaller autoCaller (this);
721 CheckComRCReturnRC (autoCaller.rc());
722
723 AutoReaderLock alock (this);
724
725 mData->mTraceFile.cloneTo (aTraceFile);
726
727 return S_OK;
728}
729
730STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (INPTR BSTR aTraceFile)
731{
732 if (!aTraceFile)
733 return E_INVALIDARG;
734
735 AutoCaller autoCaller (this);
736 CheckComRCReturnRC (autoCaller.rc());
737
738 /* the machine needs to be mutable */
739 Machine::AutoMutableStateDependency adep (mParent);
740 CheckComRCReturnRC (adep.rc());
741
742 AutoLock alock (this);
743
744 if (mData->mTraceFile != aTraceFile)
745 {
746 mData.backup();
747 mData->mTraceFile = aTraceFile;
748
749 /* leave the lock before informing callbacks */
750 alock.unlock();
751
752 mParent->onNetworkAdapterChange (this);
753 }
754
755 return S_OK;
756}
757
758// INetworkAdapter methods
759////////////////////////////////////////////////////////////////////////////////
760
761STDMETHODIMP NetworkAdapter::AttachToNAT()
762{
763 AutoCaller autoCaller (this);
764 CheckComRCReturnRC (autoCaller.rc());
765
766 /* the machine needs to be mutable */
767 Machine::AutoMutableStateDependency adep (mParent);
768 CheckComRCReturnRC (adep.rc());
769
770 AutoLock alock (this);
771
772 if (mData->mAttachmentType != NetworkAttachmentType_NATNetworkAttachment)
773 {
774 mData.backup();
775
776 detach();
777
778 mData->mAttachmentType = NetworkAttachmentType_NATNetworkAttachment;
779
780 /* leave the lock before informing callbacks */
781 alock.unlock();
782
783 mParent->onNetworkAdapterChange (this);
784 }
785
786 return S_OK;
787}
788
789STDMETHODIMP NetworkAdapter::AttachToHostInterface()
790{
791 AutoCaller autoCaller (this);
792 CheckComRCReturnRC (autoCaller.rc());
793
794 /* the machine needs to be mutable */
795 Machine::AutoMutableStateDependency adep (mParent);
796 CheckComRCReturnRC (adep.rc());
797
798 AutoLock alock (this);
799
800 /* don't do anything if we're already host interface attached */
801 if (mData->mAttachmentType != NetworkAttachmentType_HostInterfaceNetworkAttachment)
802 {
803 mData.backup();
804
805 /* first detach the current attachment */
806 detach();
807
808 mData->mAttachmentType = NetworkAttachmentType_HostInterfaceNetworkAttachment;
809
810 /* leave the lock before informing callbacks */
811 alock.unlock();
812
813 mParent->onNetworkAdapterChange (this);
814 }
815
816 return S_OK;
817}
818
819STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
820{
821 AutoCaller autoCaller (this);
822 CheckComRCReturnRC (autoCaller.rc());
823
824 /* the machine needs to be mutable */
825 Machine::AutoMutableStateDependency adep (mParent);
826 CheckComRCReturnRC (adep.rc());
827
828 AutoLock alock (this);
829
830 /* don't do anything if we're already internal network attached */
831 if (mData->mAttachmentType != NetworkAttachmentType_InternalNetworkAttachment)
832 {
833 mData.backup();
834
835 /* first detach the current attachment */
836 detach();
837
838 /* there must an internal network name */
839 if ( !mData->mInternalNetwork
840 || (mData->mInternalNetwork == Bstr ("")))
841 {
842 LogRel (("Internal network name not defined, "
843 "setting to default \"intnet\"\n"));
844 mData->mInternalNetwork = Bstr ("intnet");
845 }
846
847 mData->mAttachmentType = NetworkAttachmentType_InternalNetworkAttachment;
848
849 /* leave the lock before informing callbacks */
850 alock.unlock();
851
852 mParent->onNetworkAdapterChange (this);
853 }
854
855 return S_OK;
856}
857
858STDMETHODIMP NetworkAdapter::Detach()
859{
860 AutoCaller autoCaller (this);
861 CheckComRCReturnRC (autoCaller.rc());
862
863 /* the machine needs to be mutable */
864 Machine::AutoMutableStateDependency adep (mParent);
865 CheckComRCReturnRC (adep.rc());
866
867 AutoLock alock (this);
868
869 if (mData->mAttachmentType != NetworkAttachmentType_NoNetworkAttachment)
870 {
871 mData.backup();
872
873 detach();
874
875 /* leave the lock before informing callbacks */
876 alock.unlock();
877
878 mParent->onNetworkAdapterChange (this);
879 }
880
881 return S_OK;
882}
883
884// public methods only for internal purposes
885////////////////////////////////////////////////////////////////////////////////
886
887/**
888 * @note Locks this object for writing.
889 */
890bool NetworkAdapter::rollback()
891{
892 /* sanity */
893 AutoCaller autoCaller (this);
894 AssertComRCReturn (autoCaller.rc(), false);
895
896 AutoLock alock (this);
897
898 bool changed = false;
899
900 if (mData.isBackedUp())
901 {
902 /* we need to check all data to see whether anything will be changed
903 * after rollback */
904 changed = mData.hasActualChanges();
905 mData.rollback();
906 }
907
908 return changed;
909}
910
911/**
912 * @note Locks this object for writing, together with the peer object (also
913 * for writing) if there is one.
914 */
915void NetworkAdapter::commit()
916{
917 /* sanity */
918 AutoCaller autoCaller (this);
919 AssertComRCReturnVoid (autoCaller.rc());
920
921 /* sanity too */
922 AutoCaller thatCaller (mPeer);
923 AssertComRCReturnVoid (thatCaller.rc());
924
925 /* lock both for writing since we modify both */
926 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
927
928 if (mData.isBackedUp())
929 {
930 mData.commit();
931 if (mPeer)
932 {
933 /* attach new data to the peer and reshare it */
934 mPeer->mData.attach (mData);
935 }
936 }
937}
938
939/**
940 * @note Locks this object for writing, together with the peer object
941 * represented by @a aThat (locked for reading).
942 */
943void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
944{
945 AssertReturnVoid (aThat != NULL);
946
947 /* sanity */
948 AutoCaller autoCaller (this);
949 AssertComRCReturnVoid (autoCaller.rc());
950
951 /* sanity too */
952 AutoCaller thatCaller (mPeer);
953 AssertComRCReturnVoid (thatCaller.rc());
954
955 /* peer is not modified, lock it for reading */
956 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
957
958 /* this will back up current data */
959 mData.assignCopy (aThat->mData);
960}
961
962// private methods
963////////////////////////////////////////////////////////////////////////////////
964
965/**
966 * Worker routine for detach handling. No locking, no notifications.
967
968 * @note Must be called from under the object's write lock.
969 */
970void NetworkAdapter::detach()
971{
972 AssertReturnVoid (isLockedOnCurrentThread());
973
974 switch (mData->mAttachmentType)
975 {
976 case NetworkAttachmentType_NoNetworkAttachment:
977 {
978 /* nothing to do here */
979 break;
980 }
981 case NetworkAttachmentType_NATNetworkAttachment:
982 {
983 break;
984 }
985 case NetworkAttachmentType_HostInterfaceNetworkAttachment:
986 {
987 /* reset handle and device name */
988#ifdef RT_OS_WINDOWS
989 mData->mHostInterface = "";
990#endif
991#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
992 mData->mHostInterface.setNull();
993 mData->mTAPFD = NIL_RTFILE;
994#endif
995 break;
996 }
997 case NetworkAttachmentType_InternalNetworkAttachment:
998 {
999 mData->mInternalNetwork.setNull();
1000 break;
1001 }
1002 }
1003
1004 mData->mAttachmentType = NetworkAttachmentType_NoNetworkAttachment;
1005}
1006
1007/**
1008 * Generates a new unique MAC address based on our vendor ID and
1009 * parts of a GUID.
1010 *
1011 * @note Must be called from under the object's write lock or within the init
1012 * span.
1013 */
1014void NetworkAdapter::generateMACAddress()
1015{
1016 /*
1017 * Our strategy is as follows: the first three bytes are our fixed
1018 * vendor ID (080027). The remaining 3 bytes will be taken from the
1019 * start of a GUID. This is a fairly safe algorithm.
1020 */
1021 char strMAC[13];
1022 Guid guid;
1023 guid.create();
1024 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1025 guid.ptr()->au8[0], guid.ptr()->au8[1], guid.ptr()->au8[2]);
1026 LogFlowThisFunc (("generated MAC: '%s'\n", strMAC));
1027 mData->mMACAddress = strMAC;
1028}
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