NATNetworkImpl.cpp revision d32ee79929c09a2d5c985ed48c93385e9e0ee28a
/* $Id$ */
/** @file
* INATNetwork implementation.
*/
/*
* Copyright (C) 2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "NetworkServiceRunner.h"
#include "DHCPServerImpl.h"
#include "NATNetworkImpl.h"
#include "AutoCaller.h"
#include "Logging.h"
#include <VBox/settings.h>
#include "EventImpl.h"
#include "VBoxEvents.h"
#include "VirtualBoxImpl.h"
#include <algorithm>
#include <list>
#ifndef RT_OS_WINDOWS
#else
# define IN_LOOPBACKNET 127
#endif
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
struct NATNetwork::Data
{
Data()
{
}
virtual ~Data(){}
#ifdef VBOX_WITH_NAT_SERVICE
#endif
};
: mVirtualBox(NULL)
{
}
NATNetwork::~NATNetwork()
{
}
{
return BaseFinalConstruct();
}
void NATNetwork::FinalRelease()
{
uninit ();
}
void NATNetwork::uninit()
{
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
return;
delete m;
m = NULL;
}
{
AutoInitSpan autoInitSpan(this);
/* share VirtualBox weakly (parent remains NULL so far) */
m = new Data();
m->offGateway = 1;
m->IPv4NetworkCidr = "10.0.2.0/24";
m->IPv6Prefix = "fe80::/64";
/* Confirm a successful initialization */
return S_OK;
}
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
/* share VirtualBox weakly (parent remains NULL so far) */
m = new Data();
m->llNATLoopbackOffsetList.clear();
/* IPv4 port-forward rules */
{
}
/* IPv6 port-forward rules */
{
}
return S_OK;
}
#ifdef NAT_XML_SERIALIZATION
{
AutoCaller autoCaller(this);
/* saving ipv4 port-forward Rules*/
/* saving ipv6 port-forward Rules*/
m->llNATLoopbackOffsetList.end());
m->IPv4NetworkCidr.raw(),
m->IPv4Gateway.raw(),
return S_OK;
}
#endif /* NAT_XML_SERIALIZATION */
{
AutoCaller autoCaller(this);
/* event source is const, no need to lock */
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
// save the global settings; for that we should hold only the VirtualBox lock
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
/* silently ignore network cidr update */
if (m->mapName2PortForwardRule4.empty())
{
#ifdef NAT_XML_SERIALIZATION
#endif
}
return rc;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
// save the global settings; for that we should hold only the VirtualBox lock
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
/* silently ignore network cidr update */
if (m->mapName2PortForwardRule6.empty())
{
/* @todo: do we need recalculation ? */
#ifdef NAT_XML_SERIALIZATION
#endif
}
return rc;
}
STDMETHODIMP NATNetwork::COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(BOOL *aAdvertiseDefaultIPv6Route)
{
AutoCaller autoCaller(this);
return S_OK;
}
STDMETHODIMP NATNetwork::COMSETTER(AdvertiseDefaultIPv6RouteEnabled)(BOOL aAdvertiseDefaultIPv6Route)
{
AutoCaller autoCaller(this);
// save the global settings; for that we should hold only the VirtualBox lock
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
AutoCaller autoCaller(this);
*aNeedDhcpServer = m->fNeedDhcpServer;
return S_OK;
}
{
AutoCaller autoCaller(this);
// save the global settings; for that we should hold only the VirtualBox lock
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
AutoCaller autoCaller(this);
size_t i = 0;
{
}
return S_OK;
}
{
AutoCaller autoCaller(this);
//AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if (RT_FAILURE(rc))
return E_INVALIDARG;
/* check against 127/8 */
return E_INVALIDARG;
/* check against networkid vs network mask */
if (RT_FAILURE(rc))
return E_INVALIDARG;
return E_INVALIDARG;
m->llNATLoopbackOffsetList.end(),
{
if (aOffset == 0) /* erase */
else /* modify */
{
m->llNATLoopbackOffsetList.end(),
return E_INVALIDARG; /* this offset is already registered. */
}
return mVirtualBox->saveSettings();
}
/* injection */
m->llNATLoopbackOffsetList.end(),
return E_INVALIDARG; /* offset is already registered. */
return mVirtualBox->saveSettings();
}
{
AutoCaller autoCaller(this);
*aLoopbackIp6 = m->u32LoopbackIp6;
return S_OK;
}
{
AutoCaller autoCaller(this);
m->u32LoopbackIp6 = aLoopbackIp6;
return mVirtualBox->saveSettings();
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
switch (aProto)
{
case NATProtocol_TCP:
proto = "tcp";
break;
case NATProtocol_UDP:
proto = "udp";
break;
default:
return E_INVALIDARG;
}
{
return setError(E_INVALIDARG,
tr("A NAT rule of this name already exists"));
&& r.u16HostPort == aHostPort
return setError(E_INVALIDARG,
tr("A NAT rule for this host port and this host IP already exists"));
}
r.u16HostPort = aHostPort;
r.strGuestIP = aGuestIp;
r.u16GuestPort = aGuestPort;
/* Notify listerners listening on this network only */
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
AutoCaller autoCaller(this);
return E_INVALIDARG;
/* Notify listerners listening on this network only */
#ifdef NAT_XML_SERIALIZATION
#endif
return rc;
}
{
#ifdef VBOX_WITH_NAT_SERVICE
AutoCaller autoCaller(this);
/* No portforwarding rules from command-line, all will be fetched via API */
if (m->fNeedDhcpServer)
{
/*
* Just to as idea... via API (on creation user pass the cidr of network and)
* and we calculate it's addreses (mutable?).
*/
/*
* Configuration and running DHCP server:
* 1. find server first createDHCPServer
* 2. if return status is E_INVALARG => server already exists just find and start.
* 3. if return status neither E_INVALRG nor S_OK => return E_FAIL
* 4. if return status S_OK proceed to DHCP server configuration
* 5. call setConfiguration() and pass all required parameters
* 6. start dhcp server.
*/
m->dhcpServer.asOutParam());
switch (rc)
{
case E_INVALIDARG:
/* server haven't beeen found let create it then */
m->dhcpServer.asOutParam());
return E_FAIL;
/* breakthrough */
{
LogFunc(("gateway: %s, dhcpserver:%s, dhcplowerip:%s, dhcpupperip:%s\n",
upperip);
}
case S_OK:
break;
default:
return E_FAIL;
}
{
m->dhcpServer.setNull();
return E_FAIL;
}
}
{
return S_OK;
}
/** @todo missing setError()! */
return E_FAIL;
#else
#endif
}
{
#ifdef VBOX_WITH_NAT_SERVICE
if (!m->dhcpServer.isNull())
m->dhcpServer->Stop();
{
return S_OK;
}
/** @todo missing setError()! */
return E_FAIL;
#else
#endif
}
void NATNetwork::GetPortForwardRulesFromMap(ComSafeArrayOut(BSTR, aPortForwardRules), NATRuleMap& aRules)
{
size_t i = 0;
{
r.u16HostPort,
r.strGuestIP.c_str(),
r.u16GuestPort);
}
}
{
&network,
&netmask);
{
if (off == m->offGateway)
continue;
continue;
bool skip = false;
++it)
{
{
skip = true;
break;
}
}
if (!skip)
break;
}
if (poff)
return VINF_SUCCESS;
}
{
&network,
&netmask);
if (m->fNeedDhcpServer)
/* I don't remember the reason CIDR calculated on the host. */
gateway.u += m->offGateway;
char szTmpIp[16];
m->IPv4Gateway = szTmpIp;
if (m->fNeedDhcpServer)
{
dhcpserver.u += m->offDhcp;
/* XXX: adding more services should change the math here */
m->IPv4DhcpServer = szTmpIp;
m->IPv4DhcpServerLowerIp = szTmpIp;
m->IPv4DhcpServerUpperIp = szTmpIp;
LogFunc(("network:%RTnaipv4, dhcpserver:%RTnaipv4, dhcplowerip:%RTnaipv4, dhcpupperip:%RTnaipv4\n",
}
/* we need IPv4NetworkMask for NAT's gw service start */
m->IPv4NetworkMask = szTmpIp;
return VINF_SUCCESS;
}