VirtualBox

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

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

Main/NATNetworks: API+XML serialization for NATNetworks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/* $Id: NATNetworkImpl.cpp 45138 2013-03-22 11:52:24Z 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 "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 /* aPortForwardRules4Size appears from ComSafeArrayOut */
460 GetPortForwardRulesFromMap(aPortForwardRules4Size,
461 aPortForwardRules4,
462 m->mapName2PortForwardRule4);
463 alock.release();
464 return S_OK;
465}
466
467STDMETHODIMP NATNetwork::COMGETTER(PortForwardRules6)(ComSafeArrayOut(BSTR, aPortForwardRules6))
468{
469 CheckComArgOutSafeArrayPointerValid(aPortForwardRules6);
470
471 AutoCaller autoCaller(this);
472 if (FAILED(autoCaller.rc())) return autoCaller.rc();
473
474 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
475 GetPortForwardRulesFromMap(aPortForwardRules6Size, aPortForwardRules6, m->mapName2PortForwardRule6);
476 return S_OK;
477}
478
479STDMETHODIMP NATNetwork::AddPortForwardRule(BOOL aIsIpv6,
480 IN_BSTR aPortForwardRuleName,
481 NATProtocol_T aProto,
482 IN_BSTR aHostIp,
483 USHORT aHostPort,
484 IN_BSTR aGuestIp,
485 USHORT aGuestPort)
486{
487 int rc = S_OK;
488 AutoCaller autoCaller(this);
489 if (FAILED(autoCaller.rc())) return autoCaller.rc();
490
491 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
492 Utf8Str name = aPortForwardRuleName;
493 Utf8Str proto;
494 settings::NATRule r;
495 NATRuleMap& mapRules = aIsIpv6 ? m->mapName2PortForwardRule6 : m->mapName2PortForwardRule4;
496 switch (aProto)
497 {
498 case NATProtocol_TCP:
499 proto = "tcp";
500 break;
501 case NATProtocol_UDP:
502 proto = "udp";
503 break;
504 default:
505 return E_INVALIDARG;
506 }
507 if (name.isEmpty())
508 name = Utf8StrFmt("%s_%s:%d_%s:%d", proto.c_str(),
509 Utf8Str(aHostIp).c_str(), aHostPort,
510 Utf8Str(aGuestIp).c_str(), aGuestPort);
511
512 NATRuleMap::iterator it;
513 for (it = mapRules.begin(); it != mapRules.end(); ++it)
514 {
515 r = it->second;
516 if (it->first == name)
517 return setError(E_INVALIDARG,
518 tr("A NAT rule of this name already exists"));
519 if ( r.strHostIP == Utf8Str(aHostIp)
520 && r.u16HostPort == aHostPort
521 && r.proto == aProto)
522 return setError(E_INVALIDARG,
523 tr("A NAT rule for this host port and this host IP already exists"));
524 }
525
526 r.strName = name.c_str();
527 r.proto = aProto;
528 r.strHostIP = aHostIp;
529 r.u16HostPort = aHostPort;
530 r.strGuestIP = aGuestIp;
531 r.u16GuestPort = aGuestPort;
532 mapRules.insert(std::make_pair(name, r));
533
534 alock.release();
535 mVirtualBox->onNATNetworkPortForward(mName.raw(), TRUE, aIsIpv6,
536 aPortForwardRuleName, aProto,
537 aHostIp, aHostPort,
538 aGuestIp, aGuestPort);
539#ifdef NAT_XML_SERIALIZATION
540 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
541 rc = mVirtualBox->saveSettings();
542#endif
543 /* @todo: fire the event */
544 return rc;
545}
546
547STDMETHODIMP NATNetwork::RemovePortForwardRule(BOOL aIsIpv6, IN_BSTR aPortForwardRuleName)
548{
549 int rc = S_OK;
550 AutoCaller autoCaller(this);
551 if (FAILED(autoCaller.rc())) return autoCaller.rc();
552
553 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
554 NATRuleMap& mapRules = aIsIpv6 ? m->mapName2PortForwardRule6 : m->mapName2PortForwardRule4;
555 NATRuleMap::iterator it = mapRules.find(aPortForwardRuleName);
556 if (it == mapRules.end())
557 return E_INVALIDARG;
558
559 mapRules.erase(it);
560
561 alock.release();
562 /* we need only name here, it supposed to be uniq within IP version protocols */
563 mVirtualBox->onNATNetworkPortForward(mName.raw(), FALSE, aIsIpv6,
564 aPortForwardRuleName, NATProtocol_TCP,
565 Bstr().raw(), 0,
566 Bstr().raw(), 0);
567#ifdef NAT_XML_SERIALIZATION
568 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
569 rc = mVirtualBox->saveSettings();
570#endif
571 /* @todo: fire the event */
572 return rc;
573}
574
575
576STDMETHODIMP NATNetwork::Start(IN_BSTR aTrunkType)
577{
578#ifdef VBOX_WITH_NAT_SERVICE
579 AutoCaller autoCaller(this);
580 if (FAILED(autoCaller.rc())) return autoCaller.rc();
581
582 if (!m->fEnabled) return S_OK;
583 m->NATRunner.setOption(NATSCCFG_NAME, mName, true);
584 m->NATRunner.setOption(NATSCCFG_TRUNKTYPE, Utf8Str(aTrunkType), true);
585 m->NATRunner.setOption(NATSCCFG_IPADDRESS, m->IPv4Gateway, true);
586 m->NATRunner.setOption(NATSCCFG_NETMASK, m->IPv4NetworkMask, true);
587
588 if (m->fNeedDhcpServer)
589 {
590 /**
591 * Just to as idea... via API (on creation user pass the cidr of network and)
592 * and we calculate it's addreses (mutable?).
593 */
594
595 /*
596 * Configuration and running DHCP server:
597 * 1. find server first createDHCPServer
598 * 2. if return status is E_INVALARG => server already exists just find and start.
599 * 3. if return status neither E_INVALRG nor S_OK => return E_FAIL
600 * 4. if return status S_OK proceed to DHCP server configuration
601 * 5. call setConfiguration() and pass all required parameters
602 * 6. start dhcp server.
603 */
604 int rc = mVirtualBox->FindDHCPServerByNetworkName(mName.raw(),
605 m->dhcpServer.asOutParam());
606 switch (rc)
607 {
608 case E_INVALIDARG:
609 /* server haven't beeen found let create it then */
610 rc = mVirtualBox->CreateDHCPServer(mName.raw(),
611 m->dhcpServer.asOutParam());
612 if (FAILED(rc))
613 return E_FAIL;
614 /* breakthrough */
615 case S_OK:
616 {
617 LogFunc(("gateway: %s, dhcpserver:%s, dhcplowerip:%s, dhcpupperip:%s\n",
618 Utf8Str(m->IPv4Gateway.raw()).c_str(),
619 Utf8Str(m->IPv4DhcpServer.raw()).c_str(),
620 Utf8Str(m->IPv4DhcpServerLowerIp.raw()).c_str(),
621 Utf8Str(m->IPv4DhcpServerUpperIp.raw()).c_str()));
622
623
624 rc = m->dhcpServer->SetEnabled(true);
625 BSTR dhcpip = NULL;
626 BSTR netmask = NULL;
627 BSTR lowerip = NULL;
628 BSTR upperip = NULL;
629 m->IPv4DhcpServer.cloneTo(&dhcpip);
630 m->IPv4NetworkMask.cloneTo(&netmask);
631
632 m->IPv4DhcpServerLowerIp.cloneTo(&lowerip);
633 m->IPv4DhcpServerUpperIp.cloneTo(&upperip);
634 rc = m->dhcpServer->SetConfiguration(dhcpip,
635 netmask,
636 lowerip,
637 upperip);
638 break;
639 }
640
641 default:
642 return E_FAIL;
643 }
644
645 rc = m->dhcpServer->Start(mName.raw(), Bstr("").raw(), aTrunkType);
646 if (FAILED(rc))
647 {
648 m->dhcpServer.setNull();
649 return E_FAIL;
650 }
651 }
652
653 if (RT_SUCCESS(m->NATRunner.start()))
654 {
655 mVirtualBox->onNATNetworkStartStop(mName.raw(), TRUE);
656 return S_OK;
657 }
658 else return E_FAIL;
659#else
660 NOREF(aTrunkType);
661 return E_NOTIMPL;
662#endif
663}
664
665STDMETHODIMP NATNetwork::Stop()
666{
667#ifdef VBOX_WITH_NAT_SERVICE
668 if (RT_SUCCESS(m->NATRunner.stop()))
669 {
670 mVirtualBox->onNATNetworkStartStop(mName.raw(), FALSE);
671 return S_OK;
672 }
673 else return E_FAIL;
674
675#else
676 return E_NOTIMPL;
677#endif
678}
679
680void NATNetwork::GetPortForwardRulesFromMap(ComSafeArrayOut(BSTR, aPortForwardRules), NATRuleMap& aRules)
681{
682 com::SafeArray<BSTR> sf(aRules.size());
683 size_t i = 0;
684 NATRuleMap::const_iterator it;
685 for (it = aRules.begin();
686 it != aRules.end(); ++it, ++i)
687 {
688 settings::NATRule r = it->second;
689 BstrFmt bstr("%s,%d,%s,%d,%s,%d",
690 r.strName.c_str(),
691 r.proto,
692 r.strHostIP.c_str(),
693 r.u16HostPort,
694 r.strGuestIP.c_str(),
695 r.u16GuestPort);
696 bstr.detachTo(&sf[i]);
697 }
698 sf.detachTo(ComSafeArrayOutArg(aPortForwardRules));
699}
700
701int NATNetwork::RecalculateIpv4AddressAssignments()
702{
703 /**
704 * We assume that port-forwarding rules set is empty!
705 * possible scenarious on change of CIDR we clean up (1) pfs
706 * or (2) rewrite all rules to new network.
707 */
708 AssertReturn(m->mapName2PortForwardRule4.empty(), VERR_INTERNAL_ERROR);
709 RTNETADDRIPV4 network, netmask, gateway;
710 char aszGatewayIp[16], aszNetmask[16];
711 RT_ZERO(aszNetmask);
712 int rc = RTCidrStrToIPv4(Utf8Str(m->IPv4NetworkCidr.raw()).c_str(),
713 &network,
714 &netmask);
715 AssertRCReturn(rc, rc);
716
717 /* I don't remember the reason CIDR calcualted in host */
718 gateway.u = network.u;
719
720 gateway.u += 1;
721 gateway.u = RT_H2N_U32(gateway.u);
722 RTStrPrintf(aszGatewayIp, 16, "%RTnaipv4", gateway);
723 m->IPv4Gateway = RTStrDup(aszGatewayIp);
724 if (m->fNeedDhcpServer)
725 {
726 RTNETADDRIPV4 dhcpserver,
727 dhcplowerip,
728 dhcpupperip;
729 char aszNetwork[16],
730 aszDhcpIp[16],
731 aszDhcpLowerIp[16],
732 aszDhcpUpperIp[16];
733 RT_ZERO(aszNetwork);
734
735 RT_ZERO(aszDhcpIp);
736 RT_ZERO(aszDhcpLowerIp);
737 RT_ZERO(aszDhcpUpperIp);
738
739 dhcpserver.u = network.u;
740 dhcpserver.u += 2;
741
742
743 /* XXX: adding more services should change the math here */
744 dhcplowerip.u = RT_H2N_U32(dhcpserver.u + 1);
745 dhcpupperip.u = RT_H2N_U32((network.u | (~netmask.u)) -1);
746 dhcpserver.u = RT_H2N_U32(dhcpserver.u);
747 network.u = RT_H2N_U32(network.u);
748
749 RTStrPrintf(aszNetwork, 16, "%RTnaipv4", network);
750 RTStrPrintf(aszDhcpLowerIp, 16, "%RTnaipv4", dhcplowerip);
751 RTStrPrintf(aszDhcpUpperIp, 16, "%RTnaipv4", dhcpupperip);
752 RTStrPrintf(aszDhcpIp, 16, "%RTnaipv4", dhcpserver);
753
754 m->IPv4DhcpServer = aszDhcpIp;
755 m->IPv4DhcpServerLowerIp = aszDhcpLowerIp;
756 m->IPv4DhcpServerUpperIp = aszDhcpUpperIp;
757 LogFunc(("network: %RTnaipv4, dhcpserver:%RTnaipv4, dhcplowerip:%RTnaipv4, dhcpupperip:%RTnaipv4\n", network, dhcpserver, dhcplowerip, dhcpupperip));
758 }
759 /* we need IPv4NetworkMask for NAT's gw service start */
760 netmask.u = RT_H2N_U32(netmask.u);
761 RTStrPrintf(aszNetmask, 16, "%RTnaipv4", netmask);
762 m->IPv4NetworkMask = aszNetmask;
763 LogFlowFunc(("getaway:%RTnaipv4, netmask:%RTnaipv4\n", gateway, netmask));
764 return VINF_SUCCESS;
765}
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