VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/NATEngineImpl.cpp@ 57694

最後變更 在這個檔案從57694是 57694,由 vboxsync 提交於 10 年 前

Main/NATEngine+NetworkAdapter: NetworkAdapter::i_copyFrom didn't update the NATEngine settings, which lacked the corresponding logic entirely and had totally incorrect commit/rollback handling for the settings. The NATEngine commit method was called from the wrong place and rollback was never called. The NATEngine code for updating the port forwarding rules was done ignoring the commit/rollback handling for no good reason, which was covered up by a number of hacks. Eliminated the error prone separate m_fModified flags.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 17.4 KB
 
1/* $Id: NATEngineImpl.cpp 57694 2015-09-10 16:35:59Z vboxsync $ */
2/** @file
3 * Implementation of INATEngine in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2010-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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
18#include "NATEngineImpl.h"
19#include "AutoCaller.h"
20#include "Logging.h"
21#include "MachineImpl.h"
22#include "GuestOSTypeImpl.h"
23
24#include <iprt/string.h>
25#include <iprt/cpp/utils.h>
26
27#include <VBox/err.h>
28#include <VBox/settings.h>
29#include <VBox/com/array.h>
30
31typedef std::map<Utf8Str, settings::NATRule> NATRuleMap;
32
33struct NATEngineData
34{
35 NATEngineData() : mMtu(0),
36 mSockRcv(0),
37 mSockSnd(0),
38 mTcpRcv(0),
39 mTcpSnd(0),
40 mDNSPassDomain(TRUE),
41 mDNSProxy(FALSE),
42 mDNSUseHostResolver(FALSE),
43 mAliasMode(0)
44 {}
45
46 com::Utf8Str mNetwork;
47 com::Utf8Str mBindIP;
48 uint32_t mMtu;
49 uint32_t mSockRcv;
50 uint32_t mSockSnd;
51 uint32_t mTcpRcv;
52 uint32_t mTcpSnd;
53 /* TFTP service */
54 Utf8Str mTFTPPrefix;
55 Utf8Str mTFTPBootFile;
56 Utf8Str mTFTPNextServer;
57 /* DNS service */
58 BOOL mDNSPassDomain;
59 BOOL mDNSProxy;
60 BOOL mDNSUseHostResolver;
61 /* Alias service */
62 ULONG mAliasMode;
63 /* Port forwarding rules */
64 NATRuleMap mNATRules;
65};
66
67struct NATEngine::Data
68{
69 Backupable<NATEngineData> m;
70};
71
72
73// constructor / destructor
74////////////////////////////////////////////////////////////////////////////////
75
76NATEngine::NATEngine():mData(NULL), mParent(NULL), mAdapter(NULL) {}
77NATEngine::~NATEngine(){}
78
79HRESULT NATEngine::FinalConstruct()
80{
81 return BaseFinalConstruct();
82}
83
84void NATEngine::FinalRelease()
85{
86 uninit();
87 BaseFinalRelease();
88}
89
90
91HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter)
92{
93 AutoInitSpan autoInitSpan(this);
94 AssertReturn(autoInitSpan.isOk(), E_FAIL);
95 autoInitSpan.setSucceeded();
96 mData = new Data();
97 mData->m.allocate();
98 mData->m->mNetwork.setNull();
99 mData->m->mBindIP.setNull();
100 unconst(mParent) = aParent;
101 unconst(mAdapter) = aAdapter;
102 return S_OK;
103}
104
105HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
106{
107 AutoInitSpan autoInitSpan(this);
108 AssertReturn(autoInitSpan.isOk(), E_FAIL);
109 Log(("init that:%p this:%p\n", aThat, this));
110
111 AutoCaller thatCaller(aThat);
112 AssertComRCReturnRC(thatCaller.rc());
113
114 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
115
116 mData = new Data();
117 mData->m.share(aThat->mData->m);
118 unconst(mParent) = aParent;
119 unconst(mAdapter) = aAdapter;
120 unconst(mPeer) = aThat;
121 autoInitSpan.setSucceeded();
122 return S_OK;
123}
124
125HRESULT NATEngine::initCopy(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
126{
127 AutoInitSpan autoInitSpan(this);
128 AssertReturn(autoInitSpan.isOk(), E_FAIL);
129
130 Log(("initCopy that:%p this:%p\n", aThat, this));
131
132 AutoCaller thatCaller(aThat);
133 AssertComRCReturnRC(thatCaller.rc());
134
135 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
136
137 mData = new Data();
138 mData->m.attachCopy(aThat->mData->m);
139 unconst(mAdapter) = aAdapter;
140 unconst(mParent) = aParent;
141 autoInitSpan.setSucceeded();
142 return BaseFinalConstruct();
143}
144
145
146void NATEngine::uninit()
147{
148 AutoUninitSpan autoUninitSpan(this);
149 if (autoUninitSpan.uninitDone())
150 return;
151
152 mData->m.free();
153 delete mData;
154 mData = NULL;
155 unconst(mPeer) = NULL;
156 unconst(mParent) = NULL;
157}
158
159bool NATEngine::i_isModified()
160{
161 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
162 bool fModified = mData->m.isBackedUp();
163 return fModified;
164}
165
166void NATEngine::i_rollback()
167{
168 AutoCaller autoCaller(this);
169 AssertComRCReturnVoid(autoCaller.rc());
170
171 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
172
173 mData->m.rollback();
174}
175
176void NATEngine::i_commit()
177{
178 AutoCaller autoCaller(this);
179 AssertComRCReturnVoid(autoCaller.rc());
180
181 /* sanity too */
182 AutoCaller peerCaller(mPeer);
183 AssertComRCReturnVoid(peerCaller.rc());
184
185 /* lock both for writing since we modify both (mPeer is "master" so locked
186 * first) */
187 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
188 if (mData->m.isBackedUp())
189 {
190 mData->m.commit();
191 if (mPeer)
192 mPeer->mData->m.attach(mData->m);
193 }
194}
195
196void NATEngine::i_copyFrom(NATEngine *aThat)
197{
198 AssertReturnVoid(aThat != NULL);
199
200 /* sanity */
201 AutoCaller autoCaller(this);
202 AssertComRCReturnVoid(autoCaller.rc());
203
204 /* sanity too */
205 AutoCaller thatCaller(aThat);
206 AssertComRCReturnVoid(thatCaller.rc());
207
208 /* peer is not modified, lock it for reading (aThat is "master" so locked
209 * first) */
210 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
211 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
212
213 /* this will back up current data */
214 mData->m.assignCopy(aThat->mData->m);
215}
216
217HRESULT NATEngine::getNetworkSettings(ULONG *aMtu, ULONG *aSockSnd, ULONG *aSockRcv, ULONG *aTcpWndSnd, ULONG *aTcpWndRcv)
218{
219 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
220 if (aMtu)
221 *aMtu = mData->m->mMtu;
222 if (aSockSnd)
223 *aSockSnd = mData->m->mSockSnd;
224 if (aSockRcv)
225 *aSockRcv = mData->m->mSockRcv;
226 if (aTcpWndSnd)
227 *aTcpWndSnd = mData->m->mTcpSnd;
228 if (aTcpWndRcv)
229 *aTcpWndRcv = mData->m->mTcpRcv;
230
231 return S_OK;
232}
233
234HRESULT NATEngine::setNetworkSettings(ULONG aMtu, ULONG aSockSnd, ULONG aSockRcv, ULONG aTcpWndSnd, ULONG aTcpWndRcv)
235{
236 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
237 if ( aMtu || aSockSnd || aSockRcv
238 || aTcpWndSnd || aTcpWndRcv)
239 {
240 mData->m.backup();
241 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
242 }
243 if (aMtu)
244 mData->m->mMtu = aMtu;
245 if (aSockSnd)
246 mData->m->mSockSnd = aSockSnd;
247 if (aSockRcv)
248 mData->m->mSockRcv = aSockSnd;
249 if (aTcpWndSnd)
250 mData->m->mTcpSnd = aTcpWndSnd;
251 if (aTcpWndRcv)
252 mData->m->mTcpRcv = aTcpWndRcv;
253
254 return S_OK;
255}
256
257
258HRESULT NATEngine::getRedirects(std::vector<com::Utf8Str> &aRedirects)
259{
260 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
261
262 aRedirects.resize(mData->m->mNATRules.size());
263 size_t i = 0;
264 NATRuleMap::const_iterator it;
265 for (it = mData->m->mNATRules.begin(); it != mData->m->mNATRules.end(); ++it, ++i)
266 {
267 settings::NATRule r = it->second;
268 aRedirects[i] = Utf8StrFmt("%s,%d,%s,%d,%s,%d",
269 r.strName.c_str(),
270 r.proto,
271 r.strHostIP.c_str(),
272 r.u16HostPort,
273 r.strGuestIP.c_str(),
274 r.u16GuestPort);
275 }
276 return S_OK;
277}
278
279HRESULT NATEngine::addRedirect(const com::Utf8Str &aName, NATProtocol_T aProto, const com::Utf8Str &aHostIP,
280 USHORT aHostPort, const com::Utf8Str &aGuestIP, USHORT aGuestPort)
281{
282 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
283 Utf8Str name = aName;
284 settings::NATRule r;
285 const char *proto;
286 switch (aProto)
287 {
288 case NATProtocol_TCP:
289 proto = "tcp";
290 break;
291 case NATProtocol_UDP:
292 proto = "udp";
293 break;
294 default:
295 return E_INVALIDARG;
296 }
297 if (name.isEmpty())
298 name = Utf8StrFmt("%s_%d_%d", proto, aHostPort, aGuestPort);
299
300 NATRuleMap::iterator it;
301 for (it = mData->m->mNATRules.begin(); it != mData->m->mNATRules.end(); ++it)
302 {
303 r = it->second;
304 if (it->first == name)
305 return setError(E_INVALIDARG,
306 tr("A NAT rule of this name already exists"));
307 if ( r.strHostIP == aHostIP
308 && r.u16HostPort == aHostPort
309 && r.proto == aProto)
310 return setError(E_INVALIDARG,
311 tr("A NAT rule for this host port and this host IP already exists"));
312 }
313
314 mData->m.backup();
315 r.strName = name.c_str();
316 r.proto = aProto;
317 r.strHostIP = aHostIP;
318 r.u16HostPort = aHostPort;
319 r.strGuestIP = aGuestIP;
320 r.u16GuestPort = aGuestPort;
321 mData->m->mNATRules.insert(std::make_pair(name, r));
322 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
323
324 ULONG ulSlot;
325 mAdapter->COMGETTER(Slot)(&ulSlot);
326
327 alock.release();
328 mParent->i_onNATRedirectRuleChange(ulSlot, FALSE, Bstr(name).raw(), aProto, Bstr(r.strHostIP).raw(),
329 r.u16HostPort, Bstr(r.strGuestIP).raw(), r.u16GuestPort);
330 return S_OK;
331}
332
333HRESULT NATEngine::removeRedirect(const com::Utf8Str &aName)
334{
335 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
336 NATRuleMap::iterator it = mData->m->mNATRules.find(aName);
337 if (it == mData->m->mNATRules.end())
338 return E_INVALIDARG;
339 mData->m.backup();
340 settings::NATRule r = it->second;
341 Utf8Str strHostIP = r.strHostIP;
342 Utf8Str strGuestIP = r.strGuestIP;
343 NATProtocol_T proto = r.proto;
344 uint16_t u16HostPort = r.u16HostPort;
345 uint16_t u16GuestPort = r.u16GuestPort;
346 ULONG ulSlot;
347 mAdapter->COMGETTER(Slot)(&ulSlot);
348
349 mData->m->mNATRules.erase(it);
350 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
351 alock.release();
352 mParent->i_onNATRedirectRuleChange(ulSlot, TRUE, Bstr(aName).raw(), proto, Bstr(strHostIP).raw(),
353 u16HostPort, Bstr(strGuestIP).raw(), u16GuestPort);
354 return S_OK;
355}
356
357HRESULT NATEngine::i_loadSettings(const settings::NAT &data)
358{
359 AutoCaller autoCaller(this);
360 AssertComRCReturnRC(autoCaller.rc());
361
362 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
363 HRESULT rc = S_OK;
364 mData->m->mNetwork = data.strNetwork;
365 mData->m->mBindIP = data.strBindIP;
366 mData->m->mMtu = data.u32Mtu;
367 mData->m->mSockSnd = data.u32SockSnd;
368 mData->m->mTcpRcv = data.u32TcpRcv;
369 mData->m->mTcpSnd = data.u32TcpSnd;
370 /* TFTP */
371 mData->m->mTFTPPrefix = data.strTFTPPrefix;
372 mData->m->mTFTPBootFile = data.strTFTPBootFile;
373 mData->m->mTFTPNextServer = data.strTFTPNextServer;
374 /* DNS */
375 mData->m->mDNSPassDomain = data.fDNSPassDomain;
376 mData->m->mDNSProxy = data.fDNSProxy;
377 mData->m->mDNSUseHostResolver = data.fDNSUseHostResolver;
378 /* Alias */
379 mData->m->mAliasMode = (data.fAliasUseSamePorts ? NATAliasMode_AliasUseSamePorts : 0);
380 mData->m->mAliasMode |= (data.fAliasLog ? NATAliasMode_AliasLog : 0);
381 mData->m->mAliasMode |= (data.fAliasProxyOnly ? NATAliasMode_AliasProxyOnly : 0);
382 /* port forwarding */
383 mData->m->mNATRules.clear();
384 for (settings::NATRuleList::const_iterator it = data.llRules.begin();
385 it != data.llRules.end(); ++it)
386 {
387 mData->m->mNATRules.insert(std::make_pair(it->strName, *it));
388 }
389 return rc;
390}
391
392
393HRESULT NATEngine::i_saveSettings(settings::NAT &data)
394{
395 AutoCaller autoCaller(this);
396 AssertComRCReturnRC(autoCaller.rc());
397
398 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
399 HRESULT rc = S_OK;
400 data.strNetwork = mData->m->mNetwork;
401 data.strBindIP = mData->m->mBindIP;
402 data.u32Mtu = mData->m->mMtu;
403 data.u32SockRcv = mData->m->mSockRcv;
404 data.u32SockSnd = mData->m->mSockSnd;
405 data.u32TcpRcv = mData->m->mTcpRcv;
406 data.u32TcpSnd = mData->m->mTcpSnd;
407 /* TFTP */
408 data.strTFTPPrefix = mData->m->mTFTPPrefix;
409 data.strTFTPBootFile = mData->m->mTFTPBootFile;
410 data.strTFTPNextServer = mData->m->mTFTPNextServer;
411 /* DNS */
412 data.fDNSPassDomain = !!mData->m->mDNSPassDomain;
413 data.fDNSProxy = !!mData->m->mDNSProxy;
414 data.fDNSUseHostResolver = !!mData->m->mDNSUseHostResolver;
415 /* Alias */
416 data.fAliasLog = !!(mData->m->mAliasMode & NATAliasMode_AliasLog);
417 data.fAliasProxyOnly = !!(mData->m->mAliasMode & NATAliasMode_AliasProxyOnly);
418 data.fAliasUseSamePorts = !!(mData->m->mAliasMode & NATAliasMode_AliasUseSamePorts);
419
420 for (NATRuleMap::iterator it = mData->m->mNATRules.begin();
421 it != mData->m->mNATRules.end(); ++it)
422 data.llRules.push_back(it->second);
423 return rc;
424}
425
426HRESULT NATEngine::setNetwork(const com::Utf8Str &aNetwork)
427{
428 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
429 if (Bstr(mData->m->mNetwork) != aNetwork)
430 {
431 mData->m.backup();
432 mData->m->mNetwork = aNetwork;
433 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
434 }
435 return S_OK;
436}
437
438
439HRESULT NATEngine::getNetwork(com::Utf8Str &aNetwork)
440{
441 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
442 if (!mData->m->mNetwork.isEmpty())
443 {
444 aNetwork = mData->m->mNetwork;
445 Log(("Getter (this:%p) Network: %s\n", this, mData->m->mNetwork.c_str()));
446 }
447 return S_OK;
448}
449
450HRESULT NATEngine::setHostIP(const com::Utf8Str &aHostIP)
451{
452 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
453 if (Bstr(mData->m->mBindIP) != aHostIP)
454 {
455 mData->m.backup();
456 mData->m->mBindIP = aHostIP;
457 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
458 }
459 return S_OK;
460}
461
462HRESULT NATEngine::getHostIP(com::Utf8Str &aBindIP)
463{
464 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
465
466 if (!mData->m->mBindIP.isEmpty())
467 aBindIP = mData->m->mBindIP;
468 return S_OK;
469}
470
471HRESULT NATEngine::setTFTPPrefix(const com::Utf8Str &aTFTPPrefix)
472{
473 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
474 if (Bstr(mData->m->mTFTPPrefix) != aTFTPPrefix)
475 {
476 mData->m.backup();
477 mData->m->mTFTPPrefix = aTFTPPrefix;
478 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
479 }
480 return S_OK;
481}
482
483
484HRESULT NATEngine::getTFTPPrefix(com::Utf8Str &aTFTPPrefix)
485{
486 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
487
488 if (!mData->m->mTFTPPrefix.isEmpty())
489 {
490 aTFTPPrefix = mData->m->mTFTPPrefix;
491 Log(("Getter (this:%p) TFTPPrefix: %s\n", this, mData->m->mTFTPPrefix.c_str()));
492 }
493 return S_OK;
494}
495
496HRESULT NATEngine::setTFTPBootFile(const com::Utf8Str &aTFTPBootFile)
497{
498 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
499 if (Bstr(mData->m->mTFTPBootFile) != aTFTPBootFile)
500 {
501 mData->m.backup();
502 mData->m->mTFTPBootFile = aTFTPBootFile;
503 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
504 }
505 return S_OK;
506}
507
508
509HRESULT NATEngine::getTFTPBootFile(com::Utf8Str &aTFTPBootFile)
510{
511 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
512 if (!mData->m->mTFTPBootFile.isEmpty())
513 {
514 aTFTPBootFile = mData->m->mTFTPBootFile;
515 Log(("Getter (this:%p) BootFile: %s\n", this, mData->m->mTFTPBootFile.c_str()));
516 }
517 return S_OK;
518}
519
520
521HRESULT NATEngine::setTFTPNextServer(const com::Utf8Str &aTFTPNextServer)
522{
523 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
524 if (Bstr(mData->m->mTFTPNextServer) != aTFTPNextServer)
525 {
526 mData->m.backup();
527 mData->m->mTFTPNextServer = aTFTPNextServer;
528 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
529 }
530 return S_OK;
531}
532
533HRESULT NATEngine::getTFTPNextServer(com::Utf8Str &aTFTPNextServer)
534{
535 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
536 if (!mData->m->mTFTPNextServer.isEmpty())
537 {
538 aTFTPNextServer = mData->m->mTFTPNextServer;
539 Log(("Getter (this:%p) NextServer: %s\n", this, mData->m->mTFTPNextServer.c_str()));
540 }
541 return S_OK;
542}
543
544/* DNS */
545HRESULT NATEngine::setDNSPassDomain(BOOL aDNSPassDomain)
546{
547 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
548
549 if (mData->m->mDNSPassDomain != aDNSPassDomain)
550 {
551 mData->m.backup();
552 mData->m->mDNSPassDomain = aDNSPassDomain;
553 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
554 }
555 return S_OK;
556}
557
558HRESULT NATEngine::getDNSPassDomain(BOOL *aDNSPassDomain)
559{
560 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
561 *aDNSPassDomain = mData->m->mDNSPassDomain;
562 return S_OK;
563}
564
565
566HRESULT NATEngine::setDNSProxy(BOOL aDNSProxy)
567{
568 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
569
570 if (mData->m->mDNSProxy != aDNSProxy)
571 {
572 mData->m.backup();
573 mData->m->mDNSProxy = aDNSProxy;
574 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
575 }
576 return S_OK;
577}
578
579HRESULT NATEngine::getDNSProxy(BOOL *aDNSProxy)
580{
581 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
582 *aDNSProxy = mData->m->mDNSProxy;
583 return S_OK;
584}
585
586
587HRESULT NATEngine::getDNSUseHostResolver(BOOL *aDNSUseHostResolver)
588{
589 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
590 *aDNSUseHostResolver = mData->m->mDNSUseHostResolver;
591 return S_OK;
592}
593
594
595HRESULT NATEngine::setDNSUseHostResolver(BOOL aDNSUseHostResolver)
596{
597 if (mData->m->mDNSUseHostResolver != aDNSUseHostResolver)
598 {
599 mData->m.backup();
600 mData->m->mDNSUseHostResolver = aDNSUseHostResolver;
601 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
602 }
603 return S_OK;
604}
605
606HRESULT NATEngine::setAliasMode(ULONG aAliasMode)
607{
608 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
609
610 if (mData->m->mAliasMode != aAliasMode)
611 {
612 mData->m.backup();
613 mData->m->mAliasMode = aAliasMode;
614 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
615 }
616 return S_OK;
617}
618
619HRESULT NATEngine::getAliasMode(ULONG *aAliasMode)
620{
621 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
622 *aAliasMode = mData->m->mAliasMode;
623 return S_OK;
624}
625
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette