VirtualBox

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

Last change on this file since 22292 was 22186, checked in by vboxsync, 15 years ago

Main: fix more windows warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.4 KB
Line 
1/* $Id: NetworkAdapterImpl.cpp 22186 2009-08-11 17:44:54Z vboxsync $ */
2/** @file
3 * Implementation of INetworkAdaptor in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "NetworkAdapterImpl.h"
23#include "Logging.h"
24#include "MachineImpl.h"
25#include "GuestOSTypeImpl.h"
26
27#include <iprt/string.h>
28#include <iprt/cpputils.h>
29
30#include <VBox/err.h>
31#include <VBox/settings.h>
32
33// constructor / destructor
34////////////////////////////////////////////////////////////////////////////////
35
36DEFINE_EMPTY_CTOR_DTOR (NetworkAdapter)
37
38HRESULT NetworkAdapter::FinalConstruct()
39{
40 return S_OK;
41}
42
43void NetworkAdapter::FinalRelease()
44{
45 uninit ();
46}
47
48// public initializer/uninitializer for internal purposes only
49////////////////////////////////////////////////////////////////////////////////
50
51/**
52 * Initializes the network adapter object.
53 *
54 * @param aParent Handle of the parent object.
55 */
56HRESULT NetworkAdapter::init (Machine *aParent, ULONG aSlot)
57{
58 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
59
60 ComAssertRet (aParent, E_INVALIDARG);
61 ComAssertRet (aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
62
63 /* Enclose the state transition NotReady->InInit->Ready */
64 AutoInitSpan autoInitSpan(this);
65 AssertReturn(autoInitSpan.isOk(), E_FAIL);
66
67 unconst(mParent) = aParent;
68 /* mPeer is left null */
69
70 mData.allocate();
71
72 /* initialize data */
73 mData->mSlot = aSlot;
74
75 /* default to Am79C973 */
76 mData->mAdapterType = NetworkAdapterType_Am79C973;
77
78 /* generate the MAC address early to guarantee it is the same both after
79 * changing some other property (i.e. after mData.backup()) and after the
80 * subsequent mData.rollback(). */
81 generateMACAddress();
82
83 /* Confirm a successful initialization */
84 autoInitSpan.setSucceeded();
85
86 return S_OK;
87}
88
89/**
90 * Initializes the network adapter object given another network adapter object
91 * (a kind of copy constructor). This object shares data with
92 * the object passed as an argument.
93 *
94 * @note This object must be destroyed before the original object
95 * it shares data with is destroyed.
96 *
97 * @note Locks @a aThat object for reading.
98 */
99HRESULT NetworkAdapter::init (Machine *aParent, NetworkAdapter *aThat)
100{
101 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
102
103 ComAssertRet (aParent && aThat, E_INVALIDARG);
104
105 /* Enclose the state transition NotReady->InInit->Ready */
106 AutoInitSpan autoInitSpan(this);
107 AssertReturn(autoInitSpan.isOk(), E_FAIL);
108
109 unconst(mParent) = aParent;
110 unconst(mPeer) = aThat;
111
112 AutoCaller thatCaller (aThat);
113 AssertComRCReturnRC(thatCaller.rc());
114
115 AutoReadLock thatLock (aThat);
116 mData.share (aThat->mData);
117
118 /* Confirm a successful initialization */
119 autoInitSpan.setSucceeded();
120
121 return S_OK;
122}
123
124/**
125 * Initializes the guest object given another guest object
126 * (a kind of copy constructor). This object makes a private copy of data
127 * of the original object passed as an argument.
128 *
129 * @note Locks @a aThat object for reading.
130 */
131HRESULT NetworkAdapter::initCopy (Machine *aParent, NetworkAdapter *aThat)
132{
133 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
134
135 ComAssertRet (aParent && aThat, E_INVALIDARG);
136
137 /* Enclose the state transition NotReady->InInit->Ready */
138 AutoInitSpan autoInitSpan(this);
139 AssertReturn(autoInitSpan.isOk(), E_FAIL);
140
141 unconst(mParent) = aParent;
142 /* mPeer is left null */
143
144 AutoCaller thatCaller (aThat);
145 AssertComRCReturnRC(thatCaller.rc());
146
147 AutoReadLock thatLock (aThat);
148 mData.attachCopy (aThat->mData);
149
150 /* Confirm a successful initialization */
151 autoInitSpan.setSucceeded();
152
153 return S_OK;
154}
155
156/**
157 * Uninitializes the instance and sets the ready flag to FALSE.
158 * Called either from FinalRelease() or by the parent when it gets destroyed.
159 */
160void NetworkAdapter::uninit()
161{
162 LogFlowThisFunc(("\n"));
163
164 /* Enclose the state transition Ready->InUninit->NotReady */
165 AutoUninitSpan autoUninitSpan(this);
166 if (autoUninitSpan.uninitDone())
167 return;
168
169 mData.free();
170
171 unconst(mPeer).setNull();
172 unconst(mParent).setNull();
173}
174
175// INetworkAdapter properties
176////////////////////////////////////////////////////////////////////////////////
177
178STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
179{
180 CheckComArgOutPointerValid(aAdapterType);
181
182 AutoCaller autoCaller(this);
183 CheckComRCReturnRC(autoCaller.rc());
184
185 AutoReadLock alock(this);
186
187 *aAdapterType = mData->mAdapterType;
188
189 return S_OK;
190}
191
192STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
193{
194 AutoCaller autoCaller(this);
195 CheckComRCReturnRC(autoCaller.rc());
196
197 /* the machine needs to be mutable */
198 Machine::AutoMutableStateDependency adep (mParent);
199 CheckComRCReturnRC(adep.rc());
200
201 AutoWriteLock alock(this);
202
203 /* make sure the value is allowed */
204 switch (aAdapterType)
205 {
206 case NetworkAdapterType_Am79C970A:
207 case NetworkAdapterType_Am79C973:
208#ifdef VBOX_WITH_E1000
209 case NetworkAdapterType_I82540EM:
210 case NetworkAdapterType_I82543GC:
211 case NetworkAdapterType_I82545EM:
212#endif
213 break;
214 default:
215 return setError (E_FAIL,
216 tr("Invalid network adapter type '%d'"),
217 aAdapterType);
218 }
219
220 if (mData->mAdapterType != aAdapterType)
221 {
222 mData.backup();
223 mData->mAdapterType = aAdapterType;
224
225 /* leave the lock before informing callbacks */
226 alock.unlock();
227
228 mParent->onNetworkAdapterChange (this, FALSE);
229 }
230
231 return S_OK;
232}
233
234STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
235{
236 CheckComArgOutPointerValid(aSlot);
237
238 AutoCaller autoCaller(this);
239 CheckComRCReturnRC(autoCaller.rc());
240
241 AutoReadLock alock(this);
242
243 *aSlot = mData->mSlot;
244
245 return S_OK;
246}
247
248STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
249{
250 CheckComArgOutPointerValid(aEnabled);
251
252 AutoCaller autoCaller(this);
253 CheckComRCReturnRC(autoCaller.rc());
254
255 AutoReadLock alock(this);
256
257 *aEnabled = mData->mEnabled;
258
259 return S_OK;
260}
261
262STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
263{
264 AutoCaller autoCaller(this);
265 CheckComRCReturnRC(autoCaller.rc());
266
267 /* the machine needs to be mutable */
268 Machine::AutoMutableStateDependency adep (mParent);
269 CheckComRCReturnRC(adep.rc());
270
271 AutoWriteLock alock(this);
272
273 if (mData->mEnabled != aEnabled)
274 {
275 mData.backup();
276 mData->mEnabled = aEnabled;
277
278 /* leave the lock before informing callbacks */
279 alock.unlock();
280
281 mParent->onNetworkAdapterChange (this, FALSE);
282 }
283
284 return S_OK;
285}
286
287STDMETHODIMP NetworkAdapter::COMGETTER(MACAddress)(BSTR *aMACAddress)
288{
289 CheckComArgOutPointerValid(aMACAddress);
290
291 AutoCaller autoCaller(this);
292 CheckComRCReturnRC(autoCaller.rc());
293
294 AutoReadLock alock(this);
295
296 ComAssertRet (!!mData->mMACAddress, E_FAIL);
297
298 mData->mMACAddress.cloneTo(aMACAddress);
299
300 return S_OK;
301}
302
303STDMETHODIMP NetworkAdapter::COMSETTER(MACAddress)(IN_BSTR aMACAddress)
304{
305 AutoCaller autoCaller(this);
306 CheckComRCReturnRC(autoCaller.rc());
307
308 /* the machine needs to be mutable */
309 Machine::AutoMutableStateDependency adep (mParent);
310 CheckComRCReturnRC(adep.rc());
311
312 AutoWriteLock alock(this);
313
314 HRESULT rc = S_OK;
315 bool emitChangeEvent = false;
316
317 /*
318 * Are we supposed to generate a MAC?
319 */
320 if (!aMACAddress || !*aMACAddress)
321 {
322 mData.backup();
323
324 generateMACAddress();
325 emitChangeEvent = true;
326 }
327 else
328 {
329 if (mData->mMACAddress != aMACAddress)
330 {
331 /*
332 * Verify given MAC address
333 */
334 Utf8Str macAddressUtf = aMACAddress;
335 char *macAddressStr = macAddressUtf.mutableRaw();
336 int i = 0;
337 while ((i < 13) && macAddressStr && *macAddressStr && (rc == S_OK))
338 {
339 char c = *macAddressStr;
340 /* canonicalize hex digits to capital letters */
341 if (c >= 'a' && c <= 'f')
342 {
343 /** @todo the runtime lacks an ascii lower/upper conv */
344 c &= 0xdf;
345 *macAddressStr = c;
346 }
347 /* we only accept capital letters */
348 if (((c < '0') || (c > '9')) &&
349 ((c < 'A') || (c > 'F')))
350 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
351 /* the second digit must have even value for unicast addresses */
352 if ((i == 1) && (!!(c & 1) == (c >= '0' && c <= '9')))
353 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
354
355 macAddressStr++;
356 i++;
357 }
358 /* we must have parsed exactly 12 characters */
359 if (i != 12)
360 rc = setError(E_INVALIDARG, tr("Invalid MAC address format"));
361
362 if (SUCCEEDED(rc))
363 {
364 mData.backup();
365
366 mData->mMACAddress = macAddressUtf;
367 emitChangeEvent = true;
368 }
369 }
370 }
371
372 if (emitChangeEvent)
373 {
374 /* leave the lock before informing callbacks */
375 alock.unlock();
376
377 mParent->onNetworkAdapterChange (this, FALSE);
378 }
379
380 return rc;
381}
382
383STDMETHODIMP NetworkAdapter::COMGETTER(AttachmentType)(
384 NetworkAttachmentType_T *aAttachmentType)
385{
386 CheckComArgOutPointerValid(aAttachmentType);
387
388 AutoCaller autoCaller(this);
389 CheckComRCReturnRC(autoCaller.rc());
390
391 AutoReadLock alock(this);
392
393 *aAttachmentType = mData->mAttachmentType;
394
395 return S_OK;
396}
397
398STDMETHODIMP NetworkAdapter::COMGETTER(HostInterface)(BSTR *aHostInterface)
399{
400 CheckComArgOutPointerValid(aHostInterface);
401
402 AutoCaller autoCaller(this);
403 CheckComRCReturnRC(autoCaller.rc());
404
405 AutoReadLock alock(this);
406
407 mData->mHostInterface.cloneTo(aHostInterface);
408
409 return S_OK;
410}
411
412STDMETHODIMP NetworkAdapter::COMSETTER(HostInterface)(IN_BSTR aHostInterface)
413{
414 /** @todo Validate input string length. r=dmik: do it in XML schema?*/
415
416 /* we don't allow null strings for the host interface (because the @name
417 * attribute of <HostInterface> must be always present but can be empty). */
418 CheckComArgNotNull (aHostInterface);
419
420 AutoCaller autoCaller(this);
421 CheckComRCReturnRC(autoCaller.rc());
422
423 /* the machine needs to be mutable */
424 Machine::AutoMutableStateDependency adep (mParent);
425 CheckComRCReturnRC(adep.rc());
426
427 AutoWriteLock alock(this);
428
429 if (mData->mHostInterface != aHostInterface)
430 {
431 mData.backup();
432 mData->mHostInterface = aHostInterface;
433
434 /* leave the lock before informing callbacks */
435 alock.unlock();
436
437 mParent->onNetworkAdapterChange (this, FALSE);
438 }
439
440 return S_OK;
441}
442
443STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
444{
445 CheckComArgOutPointerValid(aInternalNetwork);
446
447 AutoCaller autoCaller(this);
448 CheckComRCReturnRC(autoCaller.rc());
449
450 AutoReadLock alock(this);
451
452 mData->mInternalNetwork.cloneTo(aInternalNetwork);
453
454 return S_OK;
455}
456
457STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwork)
458{
459 AutoCaller autoCaller(this);
460 CheckComRCReturnRC(autoCaller.rc());
461
462 /* the machine needs to be mutable */
463 Machine::AutoMutableStateDependency adep (mParent);
464 CheckComRCReturnRC(adep.rc());
465
466 AutoWriteLock alock(this);
467
468 if (mData->mInternalNetwork != aInternalNetwork)
469 {
470 /* if an empty/null string is to be set, internal networking must be
471 * turned off */
472 if ( (aInternalNetwork == NULL || *aInternalNetwork == '\0')
473 && mData->mAttachmentType == NetworkAttachmentType_Internal)
474 {
475 return setError (E_FAIL,
476 tr ("Empty or null internal network name is not valid"));
477 }
478
479 mData.backup();
480 mData->mInternalNetwork = aInternalNetwork;
481
482 /* leave the lock before informing callbacks */
483 alock.unlock();
484
485 mParent->onNetworkAdapterChange (this, FALSE);
486 }
487
488 return S_OK;
489}
490
491STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
492{
493 CheckComArgOutPointerValid(aNATNetwork);
494
495 AutoCaller autoCaller(this);
496 CheckComRCReturnRC(autoCaller.rc());
497
498 AutoReadLock alock(this);
499
500 mData->mNATNetwork.cloneTo(aNATNetwork);
501
502 return S_OK;
503}
504
505STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork)
506{
507 AutoCaller autoCaller(this);
508 CheckComRCReturnRC(autoCaller.rc());
509
510 /* the machine needs to be mutable */
511 Machine::AutoMutableStateDependency adep (mParent);
512 CheckComRCReturnRC(adep.rc());
513
514 AutoWriteLock alock(this);
515
516 if (mData->mNATNetwork != aNATNetwork)
517 {
518 mData.backup();
519 mData->mNATNetwork = aNATNetwork;
520
521 /* leave the lock before informing callbacks */
522 alock.unlock();
523
524 mParent->onNetworkAdapterChange (this, FALSE);
525 }
526
527 return S_OK;
528}
529
530STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
531{
532 CheckComArgOutPointerValid(aConnected);
533
534 AutoCaller autoCaller(this);
535 CheckComRCReturnRC(autoCaller.rc());
536
537 AutoReadLock alock(this);
538
539 *aConnected = mData->mCableConnected;
540
541 return S_OK;
542}
543
544STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
545{
546 AutoCaller autoCaller(this);
547 CheckComRCReturnRC(autoCaller.rc());
548
549 /* the machine needs to be mutable */
550 Machine::AutoMutableStateDependency adep (mParent);
551 CheckComRCReturnRC(adep.rc());
552
553 AutoWriteLock alock(this);
554
555 if (aConnected != mData->mCableConnected)
556 {
557 mData.backup();
558 mData->mCableConnected = aConnected;
559
560 /* leave the lock before informing callbacks */
561 alock.unlock();
562
563 mParent->onNetworkAdapterChange (this, FALSE);
564 }
565
566 return S_OK;
567}
568
569STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
570{
571 CheckComArgOutPointerValid(aSpeed);
572
573 AutoCaller autoCaller(this);
574 CheckComRCReturnRC(autoCaller.rc());
575
576 AutoReadLock alock(this);
577
578 *aSpeed = mData->mLineSpeed;
579
580 return S_OK;
581}
582
583STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
584{
585 AutoCaller autoCaller(this);
586 CheckComRCReturnRC(autoCaller.rc());
587
588 /* the machine needs to be mutable */
589 Machine::AutoMutableStateDependency adep (mParent);
590 CheckComRCReturnRC(adep.rc());
591
592 AutoWriteLock alock(this);
593
594 if (aSpeed != mData->mLineSpeed)
595 {
596 mData.backup();
597 mData->mLineSpeed = aSpeed;
598
599 /* leave the lock before informing callbacks */
600 alock.unlock();
601
602 mParent->onNetworkAdapterChange (this, FALSE);
603 }
604
605 return S_OK;
606}
607
608STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
609{
610 CheckComArgOutPointerValid(aEnabled);
611
612 AutoCaller autoCaller(this);
613 CheckComRCReturnRC(autoCaller.rc());
614
615 AutoReadLock alock(this);
616
617 *aEnabled = mData->mTraceEnabled;
618 return S_OK;
619}
620
621STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
622{
623 AutoCaller autoCaller(this);
624 CheckComRCReturnRC(autoCaller.rc());
625
626 /* the machine needs to be mutable */
627 Machine::AutoMutableStateDependency adep (mParent);
628 CheckComRCReturnRC(adep.rc());
629
630 AutoWriteLock alock(this);
631
632 if (aEnabled != mData->mTraceEnabled)
633 {
634 mData.backup();
635 mData->mTraceEnabled = aEnabled;
636
637 /* leave the lock before informing callbacks */
638 alock.unlock();
639
640 mParent->onNetworkAdapterChange (this, FALSE);
641 }
642
643 return S_OK;
644}
645
646STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
647{
648 CheckComArgOutPointerValid(aTraceFile);
649
650 AutoCaller autoCaller(this);
651 CheckComRCReturnRC(autoCaller.rc());
652
653 AutoReadLock alock(this);
654
655 mData->mTraceFile.cloneTo(aTraceFile);
656
657 return S_OK;
658}
659
660STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
661{
662 AutoCaller autoCaller(this);
663 CheckComRCReturnRC(autoCaller.rc());
664
665 /* the machine needs to be mutable */
666 Machine::AutoMutableStateDependency adep (mParent);
667 CheckComRCReturnRC(adep.rc());
668
669 AutoWriteLock alock(this);
670
671 if (mData->mTraceFile != aTraceFile)
672 {
673 mData.backup();
674 mData->mTraceFile = aTraceFile;
675
676 /* leave the lock before informing callbacks */
677 alock.unlock();
678
679 mParent->onNetworkAdapterChange (this, FALSE);
680 }
681
682 return S_OK;
683}
684
685// INetworkAdapter methods
686////////////////////////////////////////////////////////////////////////////////
687
688STDMETHODIMP NetworkAdapter::AttachToNAT()
689{
690 AutoCaller autoCaller(this);
691 CheckComRCReturnRC(autoCaller.rc());
692
693 /* the machine needs to be mutable */
694 Machine::AutoMutableStateDependency adep (mParent);
695 CheckComRCReturnRC(adep.rc());
696
697 AutoWriteLock alock(this);
698
699 if (mData->mAttachmentType != NetworkAttachmentType_NAT)
700 {
701 mData.backup();
702
703 // Commented this for now as it resets the parameter mData->mNATNetwork
704 // which is essential while changing the Attachment dynamically.
705 //detach();
706
707 mData->mAttachmentType = NetworkAttachmentType_NAT;
708
709 /* leave the lock before informing callbacks */
710 alock.unlock();
711
712 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
713 if (FAILED (rc))
714 {
715 /* If changing the attachment failed then we can't assume
716 * that the previous attachment will attach correctly
717 * and thus return error along with dettaching all
718 * attachments.
719 */
720 Detach();
721 return rc;
722 }
723 }
724
725 return S_OK;
726}
727
728STDMETHODIMP NetworkAdapter::AttachToBridgedInterface()
729{
730 AutoCaller autoCaller(this);
731 CheckComRCReturnRC(autoCaller.rc());
732
733 /* the machine needs to be mutable */
734 Machine::AutoMutableStateDependency adep (mParent);
735 CheckComRCReturnRC(adep.rc());
736
737 AutoWriteLock alock(this);
738
739 /* don't do anything if we're already host interface attached */
740 if (mData->mAttachmentType != NetworkAttachmentType_Bridged)
741 {
742 mData.backup();
743
744 /* first detach the current attachment */
745 // Commented this for now as it reset the parameter mData->mHostInterface
746 // which is essential while changing the Attachment dynamically.
747 //detach();
748
749 mData->mAttachmentType = NetworkAttachmentType_Bridged;
750
751 /* leave the lock before informing callbacks */
752 alock.unlock();
753
754 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
755 if (FAILED (rc))
756 {
757 /* If changing the attachment failed then we can't assume
758 * that the previous attachment will attach correctly
759 * and thus return error along with dettaching all
760 * attachments.
761 */
762 Detach();
763 return rc;
764 }
765 }
766
767 return S_OK;
768}
769
770STDMETHODIMP NetworkAdapter::AttachToInternalNetwork()
771{
772 AutoCaller autoCaller(this);
773 CheckComRCReturnRC(autoCaller.rc());
774
775 /* the machine needs to be mutable */
776 Machine::AutoMutableStateDependency adep (mParent);
777 CheckComRCReturnRC(adep.rc());
778
779 AutoWriteLock alock(this);
780
781 /* don't do anything if we're already internal network attached */
782 if (mData->mAttachmentType != NetworkAttachmentType_Internal)
783 {
784 mData.backup();
785
786 /* first detach the current attachment */
787 // Commented this for now as it reset the parameter mData->mInternalNetwork
788 // which is essential while changing the Attachment dynamically.
789 //detach();
790
791 /* there must an internal network name */
792 if (mData->mInternalNetwork.isEmpty())
793 {
794 LogRel (("Internal network name not defined, "
795 "setting to default \"intnet\"\n"));
796 mData->mInternalNetwork = "intnet";
797 }
798
799 mData->mAttachmentType = NetworkAttachmentType_Internal;
800
801 /* leave the lock before informing callbacks */
802 alock.unlock();
803
804 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
805 if (FAILED (rc))
806 {
807 /* If changing the attachment failed then we can't assume
808 * that the previous attachment will attach correctly
809 * and thus return error along with dettaching all
810 * attachments.
811 */
812 Detach();
813 return rc;
814 }
815 }
816
817 return S_OK;
818}
819
820STDMETHODIMP NetworkAdapter::AttachToHostOnlyInterface()
821{
822 AutoCaller autoCaller(this);
823 CheckComRCReturnRC(autoCaller.rc());
824
825 /* the machine needs to be mutable */
826 Machine::AutoMutableStateDependency adep (mParent);
827 CheckComRCReturnRC(adep.rc());
828
829 AutoWriteLock alock(this);
830
831 /* don't do anything if we're already host interface attached */
832 if (mData->mAttachmentType != NetworkAttachmentType_HostOnly)
833 {
834 mData.backup();
835
836 /* first detach the current attachment */
837 // Commented this for now as it reset the parameter mData->mHostInterface
838 // which is essential while changing the Attachment dynamically.
839 //detach();
840
841 mData->mAttachmentType = NetworkAttachmentType_HostOnly;
842
843 /* leave the lock before informing callbacks */
844 alock.unlock();
845
846 HRESULT rc = mParent->onNetworkAdapterChange (this, TRUE);
847 if (FAILED (rc))
848 {
849 /* If changing the attachment failed then we can't assume
850 * that the previous attachment will attach correctly
851 * and thus return error along with dettaching all
852 * attachments.
853 */
854 Detach();
855 return rc;
856 }
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 AutoWriteLock alock(this);
872
873 if (mData->mAttachmentType != NetworkAttachmentType_Null)
874 {
875 mData.backup();
876
877 detach();
878
879 /* leave the lock before informing callbacks */
880 alock.unlock();
881
882 mParent->onNetworkAdapterChange (this, TRUE);
883 }
884
885 return S_OK;
886}
887
888// public methods only for internal purposes
889////////////////////////////////////////////////////////////////////////////////
890
891/**
892 * Loads settings from the given adapter node.
893 * May be called once right after this object creation.
894 *
895 * @param aAdapterNode <Adapter> node.
896 *
897 * @note Locks this object for writing.
898 */
899HRESULT NetworkAdapter::loadSettings(const settings::NetworkAdapter &data)
900{
901 AutoCaller autoCaller(this);
902 AssertComRCReturnRC(autoCaller.rc());
903
904 AutoWriteLock alock(this);
905
906 /* Note: we assume that the default values for attributes of optional
907 * nodes are assigned in the Data::Data() constructor and don't do it
908 * here. It implies that this method may only be called after constructing
909 * a new BIOSSettings object while all its data fields are in the default
910 * values. Exceptions are fields whose creation time defaults don't match
911 * values that should be applied when these fields are not explicitly set
912 * in the settings file (for backwards compatibility reasons). This takes
913 * place when a setting of a newly created object must default to A while
914 * the same setting of an object loaded from the old settings file must
915 * default to B. */
916
917 HRESULT rc = S_OK;
918
919 mData->mAdapterType = data.type;
920 mData->mEnabled = data.fEnabled;
921 /* MAC address (can be null) */
922 rc = COMSETTER(MACAddress)(Bstr(data.strMACAddress));
923 CheckComRCReturnRC(rc);
924 /* cable (required) */
925 mData->mCableConnected = data.fCableConnected;
926 /* line speed (defaults to 100 Mbps) */
927 mData->mLineSpeed = data.ulLineSpeed;
928 /* tracing (defaults to false) */
929 mData->mTraceEnabled = data.fTraceEnabled;
930 mData->mTraceFile = data.strTraceFile;
931
932 switch (data.mode)
933 {
934 case NetworkAttachmentType_NAT:
935 mData->mNATNetwork = data.strName;
936 rc = AttachToNAT();
937 CheckComRCReturnRC(rc);
938 break;
939
940 case NetworkAttachmentType_Bridged:
941 rc = COMSETTER(HostInterface)(Bstr(data.strName));
942 CheckComRCReturnRC(rc);
943 rc = AttachToBridgedInterface();
944 CheckComRCReturnRC(rc);
945 break;
946
947 case NetworkAttachmentType_Internal:
948 mData->mInternalNetwork = data.strName;
949 Assert(!mData->mInternalNetwork.isNull());
950
951 rc = AttachToInternalNetwork();
952 CheckComRCReturnRC(rc);
953 break;
954
955 case NetworkAttachmentType_HostOnly:
956#if defined(VBOX_WITH_NETFLT)
957 rc = COMSETTER(HostInterface)(Bstr(data.strName));
958 CheckComRCReturnRC(rc);
959#endif
960 rc = AttachToHostOnlyInterface();
961 CheckComRCReturnRC(rc);
962 break;
963
964 case NetworkAttachmentType_Null:
965 rc = Detach();
966 CheckComRCReturnRC(rc);
967 break;
968 }
969
970 return S_OK;
971}
972
973/**
974 * Saves settings to the given adapter node.
975 *
976 * Note that the given Adapter node is comletely empty on input.
977 *
978 * @param aAdapterNode <Adapter> node.
979 *
980 * @note Locks this object for reading.
981 */
982HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
983{
984 AutoCaller autoCaller(this);
985 AssertComRCReturnRC(autoCaller.rc());
986
987 AutoReadLock alock(this);
988
989 data.fEnabled = !!mData->mEnabled;
990 data.strMACAddress = mData->mMACAddress;
991 data.fCableConnected = !!mData->mCableConnected;
992
993 data.ulLineSpeed = mData->mLineSpeed;
994
995 data.fTraceEnabled = !!mData->mTraceEnabled;
996
997 data.strTraceFile = mData->mTraceFile;
998
999 data.type = mData->mAdapterType;
1000
1001 switch (data.mode = mData->mAttachmentType)
1002 {
1003 case NetworkAttachmentType_Null:
1004 data.strName.setNull();
1005 break;
1006
1007 case NetworkAttachmentType_NAT:
1008 data.strName = mData->mNATNetwork;
1009 break;
1010
1011 case NetworkAttachmentType_Bridged:
1012 data.strName = mData->mHostInterface;
1013 break;
1014
1015 case NetworkAttachmentType_Internal:
1016 data.strName = mData->mInternalNetwork;
1017 break;
1018
1019 case NetworkAttachmentType_HostOnly:
1020 data.strName = mData->mHostInterface;
1021 break;
1022 }
1023
1024 return S_OK;
1025}
1026
1027/**
1028 * @note Locks this object for writing.
1029 */
1030bool NetworkAdapter::rollback()
1031{
1032 /* sanity */
1033 AutoCaller autoCaller(this);
1034 AssertComRCReturn (autoCaller.rc(), false);
1035
1036 AutoWriteLock alock(this);
1037
1038 bool changed = false;
1039
1040 if (mData.isBackedUp())
1041 {
1042 /* we need to check all data to see whether anything will be changed
1043 * after rollback */
1044 changed = mData.hasActualChanges();
1045 mData.rollback();
1046 }
1047
1048 return changed;
1049}
1050
1051/**
1052 * @note Locks this object for writing, together with the peer object (also
1053 * for writing) if there is one.
1054 */
1055void NetworkAdapter::commit()
1056{
1057 /* sanity */
1058 AutoCaller autoCaller(this);
1059 AssertComRCReturnVoid (autoCaller.rc());
1060
1061 /* sanity too */
1062 AutoCaller peerCaller (mPeer);
1063 AssertComRCReturnVoid (peerCaller.rc());
1064
1065 /* lock both for writing since we modify both (mPeer is "master" so locked
1066 * first) */
1067 AutoMultiWriteLock2 alock (mPeer, this);
1068
1069 if (mData.isBackedUp())
1070 {
1071 mData.commit();
1072 if (mPeer)
1073 {
1074 /* attach new data to the peer and reshare it */
1075 mPeer->mData.attach (mData);
1076 }
1077 }
1078}
1079
1080/**
1081 * @note Locks this object for writing, together with the peer object
1082 * represented by @a aThat (locked for reading).
1083 */
1084void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
1085{
1086 AssertReturnVoid (aThat != NULL);
1087
1088 /* sanity */
1089 AutoCaller autoCaller(this);
1090 AssertComRCReturnVoid (autoCaller.rc());
1091
1092 /* sanity too */
1093 AutoCaller thatCaller (aThat);
1094 AssertComRCReturnVoid (thatCaller.rc());
1095
1096 /* peer is not modified, lock it for reading (aThat is "master" so locked
1097 * first) */
1098 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
1099
1100 /* this will back up current data */
1101 mData.assignCopy (aThat->mData);
1102}
1103
1104void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
1105{
1106 AssertReturnVoid (aOsType != NULL);
1107
1108 /* sanity */
1109 AutoCaller autoCaller(this);
1110 AssertComRCReturnVoid (autoCaller.rc());
1111
1112 AutoWriteLock alock(this);
1113
1114 bool e1000enabled = false;
1115#ifdef VBOX_WITH_E1000
1116 e1000enabled = true;
1117#endif // VBOX_WITH_E1000
1118
1119 NetworkAdapterType_T defaultType = aOsType->networkAdapterType();
1120
1121 /* Set default network adapter for this OS type */
1122 if (defaultType == NetworkAdapterType_I82540EM ||
1123 defaultType == NetworkAdapterType_I82543GC ||
1124 defaultType == NetworkAdapterType_I82545EM)
1125 {
1126 if (e1000enabled) mData->mAdapterType = defaultType;
1127 }
1128 else mData->mAdapterType = defaultType;
1129
1130 /* Enable and connect the first one adapter to the NAT */
1131 if (mData->mSlot == 0)
1132 {
1133 mData->mEnabled = true;
1134 mData->mAttachmentType = NetworkAttachmentType_NAT;
1135 mData->mCableConnected = true;
1136 }
1137}
1138
1139// private methods
1140////////////////////////////////////////////////////////////////////////////////
1141
1142/**
1143 * Worker routine for detach handling. No locking, no notifications.
1144
1145 * @note Must be called from under the object's write lock.
1146 */
1147void NetworkAdapter::detach()
1148{
1149 AssertReturnVoid (isWriteLockOnCurrentThread());
1150
1151 switch (mData->mAttachmentType)
1152 {
1153 case NetworkAttachmentType_Null:
1154 {
1155 /* nothing to do here */
1156 break;
1157 }
1158 case NetworkAttachmentType_NAT:
1159 {
1160 break;
1161 }
1162 case NetworkAttachmentType_Bridged:
1163 {
1164 /* reset handle and device name */
1165 mData->mHostInterface = "";
1166 break;
1167 }
1168 case NetworkAttachmentType_Internal:
1169 {
1170 mData->mInternalNetwork.setNull();
1171 break;
1172 }
1173 case NetworkAttachmentType_HostOnly:
1174 {
1175#if defined(VBOX_WITH_NETFLT)
1176 /* reset handle and device name */
1177 mData->mHostInterface = "";
1178#endif
1179 break;
1180 }
1181 }
1182
1183 mData->mAttachmentType = NetworkAttachmentType_Null;
1184}
1185
1186/**
1187 * Generates a new unique MAC address based on our vendor ID and
1188 * parts of a GUID.
1189 *
1190 * @note Must be called from under the object's write lock or within the init
1191 * span.
1192 */
1193void NetworkAdapter::generateMACAddress()
1194{
1195 /*
1196 * Our strategy is as follows: the first three bytes are our fixed
1197 * vendor ID (080027). The remaining 3 bytes will be taken from the
1198 * start of a GUID. This is a fairly safe algorithm.
1199 */
1200 char strMAC[13];
1201 Guid guid;
1202 guid.create();
1203 RTStrPrintf (strMAC, sizeof(strMAC), "080027%02X%02X%02X",
1204 guid.ptr()->au8[0], guid.ptr()->au8[1], guid.ptr()->au8[2]);
1205 LogFlowThisFunc(("generated MAC: '%s'\n", strMAC));
1206 mData->mMACAddress = strMAC;
1207}
1208/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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