VirtualBox

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

Last change on this file since 61127 was 61030, checked in by vboxsync, 9 years ago

Main/NATEngine: do not call BaseFinalConstruct from any method other than FinalConstruct, because otherwise it is done twice, which causes trouble

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

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