VirtualBox

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

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

Fix incorrect MAC address validity check.

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