VirtualBox

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

Last change on this file since 63378 was 61170, checked in by vboxsync, 8 years ago

8238 VBoxSVC settings - NetworkAdapterImpl

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