VirtualBox

source: vbox/trunk/src/VBox/Main/NATEngineImpl.cpp@ 28800

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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