VirtualBox

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

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

Main: Converted AudioAdapter and NetworkAdapter to the new locking scheme.

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