VirtualBox

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

Last change on this file since 26156 was 26046, checked in by vboxsync, 15 years ago

Main: move Auto*StateDependency templates out of MachineImpl.h

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