1
/* $Id: NATEngineImpl.cpp 35577 2011-01-16 16:16:19Z vboxsync $ */
3
* Implementation of INATEngine in VBoxSVC.
7
* Copyright (C) 2010 Oracle Corporation
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.
18
#include "NATEngineImpl.h"
19
#include "AutoCaller.h"
21
#include "MachineImpl.h"
22
#include "GuestOSTypeImpl.h"
24
#include <iprt/string.h>
25
#include <iprt/cpp/utils.h>
28
#include <VBox/settings.h>
31
// constructor / destructor
32
////////////////////////////////////////////////////////////////////////////////
34
NATEngine::NATEngine():mParent(NULL), mAdapter(NULL){}
35
NATEngine::~NATEngine(){}
37
HRESULT NATEngine::FinalConstruct()
42
HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter)
44
AutoInitSpan autoInitSpan(this);
45
AssertReturn(autoInitSpan.isOk(), E_FAIL);
46
autoInitSpan.setSucceeded();
49
mData->mNetwork.setNull();
50
mData->mBindIP.setNull();
51
unconst(mParent) = aParent;
52
unconst(mAdapter) = aAdapter;
56
HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
58
AutoInitSpan autoInitSpan(this);
59
AssertReturn(autoInitSpan.isOk(), E_FAIL);
60
Log(("init that:%p this:%p\n", aThat, this));
62
AutoCaller thatCaller (aThat);
63
AssertComRCReturnRC(thatCaller.rc());
65
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
67
mData.share(aThat->mData);
68
NATRuleMap::iterator it;
70
for (it = aThat->mNATRules.begin(); it != aThat->mNATRules.end(); ++it)
72
mNATRules.insert(std::make_pair(it->first, it->second));
74
unconst(mParent) = aParent;
75
unconst(mAdapter) = aAdapter;
76
unconst(mPeer) = aThat;
77
autoInitSpan.setSucceeded();
81
HRESULT NATEngine::initCopy (Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
83
AutoInitSpan autoInitSpan(this);
84
AssertReturn(autoInitSpan.isOk(), E_FAIL);
86
Log(("initCopy that:%p this:%p\n", aThat, this));
88
AutoCaller thatCaller (aThat);
89
AssertComRCReturnRC(thatCaller.rc());
91
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
93
mData.attachCopy(aThat->mData);
94
NATRuleMap::iterator it;
96
for (it = aThat->mNATRules.begin(); it != aThat->mNATRules.end(); ++it)
98
mNATRules.insert(std::make_pair(it->first, it->second));
100
unconst(mAdapter) = aAdapter;
101
unconst(mParent) = aParent;
102
autoInitSpan.setSucceeded();
107
void NATEngine::FinalRelease()
112
void NATEngine::uninit()
114
AutoUninitSpan autoUninitSpan(this);
115
if (autoUninitSpan.uninitDone())
120
unconst(mPeer) = NULL;
121
unconst(mParent) = NULL;
124
bool NATEngine::isModified()
126
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
127
bool fModified = m_fModified;
131
bool NATEngine::rollback()
133
AutoCaller autoCaller(this);
134
AssertComRCReturn (autoCaller.rc(), false);
136
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
137
bool fChanged = m_fModified;
141
/* we need to check all data to see whether anything will be changed
149
void NATEngine::commit()
151
AutoCaller autoCaller(this);
152
AssertComRCReturnVoid (autoCaller.rc());
155
AutoCaller peerCaller (mPeer);
156
AssertComRCReturnVoid (peerCaller.rc());
158
/* lock both for writing since we modify both (mPeer is "master" so locked
160
AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
166
mPeer->mData.attach (mData);
167
mPeer->mNATRules.clear();
168
NATRuleMap::iterator it;
169
for (it = mNATRules.begin(); it != mNATRules.end(); ++it)
171
mPeer->mNATRules.insert(std::make_pair(it->first, it->second));
179
NATEngine::GetNetworkSettings(ULONG *aMtu, ULONG *aSockSnd, ULONG *aSockRcv, ULONG *aTcpWndSnd, ULONG *aTcpWndRcv)
181
AutoCaller autoCaller(this);
182
if (FAILED(autoCaller.rc())) return autoCaller.rc();
184
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
188
*aSockSnd = mData->mSockSnd;
190
*aSockRcv = mData->mSockRcv;
192
*aTcpWndSnd = mData->mTcpSnd;
194
*aTcpWndRcv = mData->mTcpRcv;
200
NATEngine::SetNetworkSettings(ULONG aMtu, ULONG aSockSnd, ULONG aSockRcv, ULONG aTcpWndSnd, ULONG aTcpWndRcv)
202
AutoCaller autoCaller(this);
203
if (FAILED(autoCaller.rc())) return autoCaller.rc();
205
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
206
if ( aMtu || aSockSnd || aSockRcv
207
|| aTcpWndSnd || aTcpWndRcv)
215
mData->mSockSnd = aSockSnd;
217
mData->mSockRcv = aSockSnd;
219
mData->mTcpSnd = aTcpWndSnd;
221
mData->mTcpRcv = aTcpWndRcv;
224
mParent->setModified(Machine::IsModified_NetworkAdapters);
229
NATEngine::COMGETTER(Redirects)(ComSafeArrayOut(BSTR , aNatRules))
231
CheckComArgOutSafeArrayPointerValid(aNatRules);
233
AutoCaller autoCaller(this);
234
if (FAILED(autoCaller.rc())) return autoCaller.rc();
236
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
239
SafeArray<BSTR> sf(mNATRules.size());
241
NATRuleMap::const_iterator it;
242
for (it = mNATRules.begin();
243
it != mNATRules.end(); ++it, ++i)
245
settings::NATRule r = it->second;
246
BstrFmt bstr("%s,%d,%s,%d,%s,%d",
251
r.strGuestIP.c_str(),
253
bstr.detachTo(&sf[i]);
255
sf.detachTo(ComSafeArrayOutArg(aNatRules));
261
NATEngine::AddRedirect(IN_BSTR aName, NATProtocol_T aProto, IN_BSTR aBindIp, USHORT aHostPort, IN_BSTR aGuestIP, USHORT aGuestPort)
264
AutoCaller autoCaller(this);
265
if (FAILED(autoCaller.rc())) return autoCaller.rc();
267
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
268
Utf8Str name = aName;
273
case NATProtocol_TCP:
276
case NATProtocol_UDP:
283
name = Utf8StrFmt("%s_%d_%d", proto, aHostPort, aGuestPort);
285
NATRuleMap::iterator it;
286
for (it = mNATRules.begin(); it != mNATRules.end(); ++it)
289
if (it->first == name)
290
return setError(E_INVALIDARG,
291
tr("A NAT rule of this name already exists"));
292
if ( r.strHostIP == Utf8Str(aBindIp)
293
&& r.u16HostPort == aHostPort
294
&& r.proto == aProto)
295
return setError(E_INVALIDARG,
296
tr("A NAT rule for this host port and this host IP already exists"));
299
r.strName = name.c_str();
301
r.strHostIP = aBindIp;
302
r.u16HostPort = aHostPort;
303
r.strGuestIP = aGuestIP;
304
r.u16GuestPort = aGuestPort;
305
mNATRules.insert(std::make_pair(name, r));
306
mParent->setModified(Machine::IsModified_NetworkAdapters);
310
mAdapter->COMGETTER(Slot)(&ulSlot);
313
mParent->onNATRedirectRuleChange(ulSlot, FALSE, Bstr(name).raw(), aProto, Bstr(r.strHostIP).raw(), r.u16HostPort, Bstr(r.strGuestIP).raw(), r.u16GuestPort);
318
NATEngine::RemoveRedirect(IN_BSTR aName)
320
AutoCaller autoCaller(this);
321
if (FAILED(autoCaller.rc())) return autoCaller.rc();
323
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
324
NATRuleMap::iterator it = mNATRules.find(aName);
325
if (it == mNATRules.end())
328
settings::NATRule r = it->second;
329
Utf8Str strHostIP = r.strHostIP;
330
Utf8Str strGuestIP = r.strGuestIP;
331
NATProtocol_T proto = r.proto;
332
uint16_t u16HostPort = r.u16HostPort;
333
uint16_t u16GuestPort = r.u16GuestPort;
335
mAdapter->COMGETTER(Slot)(&ulSlot);
338
mParent->setModified(Machine::IsModified_NetworkAdapters);
341
mParent->onNATRedirectRuleChange(ulSlot, TRUE, aName, proto, Bstr(strHostIP).raw(), u16HostPort, Bstr(strGuestIP).raw(), u16GuestPort);
345
HRESULT NATEngine::loadSettings(const settings::NAT &data)
347
AutoCaller autoCaller(this);
348
AssertComRCReturnRC(autoCaller.rc());
350
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
352
mData->mNetwork = data.strNetwork;
353
mData->mBindIP = data.strBindIP;
354
mData->mMtu = data.u32Mtu;
355
mData->mSockSnd = data.u32SockSnd;
356
mData->mTcpRcv = data.u32TcpRcv;
357
mData->mTcpSnd = data.u32TcpSnd;
359
mData->mTftpPrefix = data.strTftpPrefix;
360
mData->mTftpBootFile = data.strTftpBootFile;
361
mData->mTftpNextServer = data.strTftpNextServer;
363
mData->mDnsPassDomain = data.fDnsPassDomain;
364
mData->mDnsProxy = data.fDnsProxy;
365
mData->mDnsUseHostResolver = data.fDnsUseHostResolver;
367
mData->mAliasMode = (data.fAliasUseSamePorts ? NATAliasMode_AliasUseSamePorts : 0);
368
mData->mAliasMode |= (data.fAliasLog ? NATAliasMode_AliasLog : 0);
369
mData->mAliasMode |= (data.fAliasProxyOnly ? NATAliasMode_AliasProxyOnly : 0);
370
/* port forwarding */
372
for (settings::NATRuleList::const_iterator it = data.llRules.begin();
373
it != data.llRules.end(); ++it)
375
mNATRules.insert(std::make_pair(it->strName, *it));
382
HRESULT NATEngine::saveSettings(settings::NAT &data)
384
AutoCaller autoCaller(this);
385
AssertComRCReturnRC(autoCaller.rc());
387
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
389
data.strNetwork = mData->mNetwork;
390
data.strBindIP = mData->mBindIP;
391
data.u32Mtu = mData->mMtu;
392
data.u32SockRcv = mData->mSockRcv;
393
data.u32SockSnd = mData->mSockSnd;
394
data.u32TcpRcv = mData->mTcpRcv;
395
data.u32TcpSnd = mData->mTcpSnd;
397
data.strTftpPrefix = mData->mTftpPrefix;
398
data.strTftpBootFile = mData->mTftpBootFile;
399
data.strTftpNextServer = mData->mTftpNextServer;
401
data.fDnsPassDomain = !!mData->mDnsPassDomain;
402
data.fDnsProxy = !!mData->mDnsProxy;
403
data.fDnsUseHostResolver = !!mData->mDnsUseHostResolver;
405
data.fAliasLog = !!(mData->mAliasMode & NATAliasMode_AliasLog);
406
data.fAliasProxyOnly = !!(mData->mAliasMode & NATAliasMode_AliasProxyOnly);
407
data.fAliasUseSamePorts = !!(mData->mAliasMode & NATAliasMode_AliasUseSamePorts);
409
for (NATRuleMap::iterator it = mNATRules.begin();
410
it != mNATRules.end(); ++it)
411
data.llRules.push_back(it->second);
418
NATEngine::COMSETTER(Network)(IN_BSTR aNetwork)
420
AutoCaller autoCaller(this);
421
AssertComRCReturnRC (autoCaller.rc());
422
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
423
if (Bstr(mData->mNetwork) != aNetwork)
426
mData->mNetwork = aNetwork;
427
mParent->setModified(Machine::IsModified_NetworkAdapters);
434
NATEngine::COMGETTER(Network)(BSTR *aNetwork)
436
CheckComArgNotNull(aNetwork);
437
AutoCaller autoCaller(this);
438
AssertComRCReturnRC(autoCaller.rc());
440
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
441
if (!mData->mNetwork.isEmpty())
443
mData->mNetwork.cloneTo(aNetwork);
444
Log(("Getter (this:%p) Network: %s\n", this, mData->mNetwork.c_str()));
450
NATEngine::COMSETTER(HostIP) (IN_BSTR aBindIP)
452
AutoCaller autoCaller(this);
453
AssertComRCReturnRC (autoCaller.rc());
454
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
455
if (Bstr(mData->mBindIP) != aBindIP)
458
mData->mBindIP = aBindIP;
459
mParent->setModified(Machine::IsModified_NetworkAdapters);
464
STDMETHODIMP NATEngine::COMGETTER(HostIP) (BSTR *aBindIP)
466
AutoCaller autoCaller(this);
467
AssertComRCReturnRC(autoCaller.rc());
469
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
470
if (!mData->mBindIP.isEmpty())
471
mData->mBindIP.cloneTo(aBindIP);
477
NATEngine::COMSETTER(TftpPrefix)(IN_BSTR aTftpPrefix)
479
AutoCaller autoCaller(this);
480
AssertComRCReturnRC (autoCaller.rc());
481
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
482
if (Bstr(mData->mTftpPrefix) != aTftpPrefix)
485
mData->mTftpPrefix = aTftpPrefix;
486
mParent->setModified(Machine::IsModified_NetworkAdapters);
493
NATEngine::COMGETTER(TftpPrefix)(BSTR *aTftpPrefix)
495
AutoCaller autoCaller(this);
496
AssertComRCReturnRC(autoCaller.rc());
498
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
499
if (!mData->mTftpPrefix.isEmpty())
501
mData->mTftpPrefix.cloneTo(aTftpPrefix);
502
Log(("Getter (this:%p) TftpPrefix: %s\n", this, mData->mTftpPrefix.c_str()));
508
NATEngine::COMSETTER(TftpBootFile)(IN_BSTR aTftpBootFile)
510
AutoCaller autoCaller(this);
511
AssertComRCReturnRC (autoCaller.rc());
512
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
513
if (Bstr(mData->mTftpBootFile) != aTftpBootFile)
516
mData->mTftpBootFile = aTftpBootFile;
517
mParent->setModified(Machine::IsModified_NetworkAdapters);
524
NATEngine::COMGETTER(TftpBootFile)(BSTR *aTftpBootFile)
526
AutoCaller autoCaller(this);
527
AssertComRCReturnRC(autoCaller.rc());
529
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
530
if (!mData->mTftpBootFile.isEmpty())
532
mData->mTftpBootFile.cloneTo(aTftpBootFile);
533
Log(("Getter (this:%p) BootFile: %s\n", this, mData->mTftpBootFile.c_str()));
539
NATEngine::COMSETTER(TftpNextServer)(IN_BSTR aTftpNextServer)
541
AutoCaller autoCaller(this);
542
AssertComRCReturnRC (autoCaller.rc());
543
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
544
if (Bstr(mData->mTftpNextServer) != aTftpNextServer)
547
mData->mTftpNextServer = aTftpNextServer;
548
mParent->setModified(Machine::IsModified_NetworkAdapters);
555
NATEngine::COMGETTER(TftpNextServer)(BSTR *aTftpNextServer)
557
AutoCaller autoCaller(this);
558
AssertComRCReturnRC(autoCaller.rc());
560
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
561
if (!mData->mTftpNextServer.isEmpty())
563
mData->mTftpNextServer.cloneTo(aTftpNextServer);
564
Log(("Getter (this:%p) NextServer: %s\n", this, mData->mTftpNextServer.c_str()));
570
NATEngine::COMSETTER(DnsPassDomain) (BOOL aDnsPassDomain)
572
AutoCaller autoCaller(this);
573
AssertComRCReturnRC (autoCaller.rc());
574
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
576
if (mData->mDnsPassDomain != aDnsPassDomain)
579
mData->mDnsPassDomain = aDnsPassDomain;
580
mParent->setModified(Machine::IsModified_NetworkAdapters);
586
NATEngine::COMGETTER(DnsPassDomain)(BOOL *aDnsPassDomain)
588
AutoCaller autoCaller(this);
589
AssertComRCReturnRC(autoCaller.rc());
591
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
592
*aDnsPassDomain = mData->mDnsPassDomain;
596
NATEngine::COMSETTER(DnsProxy)(BOOL aDnsProxy)
598
AutoCaller autoCaller(this);
599
AssertComRCReturnRC (autoCaller.rc());
600
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
602
if (mData->mDnsProxy != aDnsProxy)
605
mData->mDnsProxy = aDnsProxy;
606
mParent->setModified(Machine::IsModified_NetworkAdapters);
612
NATEngine::COMGETTER(DnsProxy)(BOOL *aDnsProxy)
614
AutoCaller autoCaller(this);
615
AssertComRCReturnRC(autoCaller.rc());
617
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
618
*aDnsProxy = mData->mDnsProxy;
622
NATEngine::COMGETTER(DnsUseHostResolver)(BOOL *aDnsUseHostResolver)
624
AutoCaller autoCaller(this);
625
AssertComRCReturnRC (autoCaller.rc());
626
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
627
*aDnsUseHostResolver = mData->mDnsUseHostResolver;
631
NATEngine::COMSETTER(DnsUseHostResolver)(BOOL aDnsUseHostResolver)
633
AutoCaller autoCaller(this);
634
AssertComRCReturnRC(autoCaller.rc());
636
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
638
if (mData->mDnsUseHostResolver != aDnsUseHostResolver)
641
mData->mDnsUseHostResolver = aDnsUseHostResolver;
642
mParent->setModified(Machine::IsModified_NetworkAdapters);
648
STDMETHODIMP NATEngine::COMSETTER(AliasMode) (ULONG aAliasMode)
650
AutoCaller autoCaller(this);
651
AssertComRCReturnRC(autoCaller.rc());
653
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
655
if (mData->mAliasMode != aAliasMode)
658
mData->mAliasMode = aAliasMode;
659
mParent->setModified(Machine::IsModified_NetworkAdapters);
665
STDMETHODIMP NATEngine::COMGETTER(AliasMode) (ULONG *aAliasMode)
667
AutoCaller autoCaller(this);
668
AssertComRCReturnRC (autoCaller.rc());
669
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
670
*aAliasMode = mData->mAliasMode;