VirtualBox

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

最後變更 在這個檔案從49871是 49871,由 vboxsync 提交於 11 年 前

6813 - User server side API wrapper code in all interfaces.. stage 4 rev 1

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

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