VirtualBox

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

Last change on this file since 54474 was 51498, checked in by vboxsync, 10 years ago

6813 - MachineImpl use of server side wrappers + misc mods on other classes

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