VirtualBox

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

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

main/natnetwork: stubs for loopback6 setter/getter.

  • 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 47869 2013-08-20 05:15:15Z 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 "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 return E_NOTIMPL;
481}
482
483STDMETHODIMP NATNetwork::AddLocalMapping(IN_BSTR aHostId, LONG aOffset)
484{
485 return E_NOTIMPL;
486}
487
488STDMETHODIMP NATNetwork::COMGETTER(LoopbackIp6)(LONG *aLoopbackIp6)
489{
490 return E_NOTIMPL;
491}
492
493STDMETHODIMP NATNetwork::COMSETTER(LoopbackIp6)(LONG aLoopbackIp6)
494{
495 return E_NOTIMPL;
496}
497
498STDMETHODIMP NATNetwork::COMGETTER(PortForwardRules4)(ComSafeArrayOut(BSTR, aPortForwardRules4))
499{
500 CheckComArgOutSafeArrayPointerValid(aPortForwardRules4);
501
502 AutoCaller autoCaller(this);
503 if (FAILED(autoCaller.rc())) return autoCaller.rc();
504
505 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
506 GetPortForwardRulesFromMap(ComSafeArrayInArg(aPortForwardRules4),
507 m->mapName2PortForwardRule4);
508 alock.release();
509 return S_OK;
510}
511
512STDMETHODIMP NATNetwork::COMGETTER(PortForwardRules6)(ComSafeArrayOut(BSTR,
513 aPortForwardRules6))
514{
515 CheckComArgOutSafeArrayPointerValid(aPortForwardRules6);
516
517 AutoCaller autoCaller(this);
518 if (FAILED(autoCaller.rc())) return autoCaller.rc();
519
520 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
521 GetPortForwardRulesFromMap(ComSafeArrayInArg(aPortForwardRules6), m->mapName2PortForwardRule6);
522 return S_OK;
523}
524
525STDMETHODIMP NATNetwork::AddPortForwardRule(BOOL aIsIpv6,
526 IN_BSTR aPortForwardRuleName,
527 NATProtocol_T aProto,
528 IN_BSTR aHostIp,
529 USHORT aHostPort,
530 IN_BSTR aGuestIp,
531 USHORT aGuestPort)
532{
533 int rc = S_OK;
534 AutoCaller autoCaller(this);
535 if (FAILED(autoCaller.rc())) return autoCaller.rc();
536
537 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
538 Utf8Str name = aPortForwardRuleName;
539 Utf8Str proto;
540 settings::NATRule r;
541 NATRuleMap& mapRules = aIsIpv6 ? m->mapName2PortForwardRule6 : m->mapName2PortForwardRule4;
542 switch (aProto)
543 {
544 case NATProtocol_TCP:
545 proto = "tcp";
546 break;
547 case NATProtocol_UDP:
548 proto = "udp";
549 break;
550 default:
551 return E_INVALIDARG;
552 }
553 if (name.isEmpty())
554 name = Utf8StrFmt("%s_[%s]%%%d_[%s]%%%d", proto.c_str(),
555 Utf8Str(aHostIp).c_str(), aHostPort,
556 Utf8Str(aGuestIp).c_str(), aGuestPort);
557
558 NATRuleMap::iterator it;
559
560 for (it = mapRules.begin(); it != mapRules.end(); ++it)
561 {
562 r = it->second;
563 if (it->first == name)
564 return setError(E_INVALIDARG,
565 tr("A NAT rule of this name already exists"));
566 if ( r.strHostIP == Utf8Str(aHostIp)
567 && r.u16HostPort == aHostPort
568 && r.proto == aProto)
569 return setError(E_INVALIDARG,
570 tr("A NAT rule for this host port and this host IP already exists"));
571 }
572
573 r.strName = name.c_str();
574 r.proto = aProto;
575 r.strHostIP = aHostIp;
576 r.u16HostPort = aHostPort;
577 r.strGuestIP = aGuestIp;
578 r.u16GuestPort = aGuestPort;
579 mapRules.insert(std::make_pair(name, r));
580
581 alock.release();
582 mVirtualBox->onNATNetworkPortForward(mName.raw(), TRUE, aIsIpv6,
583 aPortForwardRuleName, aProto,
584 aHostIp, aHostPort,
585 aGuestIp, aGuestPort);
586
587 /* Notify listerners listening on this network only */
588 fireNATNetworkPortForwardEvent(m->pEventSource, mName.raw(), TRUE,
589 aIsIpv6, aPortForwardRuleName, aProto,
590 aHostIp, aHostPort,
591 aGuestIp, aGuestPort);
592
593#ifdef NAT_XML_SERIALIZATION
594 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
595 rc = mVirtualBox->saveSettings();
596#endif
597 return rc;
598}
599
600STDMETHODIMP NATNetwork::RemovePortForwardRule(BOOL aIsIpv6, IN_BSTR aPortForwardRuleName)
601{
602 int rc = S_OK;
603 Utf8Str strHostIP, strGuestIP;
604 uint16_t u16HostPort, u16GuestPort;
605 NATProtocol_T proto = NATProtocol_TCP;
606
607 AutoCaller autoCaller(this);
608 if (FAILED(autoCaller.rc())) return autoCaller.rc();
609
610 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
611 NATRuleMap& mapRules = aIsIpv6 ? m->mapName2PortForwardRule6 : m->mapName2PortForwardRule4;
612 NATRuleMap::iterator it = mapRules.find(aPortForwardRuleName);
613
614 if (it == mapRules.end())
615 return E_INVALIDARG;
616
617 strHostIP = it->second.strHostIP;
618 strGuestIP = it->second.strGuestIP;
619 u16HostPort = it->second.u16HostPort;
620 u16GuestPort = it->second.u16GuestPort;
621 proto = it->second.proto;
622
623 mapRules.erase(it);
624
625 alock.release();
626
627 mVirtualBox->onNATNetworkPortForward(mName.raw(), FALSE, aIsIpv6,
628 aPortForwardRuleName, proto,
629 Bstr(strHostIP).raw(), u16HostPort,
630 Bstr(strGuestIP).raw(), u16GuestPort);
631
632 /* Notify listerners listening on this network only */
633 fireNATNetworkPortForwardEvent(m->pEventSource, mName.raw(), FALSE,
634 aIsIpv6, aPortForwardRuleName, proto,
635 Bstr(strHostIP).raw(), u16HostPort,
636 Bstr(strGuestIP).raw(), u16GuestPort);
637#ifdef NAT_XML_SERIALIZATION
638 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
639 rc = mVirtualBox->saveSettings();
640#endif
641
642 return rc;
643}
644
645
646STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
647{
648#ifdef VBOX_WITH_NAT_SERVICE
649 AutoCaller autoCaller(this);
650 if (FAILED(autoCaller.rc())) return autoCaller.rc();
651
652 if (!m->fEnabled) return S_OK;
653
654 m->NATRunner.setOption(NETCFG_NETNAME, mName, true);
655 m->NATRunner.setOption(NETCFG_TRUNKTYPE, Utf8Str(aTrunkType), true);
656 m->NATRunner.setOption(NETCFG_IPADDRESS, m->IPv4Gateway, true);
657 m->NATRunner.setOption(NETCFG_NETMASK, m->IPv4NetworkMask, true);
658
659 /* No portforwarding rules from command-line, all will be fetched via API */
660
661 if (m->fNeedDhcpServer)
662 {
663 /**
664 * Just to as idea... via API (on creation user pass the cidr of network and)
665 * and we calculate it's addreses (mutable?).
666 */
667
668 /*
669 * Configuration and running DHCP server:
670 * 1. find server first createDHCPServer
671 * 2. if return status is E_INVALARG => server already exists just find and start.
672 * 3. if return status neither E_INVALRG nor S_OK => return E_FAIL
673 * 4. if return status S_OK proceed to DHCP server configuration
674 * 5. call setConfiguration() and pass all required parameters
675 * 6. start dhcp server.
676 */
677 int rc = mVirtualBox->FindDHCPServerByNetworkName(mName.raw(),
678 m->dhcpServer.asOutParam());
679 switch (rc)
680 {
681 case E_INVALIDARG:
682 /* server haven't beeen found let create it then */
683 rc = mVirtualBox->CreateDHCPServer(mName.raw(),
684 m->dhcpServer.asOutParam());
685 if (FAILED(rc))
686 return E_FAIL;
687 /* breakthrough */
688
689 {
690 LogFunc(("gateway: %s, dhcpserver:%s, dhcplowerip:%s, dhcpupperip:%s\n",
691 Utf8Str(m->IPv4Gateway.raw()).c_str(),
692 Utf8Str(m->IPv4DhcpServer.raw()).c_str(),
693 Utf8Str(m->IPv4DhcpServerLowerIp.raw()).c_str(),
694 Utf8Str(m->IPv4DhcpServerUpperIp.raw()).c_str()));
695
696 m->dhcpServer->AddGlobalOption(DhcpOpt_Router, m->IPv4Gateway.raw());
697
698 rc = m->dhcpServer->COMSETTER(Enabled)(true);
699
700 BSTR dhcpip = NULL;
701 BSTR netmask = NULL;
702 BSTR lowerip = NULL;
703 BSTR upperip = NULL;
704
705 m->IPv4DhcpServer.cloneTo(&dhcpip);
706 m->IPv4NetworkMask.cloneTo(&netmask);
707 m->IPv4DhcpServerLowerIp.cloneTo(&lowerip);
708 m->IPv4DhcpServerUpperIp.cloneTo(&upperip);
709 rc = m->dhcpServer->SetConfiguration(dhcpip,
710 netmask,
711 lowerip,
712 upperip);
713 }
714 case S_OK:
715 break;
716
717 default:
718 return E_FAIL;
719 }
720
721 rc = m->dhcpServer->Start(mName.raw(), Bstr("").raw(), aTrunkType);
722 if (FAILED(rc))
723 {
724 m->dhcpServer.setNull();
725 return E_FAIL;
726 }
727 }
728
729 if (RT_SUCCESS(m->NATRunner.start()))
730 {
731 mVirtualBox->onNATNetworkStartStop(mName.raw(), TRUE);
732 return S_OK;
733 }
734 else return E_FAIL;
735#else
736 NOREF(aTrunkType);
737 ReturnComNotImplemented();
738#endif
739}
740
741STDMETHODIMP NATNetwork::Stop()
742{
743#ifdef VBOX_WITH_NAT_SERVICE
744 if (!m->dhcpServer.isNull())
745 m->dhcpServer->Stop();
746
747 if (RT_SUCCESS(m->NATRunner.stop()))
748 {
749 mVirtualBox->onNATNetworkStartStop(mName.raw(), FALSE);
750 return S_OK;
751 }
752 else return E_FAIL;
753#else
754 ReturnComNotImplemented();
755#endif
756}
757
758void NATNetwork::GetPortForwardRulesFromMap(ComSafeArrayOut(BSTR, aPortForwardRules), NATRuleMap& aRules)
759{
760 com::SafeArray<BSTR> sf(aRules.size());
761 size_t i = 0;
762 NATRuleMap::const_iterator it;
763 for (it = aRules.begin();
764 it != aRules.end(); ++it, ++i)
765 {
766 settings::NATRule r = it->second;
767 BstrFmt bstr("%s:%s:[%s]:%d:[%s]:%d",
768 r.strName.c_str(),
769 (r.proto == NATProtocol_TCP? "tcp" : "udp"),
770 r.strHostIP.c_str(),
771 r.u16HostPort,
772 r.strGuestIP.c_str(),
773 r.u16GuestPort);
774 bstr.detachTo(&sf[i]);
775 }
776 sf.detachTo(ComSafeArrayOutArg(aPortForwardRules));
777}
778
779int NATNetwork::RecalculateIpv4AddressAssignments()
780{
781 RTNETADDRIPV4 network, netmask, gateway;
782 char aszGatewayIp[16], aszNetmask[16];
783 RT_ZERO(aszNetmask);
784 int rc = RTCidrStrToIPv4(Utf8Str(m->IPv4NetworkCidr.raw()).c_str(),
785 &network,
786 &netmask);
787 AssertRCReturn(rc, rc);
788
789 /* I don't remember the reason CIDR calcualted in host */
790 gateway.u = network.u;
791
792 gateway.u += 1;
793 gateway.u = RT_H2N_U32(gateway.u);
794 RTStrPrintf(aszGatewayIp, 16, "%RTnaipv4", gateway);
795 m->IPv4Gateway = RTStrDup(aszGatewayIp);
796 if (m->fNeedDhcpServer)
797 {
798 RTNETADDRIPV4 dhcpserver,
799 dhcplowerip,
800 dhcpupperip;
801 char aszNetwork[16],
802 aszDhcpIp[16],
803 aszDhcpLowerIp[16],
804 aszDhcpUpperIp[16];
805 RT_ZERO(aszNetwork);
806
807 RT_ZERO(aszDhcpIp);
808 RT_ZERO(aszDhcpLowerIp);
809 RT_ZERO(aszDhcpUpperIp);
810
811 dhcpserver.u = network.u;
812 dhcpserver.u += 2;
813
814
815 /* XXX: adding more services should change the math here */
816 dhcplowerip.u = RT_H2N_U32(dhcpserver.u + 1);
817 dhcpupperip.u = RT_H2N_U32((network.u | (~netmask.u)) -1);
818 dhcpserver.u = RT_H2N_U32(dhcpserver.u);
819 network.u = RT_H2N_U32(network.u);
820
821 RTStrPrintf(aszNetwork, 16, "%RTnaipv4", network);
822 RTStrPrintf(aszDhcpLowerIp, 16, "%RTnaipv4", dhcplowerip);
823 RTStrPrintf(aszDhcpUpperIp, 16, "%RTnaipv4", dhcpupperip);
824 RTStrPrintf(aszDhcpIp, 16, "%RTnaipv4", dhcpserver);
825
826 m->IPv4DhcpServer = aszDhcpIp;
827 m->IPv4DhcpServerLowerIp = aszDhcpLowerIp;
828 m->IPv4DhcpServerUpperIp = aszDhcpUpperIp;
829
830 LogFunc(("network: %RTnaipv4, dhcpserver:%RTnaipv4, dhcplowerip:%RTnaipv4, dhcpupperip:%RTnaipv4\n",
831 network,
832 dhcpserver,
833 dhcplowerip,
834 dhcpupperip));
835 }
836 /* we need IPv4NetworkMask for NAT's gw service start */
837 netmask.u = RT_H2N_U32(netmask.u);
838 RTStrPrintf(aszNetmask, 16, "%RTnaipv4", netmask);
839 m->IPv4NetworkMask = aszNetmask;
840 LogFlowFunc(("getaway:%RTnaipv4, netmask:%RTnaipv4\n", gateway, netmask));
841 return VINF_SUCCESS;
842}
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