VirtualBox

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

Last change on this file since 5118 was 5118, checked in by vboxsync, 18 years ago

Main: Added checking for errors when initializing NetworkAdapter and AudioAdapter classes from the settings file; Improved inaccessible VM handling (could show a wrong message as a last access error).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.1 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 = macAddressUtf.mutableRaw();
329 int i = 0;
330 while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK))
331 {
332 char c = *macAddressStr;
333 /* strip any occurrence of colons in the string. */
334 if (c == ':')
335 {
336 /* cannot use strcpy, as the areas do overlap. */
337 /* remember that in this context
338 * strlen(macAddressStr) == strlen(macAddressStr+1)+1 */
339 memmove(macAddressStr, macAddressStr + 1,
340 strlen(macAddressStr));
341 continue;
342 }
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 be even for unicast addresses */
355 if ((i == 1) && (c & 1))
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);
381 }
382
383 return rc;
384}
385
386STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
387 NetworkAttachmentType_T *aAttachmentType)
388{
389 if (!aAttachmentType)
390 return E_POINTER;
391
392 AutoCaller autoCaller (this);
393 CheckComRCReturnRC (autoCaller.rc());
394
395 AutoReaderLock alock (this);
396
397 *aAttachmentType = mData->mAttachmentType;
398
399 return S_OK;
400}
401
402STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
403{
404 if (!aHostInterface)
405 return E_POINTER;
406
407 AutoCaller autoCaller (this);
408 CheckComRCReturnRC (autoCaller.rc());
409
410 AutoReaderLock alock (this);
411
412 mData->mHostInterface.cloneTo (aHostInterface);
413
414 return S_OK;
415}
416
417STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(INPTR BSTR aHostInterface)
418{
419 /** @todo Validate input string length. r=dmik: do it in XML schema?*/
420
421#ifdef RT_OS_WINDOWS
422 // we don't allow null strings for the host interface on Win32
423 // (because the @name attribute of <HostInerface> must be always present,
424 // but can be empty).
425 if (!aHostInterface)
426 return E_INVALIDARG;
427#endif
428#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
429 // empty strings are not allowed as path names
430 if (aHostInterface && !(*aHostInterface))
431 return E_INVALIDARG;
432#endif
433
434 AutoCaller autoCaller (this);
435 CheckComRCReturnRC (autoCaller.rc());
436
437 /* the machine needs to be mutable */
438 Machine::AutoMutableStateDependency adep (mParent);
439 CheckComRCReturnRC (adep.rc());
440
441 AutoLock alock (this);
442
443 if (mData->mHostInterface != aHostInterface)
444 {
445 mData.backup();
446 mData->mHostInterface = aHostInterface;
447
448 /* leave the lock before informing callbacks */
449 alock.unlock();
450
451 mParent->onNetworkAdapterChange (this);
452 }
453
454 return S_OK;
455}
456
457#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
458
459STDMETHODIMP NetworkAdapter::COMGETTER(TAPFileDescriptor)(LONG *aTAPFileDescriptor)
460{
461 if (!aTAPFileDescriptor)
462 return E_POINTER;
463
464 AutoCaller autoCaller (this);
465 CheckComRCReturnRC (autoCaller.rc());
466
467 AutoReaderLock alock (this);
468
469 *aTAPFileDescriptor = mData->mTAPFD;
470
471 return S_OK;
472}
473
474STDMETHODIMP NetworkAdapter::COMSETTER(TAPFileDescriptor)(LONG aTAPFileDescriptor)
475{
476 /*
477 * Validate input.
478 */
479 RTFILE tapFD = aTAPFileDescriptor;
480 if (tapFD != NIL_RTFILE && (LONG)tapFD != aTAPFileDescriptor)
481 {
482 AssertMsgFailed(("Invalid file descriptor: %ld.\n", aTAPFileDescriptor));
483 return setError (E_INVALIDARG,
484 tr ("Invalid file descriptor: %ld"), aTAPFileDescriptor);
485 }
486
487 AutoCaller autoCaller (this);
488 CheckComRCReturnRC (autoCaller.rc());
489
490 /* the machine needs to be mutable */
491 Machine::AutoMutableStateDependency adep (mParent);
492 CheckComRCReturnRC (adep.rc());
493
494 AutoLock alock (this);
495
496 if (mData->mTAPFD != (RTFILE) aTAPFileDescriptor)
497 {
498 mData.backup();
499 mData->mTAPFD = aTAPFileDescriptor;
500
501 /* leave the lock before informing callbacks */
502 alock.unlock();
503
504 mParent->onNetworkAdapterChange (this);
505 }
506
507 return S_OK;
508}
509
510STDMETHODIMP NetworkAdapter::COMGETTER(TAPSetupApplication) (
511 BSTR *aTAPSetupApplication)
512{
513 if (!aTAPSetupApplication)
514 return E_POINTER;
515
516 AutoCaller autoCaller (this);
517 CheckComRCReturnRC (autoCaller.rc());
518
519 AutoReaderLock alock (this);
520
521 /* we don't have to be in TAP mode to support this call */
522 mData->mTAPSetupApplication.cloneTo (aTAPSetupApplication);
523
524 return S_OK;
525}
526
527STDMETHODIMP NetworkAdapter::COMSETTER(TAPSetupApplication) (
528 INPTR BSTR aTAPSetupApplication)
529{
530 /* empty strings are not allowed as path names */
531 if (aTAPSetupApplication && !(*aTAPSetupApplication))
532 return E_INVALIDARG;
533
534 AutoCaller autoCaller (this);
535 CheckComRCReturnRC (autoCaller.rc());
536
537 /* the machine needs to be mutable */
538 Machine::AutoMutableStateDependency adep (mParent);
539 CheckComRCReturnRC (adep.rc());
540
541 AutoLock alock (this);
542
543 if (mData->mTAPSetupApplication != aTAPSetupApplication)
544 {
545 mData.backup();
546 mData->mTAPSetupApplication = aTAPSetupApplication;
547
548 /* leave the lock before informing callbacks */
549 alock.unlock();
550
551 mParent->onNetworkAdapterChange (this);
552 }
553
554 return S_OK;
555}
556
557STDMETHODIMP NetworkAdapter::COMGETTER(TAPTerminateApplication) (
558 BSTR *aTAPTerminateApplication)
559{
560 if (!aTAPTerminateApplication)
561 return E_POINTER;
562
563 AutoCaller autoCaller (this);
564 CheckComRCReturnRC (autoCaller.rc());
565
566 AutoReaderLock alock (this);
567
568 /* we don't have to be in TAP mode to support this call */
569 mData->mTAPTerminateApplication.cloneTo(aTAPTerminateApplication);
570
571 return S_OK;
572}
573
574STDMETHODIMP NetworkAdapter::COMSETTER(TAPTerminateApplication) (
575 INPTR BSTR aTAPTerminateApplication)
576{
577 /* empty strings are not allowed as path names */
578 if (aTAPTerminateApplication && !(*aTAPTerminateApplication))
579 return E_INVALIDARG;
580
581 AutoCaller autoCaller (this);
582 CheckComRCReturnRC (autoCaller.rc());
583
584 /* the machine needs to be mutable */
585 Machine::AutoMutableStateDependency adep (mParent);
586 CheckComRCReturnRC (adep.rc());
587
588 AutoLock alock (this);
589
590 if (mData->mTAPTerminateApplication != aTAPTerminateApplication)
591 {
592 mData.backup();
593 mData->mTAPTerminateApplication = aTAPTerminateApplication;
594
595 /* leave the lock before informing callbacks */
596 alock.unlock();
597
598 mParent->onNetworkAdapterChange(this);
599 }
600
601 return S_OK;
602}
603
604#endif /* VBOX_WITH_UNIXY_TAP_NETWORKING */
605
606STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
607{
608 /* we don't allow null strings */
609 if (!aInternalNetwork)
610 return E_POINTER;
611
612 AutoCaller autoCaller (this);
613 CheckComRCReturnRC (autoCaller.rc());
614
615 AutoReaderLock alock (this);
616
617 mData->mInternalNetwork.cloneTo (aInternalNetwork);
618
619 return S_OK;
620}
621
622STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (INPTR BSTR aInternalNetwork)
623{
624 if (!aInternalNetwork)
625 return E_INVALIDARG;
626
627 AutoCaller autoCaller (this);
628 CheckComRCReturnRC (autoCaller.rc());
629
630 /* the machine needs to be mutable */
631 Machine::AutoMutableStateDependency adep (mParent);
632 CheckComRCReturnRC (adep.rc());
633
634 AutoLock alock (this);
635
636 if (mData->mInternalNetwork != aInternalNetwork)
637 {
638 /* if an empty string is to be set, internal networking must be turned off */
639 if ( (aInternalNetwork == Bstr(""))
640 && (mData->mAttachmentType = NetworkAttachmentType_InternalNetworkAttachment))
641 {
642 return setError (E_FAIL, tr ("Empty internal network name is not valid"));
643 }
644
645 mData.backup();
646 mData->mInternalNetwork = aInternalNetwork;
647
648 /* leave the lock before informing callbacks */
649 alock.unlock();
650
651 mParent->onNetworkAdapterChange (this);
652 }
653
654 return S_OK;
655}
656
657STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
658{
659 if (!aConnected)
660 return E_POINTER;
661
662 AutoCaller autoCaller (this);
663 CheckComRCReturnRC (autoCaller.rc());
664
665 AutoReaderLock alock (this);
666
667 *aConnected = mData->mCableConnected;
668
669 return S_OK;
670}
671
672STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
673{
674 AutoCaller autoCaller (this);
675 CheckComRCReturnRC (autoCaller.rc());
676
677 /* the machine needs to be mutable */
678 Machine::AutoMutableStateDependency adep (mParent);
679 CheckComRCReturnRC (adep.rc());
680
681 AutoLock alock (this);
682
683 if (aConnected != mData->mCableConnected)
684 {
685 mData.backup();
686 mData->mCableConnected = aConnected;
687
688 /* leave the lock before informing callbacks */
689 alock.unlock();
690
691 mParent->onNetworkAdapterChange (this);
692 }
693
694 return S_OK;
695}
696
697STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
698{
699 if (!aSpeed)
700 return E_POINTER;
701
702 AutoCaller autoCaller (this);
703 CheckComRCReturnRC (autoCaller.rc());
704
705 AutoReaderLock alock (this);
706
707 *aSpeed = mData->mLineSpeed;
708
709 return S_OK;
710}
711
712STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
713{
714 AutoCaller autoCaller (this);
715 CheckComRCReturnRC (autoCaller.rc());
716
717 /* the machine needs to be mutable */
718 Machine::AutoMutableStateDependency adep (mParent);
719 CheckComRCReturnRC (adep.rc());
720
721 AutoLock alock (this);
722
723 if (aSpeed != mData->mLineSpeed)
724 {
725 mData.backup();
726 mData->mLineSpeed = aSpeed;
727
728 /* leave the lock before informing callbacks */
729 alock.unlock();
730
731 mParent->onNetworkAdapterChange (this);
732 }
733
734 return S_OK;
735}
736
737STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
738{
739 if (!aEnabled)
740 return E_POINTER;
741
742 AutoCaller autoCaller (this);
743 CheckComRCReturnRC (autoCaller.rc());
744
745 AutoReaderLock alock (this);
746
747 *aEnabled = mData->mTraceEnabled;
748 return S_OK;
749}
750
751STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
752{
753 AutoCaller autoCaller (this);
754 CheckComRCReturnRC (autoCaller.rc());
755
756 /* the machine needs to be mutable */
757 Machine::AutoMutableStateDependency adep (mParent);
758 CheckComRCReturnRC (adep.rc());
759
760 AutoLock alock (this);
761
762 if (aEnabled != mData->mTraceEnabled)
763 {
764 mData.backup();
765 mData->mTraceEnabled = aEnabled;
766
767 /* leave the lock before informing callbacks */
768 alock.unlock();
769
770 mParent->onNetworkAdapterChange (this);
771 }
772
773 return S_OK;
774}
775
776STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
777{
778 if (!aTraceFile)
779 return E_POINTER;
780
781 AutoCaller autoCaller (this);
782 CheckComRCReturnRC (autoCaller.rc());
783
784 AutoReaderLock alock (this);
785
786 mData->mTraceFile.cloneTo (aTraceFile);
787
788 return S_OK;
789}
790
791STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (INPTR BSTR aTraceFile)
792{
793 AutoCaller autoCaller (this);
794 CheckComRCReturnRC (autoCaller.rc());
795
796 /* the machine needs to be mutable */
797 Machine::AutoMutableStateDependency adep (mParent);
798 CheckComRCReturnRC (adep.rc());
799
800 AutoLock alock (this);
801
802 if (mData->mTraceFile != aTraceFile)
803 {
804 mData.backup();
805 mData->mTraceFile = aTraceFile;
806
807 /* leave the lock before informing callbacks */
808 alock.unlock();
809
810 mParent->onNetworkAdapterChange (this);
811 }
812
813 return S_OK;
814}
815
816// INetworkAdapter methods
817////////////////////////////////////////////////////////////////////////////////
818
819STDMETHODIMP NetworkAdapter::AttachToNAT()
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 if (mData->mAttachmentType != NetworkAttachmentType_NATNetworkAttachment)
831 {
832 mData.backup();
833
834 detach();
835
836 mData->mAttachmentType = NetworkAttachmentType_NATNetworkAttachment;
837
838 /* leave the lock before informing callbacks */
839 alock.unlock();
840
841 mParent->onNetworkAdapterChange (this);
842 }
843
844 return S_OK;
845}
846
847STDMETHODIMP NetworkAdapter::AttachToHostInterface()
848{
849 AutoCaller autoCaller (this);
850 CheckComRCReturnRC (autoCaller.rc());
851
852 /* the machine needs to be mutable */
853 Machine::AutoMutableStateDependency adep (mParent);
854 CheckComRCReturnRC (adep.rc());
855
856 AutoLock alock (this);
857
858 /* don't do anything if we're already host interface attached */
859 if (mData->mAttachmentType != NetworkAttachmentType_HostInterfaceNetworkAttachment)
860 {
861 mData.backup();
862
863 /* first detach the current attachment */
864 detach();
865
866 mData->mAttachmentType = NetworkAttachmentType_HostInterfaceNetworkAttachment;
867
868 /* leave the lock before informing callbacks */
869 alock.unlock();
870
871 mParent->onNetworkAdapterChange (this);
872 }
873
874 return S_OK;
875}
876
877STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
878{
879 AutoCaller autoCaller (this);
880 CheckComRCReturnRC (autoCaller.rc());
881
882 /* the machine needs to be mutable */
883 Machine::AutoMutableStateDependency adep (mParent);
884 CheckComRCReturnRC (adep.rc());
885
886 AutoLock alock (this);
887
888 /* don't do anything if we're already internal network attached */
889 if (mData->mAttachmentType != NetworkAttachmentType_InternalNetworkAttachment)
890 {
891 mData.backup();
892
893 /* first detach the current attachment */
894 detach();
895
896 /* there must an internal network name */
897 if ( !mData->mInternalNetwork
898 || (mData->mInternalNetwork == Bstr ("")))
899 {
900 LogRel (("Internal network name not defined, "
901 "setting to default \"intnet\"\n"));
902 mData->mInternalNetwork = Bstr ("intnet");
903 }
904
905 mData->mAttachmentType = NetworkAttachmentType_InternalNetworkAttachment;
906
907 /* leave the lock before informing callbacks */
908 alock.unlock();
909
910 mParent->onNetworkAdapterChange (this);
911 }
912
913 return S_OK;
914}
915
916STDMETHODIMP NetworkAdapter::Detach()
917{
918 AutoCaller autoCaller (this);
919 CheckComRCReturnRC (autoCaller.rc());
920
921 /* the machine needs to be mutable */
922 Machine::AutoMutableStateDependency adep (mParent);
923 CheckComRCReturnRC (adep.rc());
924
925 AutoLock alock (this);
926
927 if (mData->mAttachmentType != NetworkAttachmentType_NoNetworkAttachment)
928 {
929 mData.backup();
930
931 detach();
932
933 /* leave the lock before informing callbacks */
934 alock.unlock();
935
936 mParent->onNetworkAdapterChange (this);
937 }
938
939 return S_OK;
940}
941
942// public methods only for internal purposes
943////////////////////////////////////////////////////////////////////////////////
944
945/**
946 * @note Locks this object for writing.
947 */
948bool NetworkAdapter::rollback()
949{
950 /* sanity */
951 AutoCaller autoCaller (this);
952 AssertComRCReturn (autoCaller.rc(), false);
953
954 AutoLock alock (this);
955
956 bool changed = false;
957
958 if (mData.isBackedUp())
959 {
960 /* we need to check all data to see whether anything will be changed
961 * after rollback */
962 changed = mData.hasActualChanges();
963 mData.rollback();
964 }
965
966 return changed;
967}
968
969/**
970 * @note Locks this object for writing, together with the peer object (also
971 * for writing) if there is one.
972 */
973void NetworkAdapter::commit()
974{
975 /* sanity */
976 AutoCaller autoCaller (this);
977 AssertComRCReturnVoid (autoCaller.rc());
978
979 /* sanity too */
980 AutoCaller thatCaller (mPeer);
981 AssertComRCReturnVoid (thatCaller.rc());
982
983 /* lock both for writing since we modify both */
984 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
985
986 if (mData.isBackedUp())
987 {
988 mData.commit();
989 if (mPeer)
990 {
991 /* attach new data to the peer and reshare it */
992 mPeer->mData.attach (mData);
993 }
994 }
995}
996
997/**
998 * @note Locks this object for writing, together with the peer object
999 * represented by @a aThat (locked for reading).
1000 */
1001void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1002{
1003 AssertReturnVoid (aThat != NULL);
1004
1005 /* sanity */
1006 AutoCaller autoCaller (this);
1007 AssertComRCReturnVoid (autoCaller.rc());
1008
1009 /* sanity too */
1010 AutoCaller thatCaller (mPeer);
1011 AssertComRCReturnVoid (thatCaller.rc());
1012
1013 /* peer is not modified, lock it for reading */
1014 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
1015
1016 /* this will back up current data */
1017 mData.assignCopy (aThat->mData);
1018}
1019
1020// private methods
1021////////////////////////////////////////////////////////////////////////////////
1022
1023/**
1024 * Worker routine for detach handling. No locking, no notifications.
1025
1026 * @note Must be called from under the object's write lock.
1027 */
1028void NetworkAdapter::detach()
1029{
1030 AssertReturnVoid (isLockedOnCurrentThread());
1031
1032 switch (mData->mAttachmentType)
1033 {
1034 case NetworkAttachmentType_NoNetworkAttachment:
1035 {
1036 /* nothing to do here */
1037 break;
1038 }
1039 case NetworkAttachmentType_NATNetworkAttachment:
1040 {
1041 break;
1042 }
1043 case NetworkAttachmentType_HostInterfaceNetworkAttachment:
1044 {
1045 /* reset handle and device name */
1046#ifdef RT_OS_WINDOWS
1047 mData->mHostInterface = "";
1048#endif
1049#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
1050 mData->mHostInterface.setNull();
1051 mData->mTAPFD = NIL_RTFILE;
1052#endif
1053 break;
1054 }
1055 case NetworkAttachmentType_InternalNetworkAttachment:
1056 {
1057 mData->mInternalNetwork.setNull();
1058 break;
1059 }
1060 }
1061
1062 mData->mAttachmentType = NetworkAttachmentType_NoNetworkAttachment;
1063}
1064
1065/**
1066 * Generates a new unique MAC address based on our vendor ID and
1067 * parts of a GUID.
1068 *
1069 * @note Must be called from under the object's write lock or within the init
1070 * span.
1071 */
1072void NetworkAdapter::generateMACAddress()
1073{
1074 /*
1075 * Our strategy is as follows: the first three bytes are our fixed
1076 * vendor ID (080027). The remaining 3 bytes will be taken from the
1077 * start of a GUID. This is a fairly safe algorithm.
1078 */
1079 char strMAC[13];
1080 Guid guid;
1081 guid.create();
1082 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1083 guid.ptr()->au8[0], guid.ptr()->au8[1], guid.ptr()->au8[2]);
1084 LogFlowThisFunc (("generated MAC: '%s'\n", strMAC));
1085 mData->mMACAddress = strMAC;
1086}
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