VirtualBox

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

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

Main: Bstr makeover -- make Bstr(NULL) and Bstr() behave the same; resulting cleanup; make some more internal methods use Utf8Str instead of Bstr; fix a lot of CheckComArgNotNull() usage

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