VirtualBox

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

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

*: scm cleans up whitespace and adds a new line at the end of ApplianceimplPrivate.h.

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