VirtualBox

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

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

Main/src-server: Unused variables and parameters warnings.

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