VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/NATNetworkImpl.cpp@ 46860

Last change on this file since 46860 was 45559, checked in by vboxsync, 12 years ago

NAT/Lwip-service: Main client now, dynamic port-forward + managment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.1 KB
Line 
1/* $Id: NATNetworkImpl.cpp 45559 2013-04-16 06:11:59Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM class implementation
6 */
7
8/*
9 * Copyright (C) 2013 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include "DHCPServerRunner.h"
21#include "DHCPServerImpl.h"
22#include "NATNetworkImpl.h"
23#include "AutoCaller.h"
24#include "Logging.h"
25
26#include <iprt/asm.h>
27#include <iprt/cpp/utils.h>
28#include <iprt/cidr.h>
29#include <iprt/net.h>
30#include <VBox/com/array.h>
31#include <VBox/com/ptr.h>
32#include <VBox/settings.h>
33
34#include "EventImpl.h"
35#include "VBoxEvents.h"
36
37#include "NATNetworkServiceRunner.h"
38#include "VirtualBoxImpl.h"
39
40
41// constructor / destructor
42/////////////////////////////////////////////////////////////////////////////
43
44struct NATNetwork::Data
45{
46 Data() :
47
48 fEnabled(FALSE),
49 fIPv6Enabled(FALSE),
50 fAdvertiseDefaultIPv6Route(FALSE),
51 fNeedDhcpServer(FALSE)
52 {
53 IPv4Gateway.setNull();
54 IPv4NetworkCidr.setNull();
55 IPv6Prefix.setNull();
56 IPv4DhcpServer.setNull();
57 IPv4NetworkMask.setNull();
58 IPv4DhcpServerLowerIp.setNull();
59 IPv4DhcpServerUpperIp.setNull();
60 }
61 virtual ~Data(){}
62 const ComObjPtr<EventSource> pEventSource;
63#ifdef VBOX_WITH_NAT_SERVICE
64 NATNetworkServiceRunner NATRunner;
65 ComObjPtr<IDHCPServer> dhcpServer;
66#endif
67 Bstr IPv4Gateway;
68 Bstr IPv4NetworkCidr;
69 Bstr IPv4NetworkMask;
70 Bstr IPv4DhcpServer;
71 Bstr IPv4DhcpServerLowerIp;
72 Bstr IPv4DhcpServerUpperIp;
73 BOOL fEnabled;
74 BOOL fIPv6Enabled;
75 Bstr IPv6Prefix;
76 BOOL fAdvertiseDefaultIPv6Route;
77 BOOL fNeedDhcpServer;
78 NATRuleMap mapName2PortForwardRule4;
79 NATRuleMap mapName2PortForwardRule6;
80};
81
82NATNetwork::NATNetwork()
83 : mVirtualBox(NULL)
84{
85}
86
87NATNetwork::~NATNetwork()
88{
89}
90
91HRESULT NATNetwork::FinalConstruct()
92{
93 return BaseFinalConstruct();
94}
95
96void NATNetwork::FinalRelease()
97{
98 uninit ();
99
100 BaseFinalRelease();
101}
102
103void NATNetwork::uninit()
104{
105 /* Enclose the state transition Ready->InUninit->NotReady */
106 AutoUninitSpan autoUninitSpan(this);
107 if (autoUninitSpan.uninitDone())
108 return;
109 delete m;
110 m = NULL;
111 unconst(mVirtualBox) = NULL;
112}
113
114HRESULT NATNetwork::init(VirtualBox *aVirtualBox, IN_BSTR aName)
115{
116 AssertReturn(aName != NULL, E_INVALIDARG);
117
118 AutoInitSpan autoInitSpan(this);
119 AssertReturn(autoInitSpan.isOk(), E_FAIL);
120
121 /* share VirtualBox weakly (parent remains NULL so far) */
122 unconst(mVirtualBox) = aVirtualBox;
123 unconst(mName) = aName;
124 m = new Data();
125 m->IPv4Gateway = "10.0.2.2";
126 m->IPv4NetworkCidr = "10.0.2.0/24";
127 m->IPv6Prefix = "fe80::/64";
128 m->fEnabled = FALSE;
129
130
131
132 RecalculateIpv4AddressAssignments();
133
134 HRESULT hrc = unconst(m->pEventSource).createObject();
135 if (FAILED(hrc)) throw hrc;
136
137 hrc = m->pEventSource->init(static_cast<INATNetwork *>(this));
138 if (FAILED(hrc)) throw hrc;
139
140 /* Confirm a successful initialization */
141 autoInitSpan.setSucceeded();
142
143 return S_OK;
144}
145
146
147HRESULT NATNetwork::init(VirtualBox *aVirtualBox,
148 const settings::NATNetwork &data)
149{
150 /* Enclose the state transition NotReady->InInit->Ready */
151 AutoInitSpan autoInitSpan(this);
152 AssertReturn(autoInitSpan.isOk(), E_FAIL);
153
154 /* share VirtualBox weakly (parent remains NULL so far) */
155 unconst(mVirtualBox) = aVirtualBox;
156
157 unconst(mName) = data.strNetworkName;
158 m = new Data();
159 m->IPv4NetworkCidr = data.strNetwork;
160 m->fEnabled = data.fEnabled;
161 m->fAdvertiseDefaultIPv6Route = data.fAdvertiseDefaultIPv6Route;
162 m->fNeedDhcpServer = data.fNeedDhcpServer;
163
164 RecalculateIpv4AddressAssignments();
165
166 /* IPv4 port-forward rules */
167 m->mapName2PortForwardRule4.clear();
168 for (settings::NATRuleList::const_iterator it = data.llPortForwardRules4.begin();
169 it != data.llPortForwardRules4.end(); ++it)
170 {
171 m->mapName2PortForwardRule4.insert(std::make_pair(it->strName.c_str(), *it));
172 }
173
174 /* IPv6 port-forward rules */
175 m->mapName2PortForwardRule6.clear();
176 for (settings::NATRuleList::const_iterator it = data.llPortForwardRules6.begin();
177 it != data.llPortForwardRules6.end(); ++it)
178 {
179 m->mapName2PortForwardRule6.insert(std::make_pair(it->strName, *it));
180 }
181
182 HRESULT hrc = unconst(m->pEventSource).createObject();
183 if (FAILED(hrc)) throw hrc;
184
185 hrc = m->pEventSource->init(static_cast<INATNetwork *>(this));
186 if (FAILED(hrc)) throw hrc;
187
188 autoInitSpan.setSucceeded();
189
190 return S_OK;
191}
192
193#ifdef NAT_XML_SERIALIZATION
194HRESULT NATNetwork::saveSettings(settings::NATNetwork &data)
195{
196 AutoCaller autoCaller(this);
197 if (FAILED(autoCaller.rc())) return autoCaller.rc();
198
199 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
200
201 data.strNetworkName = mName;
202 data.strNetwork = m->IPv4NetworkCidr;
203 data.fEnabled = RT_BOOL(m->fEnabled);
204 data.fAdvertiseDefaultIPv6Route = RT_BOOL(m->fAdvertiseDefaultIPv6Route);
205 data.fNeedDhcpServer = RT_BOOL(m->fNeedDhcpServer);
206 data.fIPv6 = RT_BOOL(m->fIPv6Enabled);
207 data.strIPv6Prefix = m->IPv6Prefix;
208
209 /* saving ipv4 port-forward Rules*/
210 data.llPortForwardRules4.clear();
211 for (NATRuleMap::iterator it = m->mapName2PortForwardRule4.begin();
212 it != m->mapName2PortForwardRule4.end(); ++it)
213 data.llPortForwardRules4.push_back(it->second);
214
215 /* saving ipv6 port-forward Rules*/
216 data.llPortForwardRules6.clear();
217 for (NATRuleMap::iterator it = m->mapName2PortForwardRule6.begin();
218 it != m->mapName2PortForwardRule6.end(); ++it)
219 data.llPortForwardRules4.push_back(it->second);
220
221 /* XXX: should we do here a copy of params */
222 /* XXX: should we unlock here? */
223 mVirtualBox->onNATNetworkSetting(mName.raw(),
224 data.fEnabled ? TRUE : FALSE,
225 m->IPv4NetworkCidr.raw(),
226 m->IPv4Gateway.raw(),
227 data.fAdvertiseDefaultIPv6Route ? TRUE : FALSE,
228 data.fNeedDhcpServer ? TRUE : FALSE);
229 return S_OK;
230}
231#endif
232
233STDMETHODIMP NATNetwork::COMGETTER(EventSource)(IEventSource ** aEventSource)
234{
235 CheckComArgOutPointerValid(aEventSource);
236
237 AutoCaller autoCaller(this);
238 if (FAILED(autoCaller.rc())) return autoCaller.rc();
239
240 /* event source is const, no need to lock */
241 m->pEventSource.queryInterfaceTo(aEventSource);
242
243 return S_OK;
244}
245
246STDMETHODIMP NATNetwork::COMGETTER(NetworkName) (BSTR *aName)
247{
248 CheckComArgOutPointerValid(aName);
249
250 AutoCaller autoCaller(this);
251 if (FAILED(autoCaller.rc())) return autoCaller.rc();
252
253 mName.cloneTo(aName);
254
255 return S_OK;
256}
257
258STDMETHODIMP NATNetwork::COMSETTER(NetworkName) (IN_BSTR aName)
259{
260 CheckComArgOutPointerValid(aName);
261
262 HRESULT rc = S_OK;
263 AutoCaller autoCaller(this);
264 if (FAILED(autoCaller.rc())) return autoCaller.rc();
265 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
266 unconst(mName) = aName;
267
268 alock.release();
269
270#ifdef NAT_XML_SERIALIZATION
271 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
272 rc = mVirtualBox->saveSettings();
273#endif
274 return rc;
275}
276
277
278STDMETHODIMP NATNetwork::COMGETTER(Enabled) (BOOL *aEnabled)
279{
280 CheckComArgOutPointerValid(aEnabled);
281
282 AutoCaller autoCaller(this);
283 if (FAILED(autoCaller.rc())) return autoCaller.rc();
284
285 *aEnabled = m->fEnabled;
286 RecalculateIpv4AddressAssignments();
287
288 return S_OK;
289}
290
291STDMETHODIMP NATNetwork::COMSETTER(Enabled) (BOOL aEnabled)
292{
293 AutoCaller autoCaller(this);
294 if (FAILED(autoCaller.rc())) return autoCaller.rc();
295 HRESULT rc = S_OK;
296 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
297 m->fEnabled = aEnabled;
298
299 // save the global settings; for that we should hold only the VirtualBox lock
300 alock.release();
301#ifdef NAT_XML_SERIALIZATION
302 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
303 rc = mVirtualBox->saveSettings();
304#endif
305 return rc;
306}
307
308STDMETHODIMP NATNetwork::COMGETTER(Gateway) (BSTR *aIPv4Gateway)
309{
310 CheckComArgOutPointerValid(aIPv4Gateway);
311
312 AutoCaller autoCaller(this);
313 if (FAILED(autoCaller.rc())) return autoCaller.rc();
314
315 m->IPv4Gateway.cloneTo(aIPv4Gateway);
316
317 return S_OK;
318}
319
320STDMETHODIMP NATNetwork::COMGETTER(Network) (BSTR *aIPv4NetworkCidr)
321{
322 CheckComArgOutPointerValid(aIPv4NetworkCidr);
323
324 AutoCaller autoCaller(this);
325 if (FAILED(autoCaller.rc())) return autoCaller.rc();
326 m->IPv4NetworkCidr.cloneTo(aIPv4NetworkCidr);
327 return S_OK;
328}
329
330STDMETHODIMP NATNetwork::COMSETTER(Network) (IN_BSTR aIPv4NetworkCidr)
331{
332 CheckComArgOutPointerValid(aIPv4NetworkCidr);
333
334 HRESULT rc = S_OK;
335 AutoCaller autoCaller(this);
336 if (FAILED(autoCaller.rc())) return autoCaller.rc();
337 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
338 /* silently ignore network cidr update */
339 if (m->mapName2PortForwardRule4.empty())
340 {
341
342 unconst(m->IPv4NetworkCidr) = Bstr(aIPv4NetworkCidr);
343 RecalculateIpv4AddressAssignments();
344 alock.release();
345
346#ifdef NAT_XML_SERIALIZATION
347 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
348 rc = mVirtualBox->saveSettings();
349#endif
350 }
351 return rc;
352}
353
354STDMETHODIMP NATNetwork::COMGETTER(IPv6Enabled)(BOOL *aAdvertiseDefaultIPv6Route)
355{
356 CheckComArgOutPointerValid(aAdvertiseDefaultIPv6Route);
357
358 AutoCaller autoCaller(this);
359 if (FAILED(autoCaller.rc())) return autoCaller.rc();
360
361 *aAdvertiseDefaultIPv6Route = m->fAdvertiseDefaultIPv6Route;
362
363 return S_OK;
364}
365
366STDMETHODIMP NATNetwork::COMSETTER(IPv6Enabled)(BOOL aAdvertiseDefaultIPv6Route)
367{
368 AutoCaller autoCaller(this);
369 if (FAILED(autoCaller.rc())) return autoCaller.rc();
370 HRESULT rc = S_OK;
371 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
372 m->fAdvertiseDefaultIPv6Route = aAdvertiseDefaultIPv6Route;
373
374 // save the global settings; for that we should hold only the VirtualBox lock
375 alock.release();
376
377#ifdef NAT_XML_SERIALIZATION
378 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
379 rc = mVirtualBox->saveSettings();
380#endif
381 return rc;
382}
383
384STDMETHODIMP NATNetwork::COMGETTER(IPv6Prefix) (BSTR *aIPv6Prefix)
385{
386 CheckComArgOutPointerValid(aIPv6Prefix);
387
388 AutoCaller autoCaller(this);
389 if (FAILED(autoCaller.rc())) return autoCaller.rc();
390 return S_OK;
391}
392
393STDMETHODIMP NATNetwork::COMSETTER(IPv6Prefix) (IN_BSTR aIPv6Prefix)
394{
395 CheckComArgOutPointerValid(aIPv6Prefix);
396
397 HRESULT rc = S_OK;
398 AutoCaller autoCaller(this);
399 if (FAILED(autoCaller.rc())) return autoCaller.rc();
400 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
401 /* silently ignore network cidr update */
402 if (m->mapName2PortForwardRule6.empty())
403 {
404
405 unconst(m->IPv6Prefix) = Bstr(aIPv6Prefix);
406 /* @todo: do we need recalculation ? */
407 alock.release();
408
409#ifdef NAT_XML_SERIALIZATION
410 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
411 rc = mVirtualBox->saveSettings();
412#endif
413 }
414 return rc;
415}
416
417STDMETHODIMP NATNetwork::COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(BOOL *aAdvertiseDefaultIPv6Route)
418{
419 CheckComArgOutPointerValid(aAdvertiseDefaultIPv6Route);
420
421 AutoCaller autoCaller(this);
422 if (FAILED(autoCaller.rc())) return autoCaller.rc();
423
424 *aAdvertiseDefaultIPv6Route = m->fAdvertiseDefaultIPv6Route;
425
426 return S_OK;
427}
428
429STDMETHODIMP NATNetwork::COMSETTER(AdvertiseDefaultIPv6RouteEnabled)(BOOL aAdvertiseDefaultIPv6Route)
430{
431 AutoCaller autoCaller(this);
432 if (FAILED(autoCaller.rc())) return autoCaller.rc();
433 HRESULT rc = S_OK;
434 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
435 m->fAdvertiseDefaultIPv6Route = aAdvertiseDefaultIPv6Route;
436
437 // save the global settings; for that we should hold only the VirtualBox lock
438 alock.release();
439
440#ifdef NAT_XML_SERIALIZATION
441 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
442 rc = mVirtualBox->saveSettings();
443#endif
444 return rc;
445}
446
447STDMETHODIMP NATNetwork::COMGETTER(NeedDhcpServer)(BOOL *aNeedDhcpServer)
448{
449 CheckComArgOutPointerValid(aNeedDhcpServer);
450
451 AutoCaller autoCaller(this);
452 if (FAILED(autoCaller.rc())) return autoCaller.rc();
453
454 *aNeedDhcpServer = m->fNeedDhcpServer;
455
456 return S_OK;
457}
458
459STDMETHODIMP NATNetwork::COMSETTER(NeedDhcpServer)(BOOL aNeedDhcpServer)
460{
461 AutoCaller autoCaller(this);
462 if (FAILED(autoCaller.rc())) return autoCaller.rc();
463 HRESULT rc = S_OK;
464 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
465 m->fNeedDhcpServer = aNeedDhcpServer;
466
467 RecalculateIpv4AddressAssignments();
468
469 // save the global settings; for that we should hold only the VirtualBox lock
470 alock.release();
471
472#ifdef NAT_XML_SERIALIZATION
473 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
474 rc = mVirtualBox->saveSettings();
475#endif
476 return rc;
477}
478
479STDMETHODIMP NATNetwork::COMGETTER(PortForwardRules4)(ComSafeArrayOut(BSTR, aPortForwardRules4))
480{
481 CheckComArgOutSafeArrayPointerValid(aPortForwardRules4);
482
483 AutoCaller autoCaller(this);
484 if (FAILED(autoCaller.rc())) return autoCaller.rc();
485
486 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
487 GetPortForwardRulesFromMap(ComSafeArrayInArg(aPortForwardRules4),
488 m->mapName2PortForwardRule4);
489 alock.release();
490 return S_OK;
491}
492
493STDMETHODIMP NATNetwork::COMGETTER(PortForwardRules6)(ComSafeArrayOut(BSTR,
494 aPortForwardRules6))
495{
496 CheckComArgOutSafeArrayPointerValid(aPortForwardRules6);
497
498 AutoCaller autoCaller(this);
499 if (FAILED(autoCaller.rc())) return autoCaller.rc();
500
501 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
502 GetPortForwardRulesFromMap(ComSafeArrayInArg(aPortForwardRules6), m->mapName2PortForwardRule6);
503 return S_OK;
504}
505
506STDMETHODIMP NATNetwork::AddPortForwardRule(BOOL aIsIpv6,
507 IN_BSTR aPortForwardRuleName,
508 NATProtocol_T aProto,
509 IN_BSTR aHostIp,
510 USHORT aHostPort,
511 IN_BSTR aGuestIp,
512 USHORT aGuestPort)
513{
514 int rc = S_OK;
515 AutoCaller autoCaller(this);
516 if (FAILED(autoCaller.rc())) return autoCaller.rc();
517
518 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
519 Utf8Str name = aPortForwardRuleName;
520 Utf8Str proto;
521 settings::NATRule r;
522 NATRuleMap& mapRules = aIsIpv6 ? m->mapName2PortForwardRule6 : m->mapName2PortForwardRule4;
523 switch (aProto)
524 {
525 case NATProtocol_TCP:
526 proto = "tcp";
527 break;
528 case NATProtocol_UDP:
529 proto = "udp";
530 break;
531 default:
532 return E_INVALIDARG;
533 }
534 if (name.isEmpty())
535 name = Utf8StrFmt("%s_[%s]%%%d_[%s]%%%d", proto.c_str(),
536 Utf8Str(aHostIp).c_str(), aHostPort,
537 Utf8Str(aGuestIp).c_str(), aGuestPort);
538
539 NATRuleMap::iterator it;
540
541 for (it = mapRules.begin(); it != mapRules.end(); ++it)
542 {
543 r = it->second;
544 if (it->first == name)
545 return setError(E_INVALIDARG,
546 tr("A NAT rule of this name already exists"));
547 if ( r.strHostIP == Utf8Str(aHostIp)
548 && r.u16HostPort == aHostPort
549 && r.proto == aProto)
550 return setError(E_INVALIDARG,
551 tr("A NAT rule for this host port and this host IP already exists"));
552 }
553
554 r.strName = name.c_str();
555 r.proto = aProto;
556 r.strHostIP = aHostIp;
557 r.u16HostPort = aHostPort;
558 r.strGuestIP = aGuestIp;
559 r.u16GuestPort = aGuestPort;
560 mapRules.insert(std::make_pair(name, r));
561
562 alock.release();
563 mVirtualBox->onNATNetworkPortForward(mName.raw(), TRUE, aIsIpv6,
564 aPortForwardRuleName, aProto,
565 aHostIp, aHostPort,
566 aGuestIp, aGuestPort);
567
568 /* Notify listerners listening on this network only */
569 fireNATNetworkPortForwardEvent(m->pEventSource, mName.raw(), TRUE,
570 aIsIpv6, aPortForwardRuleName, aProto,
571 aHostIp, aHostPort,
572 aGuestIp, aGuestPort);
573
574#ifdef NAT_XML_SERIALIZATION
575 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
576 rc = mVirtualBox->saveSettings();
577#endif
578 return rc;
579}
580
581STDMETHODIMP NATNetwork::RemovePortForwardRule(BOOL aIsIpv6, IN_BSTR aPortForwardRuleName)
582{
583 int rc = S_OK;
584 Utf8Str strHostIP, strGuestIP;
585 uint16_t u16HostPort, u16GuestPort;
586 NATProtocol_T proto = NATProtocol_TCP;
587
588 AutoCaller autoCaller(this);
589 if (FAILED(autoCaller.rc())) return autoCaller.rc();
590
591 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
592 NATRuleMap& mapRules = aIsIpv6 ? m->mapName2PortForwardRule6 : m->mapName2PortForwardRule4;
593 NATRuleMap::iterator it = mapRules.find(aPortForwardRuleName);
594
595 if (it == mapRules.end())
596 return E_INVALIDARG;
597
598 strHostIP = it->second.strHostIP;
599 strGuestIP = it->second.strGuestIP;
600 u16HostPort = it->second.u16HostPort;
601 u16GuestPort = it->second.u16GuestPort;
602 proto = it->second.proto;
603
604 mapRules.erase(it);
605
606 alock.release();
607
608 mVirtualBox->onNATNetworkPortForward(mName.raw(), FALSE, aIsIpv6,
609 aPortForwardRuleName, proto,
610 Bstr(strHostIP).raw(), u16HostPort,
611 Bstr(strGuestIP).raw(), u16GuestPort);
612
613 /* Notify listerners listening on this network only */
614 fireNATNetworkPortForwardEvent(m->pEventSource, mName.raw(), FALSE,
615 aIsIpv6, aPortForwardRuleName, proto,
616 Bstr(strHostIP).raw(), u16HostPort,
617 Bstr(strGuestIP).raw(), u16GuestPort);
618#ifdef NAT_XML_SERIALIZATION
619 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
620 rc = mVirtualBox->saveSettings();
621#endif
622
623 return rc;
624}
625
626
627STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
628{
629#ifdef VBOX_WITH_NAT_SERVICE
630 AutoCaller autoCaller(this);
631 if (FAILED(autoCaller.rc())) return autoCaller.rc();
632
633 if (!m->fEnabled) return S_OK;
634 m->NATRunner.setOption(NATSCCFG_NAME, mName, true);
635 m->NATRunner.setOption(NATSCCFG_TRUNKTYPE, Utf8Str(aTrunkType), true);
636 m->NATRunner.setOption(NATSCCFG_IPADDRESS, m->IPv4Gateway, true);
637 m->NATRunner.setOption(NATSCCFG_NETMASK, m->IPv4NetworkMask, true);
638
639 /* port-forwarding */
640
641 for (constNATRuleMapIterator it = m->mapName2PortForwardRule4.begin();
642 it != m->mapName2PortForwardRule4.end(); ++it)
643 {
644 settings::NATRule r = it->second;
645 m->NATRunner.setOption(NATSCCFG_PORTFORWARD4,
646 Bstr(Utf8StrFmt("%s:%d:[%s]:%d:[%s]:%d",
647 r.strName.c_str(),
648 r.proto,
649 r.strHostIP.isEmpty() ?
650 "0.0.0.0" :
651 r.strHostIP.c_str(),
652 r.u16HostPort,
653 r.strGuestIP.c_str(),
654 r.u16GuestPort)), true);
655 }
656
657 if (m->fNeedDhcpServer)
658 {
659 /**
660 * Just to as idea... via API (on creation user pass the cidr of network and)
661 * and we calculate it's addreses (mutable?).
662 */
663
664 /*
665 * Configuration and running DHCP server:
666 * 1. find server first createDHCPServer
667 * 2. if return status is E_INVALARG => server already exists just find and start.
668 * 3. if return status neither E_INVALRG nor S_OK => return E_FAIL
669 * 4. if return status S_OK proceed to DHCP server configuration
670 * 5. call setConfiguration() and pass all required parameters
671 * 6. start dhcp server.
672 */
673 int rc = mVirtualBox->FindDHCPServerByNetworkName(mName.raw(),
674 m->dhcpServer.asOutParam());
675 switch (rc)
676 {
677 case E_INVALIDARG:
678 /* server haven't beeen found let create it then */
679 rc = mVirtualBox->CreateDHCPServer(mName.raw(),
680 m->dhcpServer.asOutParam());
681 if (FAILED(rc))
682 return E_FAIL;
683 /* breakthrough */
684 case S_OK:
685 {
686 LogFunc(("gateway: %s, dhcpserver:%s, dhcplowerip:%s, dhcpupperip:%s\n",
687 Utf8Str(m->IPv4Gateway.raw()).c_str(),
688 Utf8Str(m->IPv4DhcpServer.raw()).c_str(),
689 Utf8Str(m->IPv4DhcpServerLowerIp.raw()).c_str(),
690 Utf8Str(m->IPv4DhcpServerUpperIp.raw()).c_str()));
691
692
693 rc = m->dhcpServer->SetEnabled(true);
694 BSTR dhcpip = NULL;
695 BSTR netmask = NULL;
696 BSTR lowerip = NULL;
697 BSTR upperip = NULL;
698 m->IPv4DhcpServer.cloneTo(&dhcpip);
699 m->IPv4NetworkMask.cloneTo(&netmask);
700
701 m->IPv4DhcpServerLowerIp.cloneTo(&lowerip);
702 m->IPv4DhcpServerUpperIp.cloneTo(&upperip);
703 rc = m->dhcpServer->SetConfiguration(dhcpip,
704 netmask,
705 lowerip,
706 upperip);
707 break;
708 }
709
710 default:
711 return E_FAIL;
712 }
713
714 rc = m->dhcpServer->Start(mName.raw(), Bstr("").raw(), aTrunkType);
715 if (FAILED(rc))
716 {
717 m->dhcpServer.setNull();
718 return E_FAIL;
719 }
720 }
721
722 if (RT_SUCCESS(m->NATRunner.start()))
723 {
724 mVirtualBox->onNATNetworkStartStop(mName.raw(), TRUE);
725 return S_OK;
726 }
727 else return E_FAIL;
728#else
729 NOREF(aTrunkType);
730 return E_NOTIMPL;
731#endif
732}
733
734STDMETHODIMP NATNetwork::Stop()
735{
736#ifdef VBOX_WITH_NAT_SERVICE
737 if (RT_SUCCESS(m->NATRunner.stop()))
738 {
739 mVirtualBox->onNATNetworkStartStop(mName.raw(), FALSE);
740 return S_OK;
741 }
742 else return E_FAIL;
743
744#else
745 return E_NOTIMPL;
746#endif
747}
748
749void NATNetwork::GetPortForwardRulesFromMap(ComSafeArrayOut(BSTR, aPortForwardRules), NATRuleMap& aRules)
750{
751 com::SafeArray<BSTR> sf(aRules.size());
752 size_t i = 0;
753 NATRuleMap::const_iterator it;
754 for (it = aRules.begin();
755 it != aRules.end(); ++it, ++i)
756 {
757 settings::NATRule r = it->second;
758 BstrFmt bstr("%s:%s:[%s]:%d:[%s]:%d",
759 r.strName.c_str(),
760 (r.proto == NATProtocol_TCP? "tcp" : "udp"),
761 r.strHostIP.c_str(),
762 r.u16HostPort,
763 r.strGuestIP.c_str(),
764 r.u16GuestPort);
765 bstr.detachTo(&sf[i]);
766 }
767 sf.detachTo(ComSafeArrayOutArg(aPortForwardRules));
768}
769
770int NATNetwork::RecalculateIpv4AddressAssignments()
771{
772 RTNETADDRIPV4 network, netmask, gateway;
773 char aszGatewayIp[16], aszNetmask[16];
774 RT_ZERO(aszNetmask);
775 int rc = RTCidrStrToIPv4(Utf8Str(m->IPv4NetworkCidr.raw()).c_str(),
776 &network,
777 &netmask);
778 AssertRCReturn(rc, rc);
779
780 /* I don't remember the reason CIDR calcualted in host */
781 gateway.u = network.u;
782
783 gateway.u += 1;
784 gateway.u = RT_H2N_U32(gateway.u);
785 RTStrPrintf(aszGatewayIp, 16, "%RTnaipv4", gateway);
786 m->IPv4Gateway = RTStrDup(aszGatewayIp);
787 if (m->fNeedDhcpServer)
788 {
789 RTNETADDRIPV4 dhcpserver,
790 dhcplowerip,
791 dhcpupperip;
792 char aszNetwork[16],
793 aszDhcpIp[16],
794 aszDhcpLowerIp[16],
795 aszDhcpUpperIp[16];
796 RT_ZERO(aszNetwork);
797
798 RT_ZERO(aszDhcpIp);
799 RT_ZERO(aszDhcpLowerIp);
800 RT_ZERO(aszDhcpUpperIp);
801
802 dhcpserver.u = network.u;
803 dhcpserver.u += 2;
804
805
806 /* XXX: adding more services should change the math here */
807 dhcplowerip.u = RT_H2N_U32(dhcpserver.u + 1);
808 dhcpupperip.u = RT_H2N_U32((network.u | (~netmask.u)) -1);
809 dhcpserver.u = RT_H2N_U32(dhcpserver.u);
810 network.u = RT_H2N_U32(network.u);
811
812 RTStrPrintf(aszNetwork, 16, "%RTnaipv4", network);
813 RTStrPrintf(aszDhcpLowerIp, 16, "%RTnaipv4", dhcplowerip);
814 RTStrPrintf(aszDhcpUpperIp, 16, "%RTnaipv4", dhcpupperip);
815 RTStrPrintf(aszDhcpIp, 16, "%RTnaipv4", dhcpserver);
816
817 m->IPv4DhcpServer = aszDhcpIp;
818 m->IPv4DhcpServerLowerIp = aszDhcpLowerIp;
819 m->IPv4DhcpServerUpperIp = aszDhcpUpperIp;
820 LogFunc(("network: %RTnaipv4, dhcpserver:%RTnaipv4, dhcplowerip:%RTnaipv4, dhcpupperip:%RTnaipv4\n", network, dhcpserver, dhcplowerip, dhcpupperip));
821 }
822 /* we need IPv4NetworkMask for NAT's gw service start */
823 netmask.u = RT_H2N_U32(netmask.u);
824 RTStrPrintf(aszNetmask, 16, "%RTnaipv4", netmask);
825 m->IPv4NetworkMask = aszNetmask;
826 LogFlowFunc(("getaway:%RTnaipv4, netmask:%RTnaipv4\n", gateway, netmask));
827 return VINF_SUCCESS;
828}
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