VirtualBox

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

Last change on this file since 67954 was 66940, checked in by vboxsync, 7 years ago

Main/NetworkAdapter+NATEngine: Improve default handling (deal with NULL guest OS type), and also add a check if the current settings are default. Note that the API defaults are not the same as the Settings defaults, and that's intentional as the API defaults apply to NICs which the settings didn't read from the config at all.

  • 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 66940 2017-05-17 16:44:04Z 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
182void NATEngine::i_applyDefaults()
183{
184 /* sanity */
185 AutoCaller autoCaller(this);
186 AssertComRCReturnVoid(autoCaller.rc());
187
188 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
189
190 /* so far nothing to do */
191}
192
193bool NATEngine::i_hasDefaults()
194{
195 /* sanity */
196 AutoCaller autoCaller(this);
197 AssertComRCReturn(autoCaller.rc(), true);
198
199 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
200
201 return mData->m->areDefaultSettings();
202}
203
204HRESULT NATEngine::getNetworkSettings(ULONG *aMtu, ULONG *aSockSnd, ULONG *aSockRcv, ULONG *aTcpWndSnd, ULONG *aTcpWndRcv)
205{
206 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
207 if (aMtu)
208 *aMtu = mData->m->u32Mtu;
209 if (aSockSnd)
210 *aSockSnd = mData->m->u32SockSnd;
211 if (aSockRcv)
212 *aSockRcv = mData->m->u32SockRcv;
213 if (aTcpWndSnd)
214 *aTcpWndSnd = mData->m->u32TcpSnd;
215 if (aTcpWndRcv)
216 *aTcpWndRcv = mData->m->u32TcpRcv;
217
218 return S_OK;
219}
220
221HRESULT NATEngine::setNetworkSettings(ULONG aMtu, ULONG aSockSnd, ULONG aSockRcv, ULONG aTcpWndSnd, ULONG aTcpWndRcv)
222{
223 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
224 if ( aMtu || aSockSnd || aSockRcv
225 || aTcpWndSnd || aTcpWndRcv)
226 {
227 mData->m.backup();
228 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
229 }
230 if (aMtu)
231 mData->m->u32Mtu = aMtu;
232 if (aSockSnd)
233 mData->m->u32SockSnd = aSockSnd;
234 if (aSockRcv)
235 mData->m->u32SockRcv = aSockSnd;
236 if (aTcpWndSnd)
237 mData->m->u32TcpSnd = aTcpWndSnd;
238 if (aTcpWndRcv)
239 mData->m->u32TcpRcv = aTcpWndRcv;
240
241 return S_OK;
242}
243
244
245HRESULT NATEngine::getRedirects(std::vector<com::Utf8Str> &aRedirects)
246{
247 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
248
249 aRedirects.resize(mData->m->mapRules.size());
250 size_t i = 0;
251 settings::NATRulesMap::const_iterator it;
252 for (it = mData->m->mapRules.begin(); it != mData->m->mapRules.end(); ++it, ++i)
253 {
254 settings::NATRule r = it->second;
255 aRedirects[i] = Utf8StrFmt("%s,%d,%s,%d,%s,%d",
256 r.strName.c_str(),
257 r.proto,
258 r.strHostIP.c_str(),
259 r.u16HostPort,
260 r.strGuestIP.c_str(),
261 r.u16GuestPort);
262 }
263 return S_OK;
264}
265
266HRESULT NATEngine::addRedirect(const com::Utf8Str &aName, NATProtocol_T aProto, const com::Utf8Str &aHostIP,
267 USHORT aHostPort, const com::Utf8Str &aGuestIP, USHORT aGuestPort)
268{
269 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
270 Utf8Str name = aName;
271 settings::NATRule r;
272 const char *proto;
273 switch (aProto)
274 {
275 case NATProtocol_TCP:
276 proto = "tcp";
277 break;
278 case NATProtocol_UDP:
279 proto = "udp";
280 break;
281 default:
282 return E_INVALIDARG;
283 }
284
285 if (name.isEmpty())
286 name = Utf8StrFmt("%s_%d_%d", proto, aHostPort, aGuestPort);
287 else
288 {
289 const char *s;
290 char c;
291
292 for (s = name.c_str(); (c = *s) != '\0'; ++s)
293 {
294 if (c == ',') /* we use csv in several places e.g. GetRedirects or natpf<N> argument */
295 return setError(E_INVALIDARG,
296 tr("'%c' - invalid character in NAT rule name"), c);
297 }
298 }
299
300 settings::NATRulesMap::iterator it;
301 for (it = mData->m->mapRules.begin(); it != mData->m->mapRules.end(); ++it)
302 {
303 r = it->second;
304 if (it->first == name)
305 return setError(E_INVALIDARG,
306 tr("A NAT rule of this name already exists"));
307 if ( r.strHostIP == aHostIP
308 && r.u16HostPort == aHostPort
309 && r.proto == aProto)
310 return setError(E_INVALIDARG,
311 tr("A NAT rule for this host port and this host IP already exists"));
312 }
313
314 mData->m.backup();
315 r.strName = name.c_str();
316 r.proto = aProto;
317 r.strHostIP = aHostIP;
318 r.u16HostPort = aHostPort;
319 r.strGuestIP = aGuestIP;
320 r.u16GuestPort = aGuestPort;
321 mData->m->mapRules.insert(std::make_pair(name, r));
322 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
323
324 ULONG ulSlot;
325 mAdapter->COMGETTER(Slot)(&ulSlot);
326
327 alock.release();
328 mParent->i_onNATRedirectRuleChange(ulSlot, FALSE, Bstr(name).raw(), aProto, Bstr(r.strHostIP).raw(),
329 r.u16HostPort, Bstr(r.strGuestIP).raw(), r.u16GuestPort);
330 return S_OK;
331}
332
333HRESULT NATEngine::removeRedirect(const com::Utf8Str &aName)
334{
335 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
336 settings::NATRulesMap::iterator it = mData->m->mapRules.find(aName);
337 if (it == mData->m->mapRules.end())
338 return E_INVALIDARG;
339 mData->m.backup();
340 /*
341 * NB: "it" may now point to the backup! In that case it's ok to
342 * get data from the backup copy of s.mapRules via it, but we can't
343 * erase(it) from potentially new s.mapRules.
344 */
345 settings::NATRule r = it->second;
346 ULONG ulSlot;
347 mAdapter->COMGETTER(Slot)(&ulSlot);
348
349 mData->m->mapRules.erase(aName); /* NB: erase by key, "it" may not be valid */
350 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
351 alock.release();
352 mParent->i_onNATRedirectRuleChange(ulSlot, TRUE, Bstr(aName).raw(), r.proto, Bstr(r.strHostIP).raw(),
353 r.u16HostPort, Bstr(r.strGuestIP).raw(), r.u16GuestPort);
354 return S_OK;
355}
356
357HRESULT NATEngine::i_loadSettings(const settings::NAT &data)
358{
359 AutoCaller autoCaller(this);
360 AssertComRCReturnRC(autoCaller.rc());
361
362 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
363 mData->m.assignCopy(&data);
364 return S_OK;
365}
366
367
368HRESULT NATEngine::i_saveSettings(settings::NAT &data)
369{
370 AutoCaller autoCaller(this);
371 AssertComRCReturnRC(autoCaller.rc());
372
373 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
374 HRESULT rc = S_OK;
375 data = *mData->m.data();
376 return rc;
377}
378
379HRESULT NATEngine::setNetwork(const com::Utf8Str &aNetwork)
380{
381 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
382 if (mData->m->strNetwork != aNetwork)
383 {
384 mData->m.backup();
385 mData->m->strNetwork = aNetwork;
386 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
387 }
388 return S_OK;
389}
390
391
392HRESULT NATEngine::getNetwork(com::Utf8Str &aNetwork)
393{
394 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
395 if (!mData->m->strNetwork.isEmpty())
396 {
397 aNetwork = mData->m->strNetwork;
398 Log(("Getter (this:%p) Network: %s\n", this, mData->m->strNetwork.c_str()));
399 }
400 return S_OK;
401}
402
403HRESULT NATEngine::setHostIP(const com::Utf8Str &aHostIP)
404{
405 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
406 if (mData->m->strBindIP != aHostIP)
407 {
408 mData->m.backup();
409 mData->m->strBindIP = aHostIP;
410 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
411 }
412 return S_OK;
413}
414
415HRESULT NATEngine::getHostIP(com::Utf8Str &aBindIP)
416{
417 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
418
419 if (!mData->m->strBindIP.isEmpty())
420 aBindIP = mData->m->strBindIP;
421 return S_OK;
422}
423
424HRESULT NATEngine::setTFTPPrefix(const com::Utf8Str &aTFTPPrefix)
425{
426 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
427 if (mData->m->strTFTPPrefix != aTFTPPrefix)
428 {
429 mData->m.backup();
430 mData->m->strTFTPPrefix = aTFTPPrefix;
431 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
432 }
433 return S_OK;
434}
435
436
437HRESULT NATEngine::getTFTPPrefix(com::Utf8Str &aTFTPPrefix)
438{
439 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
440
441 if (!mData->m->strTFTPPrefix.isEmpty())
442 {
443 aTFTPPrefix = mData->m->strTFTPPrefix;
444 Log(("Getter (this:%p) TFTPPrefix: %s\n", this, mData->m->strTFTPPrefix.c_str()));
445 }
446 return S_OK;
447}
448
449HRESULT NATEngine::setTFTPBootFile(const com::Utf8Str &aTFTPBootFile)
450{
451 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
452 if (mData->m->strTFTPBootFile != aTFTPBootFile)
453 {
454 mData->m.backup();
455 mData->m->strTFTPBootFile = aTFTPBootFile;
456 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
457 }
458 return S_OK;
459}
460
461
462HRESULT NATEngine::getTFTPBootFile(com::Utf8Str &aTFTPBootFile)
463{
464 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
465 if (!mData->m->strTFTPBootFile.isEmpty())
466 {
467 aTFTPBootFile = mData->m->strTFTPBootFile;
468 Log(("Getter (this:%p) BootFile: %s\n", this, mData->m->strTFTPBootFile.c_str()));
469 }
470 return S_OK;
471}
472
473
474HRESULT NATEngine::setTFTPNextServer(const com::Utf8Str &aTFTPNextServer)
475{
476 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
477 if (mData->m->strTFTPNextServer != aTFTPNextServer)
478 {
479 mData->m.backup();
480 mData->m->strTFTPNextServer = aTFTPNextServer;
481 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
482 }
483 return S_OK;
484}
485
486HRESULT NATEngine::getTFTPNextServer(com::Utf8Str &aTFTPNextServer)
487{
488 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
489 if (!mData->m->strTFTPNextServer.isEmpty())
490 {
491 aTFTPNextServer = mData->m->strTFTPNextServer;
492 Log(("Getter (this:%p) NextServer: %s\n", this, mData->m->strTFTPNextServer.c_str()));
493 }
494 return S_OK;
495}
496
497/* DNS */
498HRESULT NATEngine::setDNSPassDomain(BOOL aDNSPassDomain)
499{
500 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
501
502 if (mData->m->fDNSPassDomain != RT_BOOL(aDNSPassDomain))
503 {
504 mData->m.backup();
505 mData->m->fDNSPassDomain = RT_BOOL(aDNSPassDomain);
506 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
507 }
508 return S_OK;
509}
510
511HRESULT NATEngine::getDNSPassDomain(BOOL *aDNSPassDomain)
512{
513 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
514 *aDNSPassDomain = mData->m->fDNSPassDomain;
515 return S_OK;
516}
517
518
519HRESULT NATEngine::setDNSProxy(BOOL aDNSProxy)
520{
521 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
522
523 if (mData->m->fDNSProxy != RT_BOOL(aDNSProxy))
524 {
525 mData->m.backup();
526 mData->m->fDNSProxy = RT_BOOL(aDNSProxy);
527 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
528 }
529 return S_OK;
530}
531
532HRESULT NATEngine::getDNSProxy(BOOL *aDNSProxy)
533{
534 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
535 *aDNSProxy = mData->m->fDNSProxy;
536 return S_OK;
537}
538
539
540HRESULT NATEngine::getDNSUseHostResolver(BOOL *aDNSUseHostResolver)
541{
542 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
543 *aDNSUseHostResolver = mData->m->fDNSUseHostResolver;
544 return S_OK;
545}
546
547
548HRESULT NATEngine::setDNSUseHostResolver(BOOL aDNSUseHostResolver)
549{
550 if (mData->m->fDNSUseHostResolver != RT_BOOL(aDNSUseHostResolver))
551 {
552 mData->m.backup();
553 mData->m->fDNSUseHostResolver = RT_BOOL(aDNSUseHostResolver);
554 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
555 }
556 return S_OK;
557}
558
559HRESULT NATEngine::setAliasMode(ULONG aAliasMode)
560{
561 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
562 ULONG uAliasMode = (mData->m->fAliasUseSamePorts ? NATAliasMode_AliasUseSamePorts : 0);
563 uAliasMode |= (mData->m->fAliasLog ? NATAliasMode_AliasLog : 0);
564 uAliasMode |= (mData->m->fAliasProxyOnly ? NATAliasMode_AliasProxyOnly : 0);
565 if (uAliasMode != aAliasMode)
566 {
567 mData->m.backup();
568 mData->m->fAliasUseSamePorts = RT_BOOL(aAliasMode & NATAliasMode_AliasUseSamePorts);
569 mData->m->fAliasLog = RT_BOOL(aAliasMode & NATAliasMode_AliasLog);
570 mData->m->fAliasProxyOnly = RT_BOOL(aAliasMode & NATAliasMode_AliasProxyOnly);
571 mParent->i_setModified(Machine::IsModified_NetworkAdapters);
572 }
573 return S_OK;
574}
575
576HRESULT NATEngine::getAliasMode(ULONG *aAliasMode)
577{
578 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
579 ULONG uAliasMode = (mData->m->fAliasUseSamePorts ? NATAliasMode_AliasUseSamePorts : 0);
580 uAliasMode |= (mData->m->fAliasLog ? NATAliasMode_AliasLog : 0);
581 uAliasMode |= (mData->m->fAliasProxyOnly ? NATAliasMode_AliasProxyOnly : 0);
582 *aAliasMode = uAliasMode;
583 return S_OK;
584}
585
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