VirtualBox

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

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

Back out allowing colons in MAC addresses. Getting it right would
require quite some more work (getting omitted leading zeroes right and
doing the multicast/broadcast check correctly).

  • 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 be even for unicast addresses */
345 if ((i == 1) && (c & 1))
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