VirtualBox

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

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

build fix

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