VirtualBox

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

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

Main: remove templates for 'weak' com pointers which do nothing anyway

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