summaryrefslogtreecommitdiff
path: root/src/VBox/NetworkServices/NetLib
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/NetworkServices/NetLib
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/NetworkServices/NetLib')
-rw-r--r--src/VBox/NetworkServices/NetLib/ComHostUtils.cpp215
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetARP.cpp4
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp619
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h144
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp2
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetLib.h2
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetPortForwardString.cpp349
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp8
-rw-r--r--src/VBox/NetworkServices/NetLib/VBoxPortForwardString.h56
-rw-r--r--src/VBox/NetworkServices/NetLib/cpp/utils.h34
-rw-r--r--src/VBox/NetworkServices/NetLib/shared_ptr.h82
-rw-r--r--src/VBox/NetworkServices/NetLib/utils.h133
12 files changed, 1520 insertions, 128 deletions
diff --git a/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp b/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp
new file mode 100644
index 00000000..33452364
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp
@@ -0,0 +1,215 @@
+/* $Id: ComHostUtils.cpp $ */
+/** @file
+ * ComHostUtils.cpp
+ */
+
+/*
+ * 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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#ifdef RT_OS_WINDOWS
+# define VBOX_COM_OUTOFPROC_MODULE
+#endif
+#include <VBox/com/com.h>
+#include <VBox/com/listeners.h>
+#include <VBox/com/string.h>
+#include <VBox/com/Guid.h>
+#include <VBox/com/array.h>
+#include <VBox/com/ErrorInfo.h>
+#include <VBox/com/errorprint.h>
+#include <VBox/com/EventQueue.h>
+#include <VBox/com/VirtualBox.h>
+
+#include <iprt/alloca.h>
+#include <iprt/buildconfig.h>
+#include <iprt/err.h>
+#include <iprt/net.h> /* must come before getopt */
+#include <iprt/getopt.h>
+#include <iprt/initterm.h>
+#include <iprt/message.h>
+#include <iprt/param.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/time.h>
+#include <iprt/string.h>
+
+
+#include "../NetLib/VBoxNetLib.h"
+#include "../NetLib/shared_ptr.h"
+
+#include <vector>
+#include <list>
+#include <string>
+#include <map>
+
+#include "../NetLib/VBoxNetBaseService.h"
+
+#ifdef RT_OS_WINDOWS /* WinMain */
+# include <Windows.h>
+# include <stdlib.h>
+# ifdef INET_ADDRSTRLEN
+/* On Windows INET_ADDRSTRLEN defined as 22 Ws2ipdef.h, because it include port number */
+# undef INET_ADDRSTRLEN
+# endif
+# define INET_ADDRSTRLEN 16
+#else
+# include <netinet/in.h>
+#endif
+
+#include "utils.h"
+
+
+VBOX_LISTENER_DECLARE(NATNetworkListenerImpl)
+
+
+int localMappings(const ComNatPtr& nat, AddressToOffsetMapping& mapping)
+{
+ mapping.clear();
+
+ ComBstrArray strs;
+ int cStrs;
+ HRESULT hrc = nat->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));
+ if ( SUCCEEDED(hrc)
+ && (cStrs = strs.size()))
+ {
+ for (int i = 0; i < cStrs; ++i)
+ {
+ char szAddr[17];
+ RTNETADDRIPV4 ip4addr;
+ char *pszTerm;
+ uint32_t u32Off;
+ com::Utf8Str strLo2Off(strs[i]);
+ const char *pszLo2Off = strLo2Off.c_str();
+
+ RT_ZERO(szAddr);
+
+ pszTerm = RTStrStr(pszLo2Off, "=");
+
+ if ( pszTerm
+ && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN)
+ {
+ memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));
+ int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);
+ if (RT_SUCCESS(rc))
+ {
+ u32Off = RTStrToUInt32(pszTerm + 1);
+ if (u32Off != 0)
+ mapping.insert(
+ AddressToOffsetMapping::value_type(ip4addr, u32Off));
+ }
+ }
+ }
+ }
+ else
+ return VERR_NOT_FOUND;
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * @note: const dropped here, because of map<K,V>::operator[] which isn't const, map<K,V>::at() has const
+ * variant but it's C++11.
+ */
+int hostDnsServers(const ComHostPtr& host, const RTNETADDRIPV4& networkid,
+ /*const*/ AddressToOffsetMapping& mapping, AddressList& servers)
+{
+ servers.clear();
+
+ ComBstrArray strs;
+ if (SUCCEEDED(host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs))))
+ {
+ RTNETADDRIPV4 addr;
+ int rc;
+
+ for (unsigned int i = 0; i < strs.size(); ++i)
+ {
+ rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);
+ if (RT_SUCCESS(rc))
+ {
+ if (addr.au8[0] == 127)
+ {
+ /* XXX: here we want map<K,V>::at(const K& k) const */
+ if (mapping[addr] != 0)
+ {
+ addr.u = RT_H2N_U32(RT_N2H_U32(networkid.u)
+ + mapping[addr]);
+ }
+ else
+ continue; /* XXX: Warning here (local mapping wasn't registered) */
+ }
+
+ servers.push_back(addr);
+ }
+ }
+ }
+ else
+ return VERR_NOT_FOUND;
+
+ return VINF_SUCCESS;
+}
+
+
+int hostDnsSearchList(const ComHostPtr& host, std::vector<std::string>& strings)
+{
+ strings.clear();
+
+ ComBstrArray strs;
+ if (SUCCEEDED(host->COMGETTER(SearchStrings)(ComSafeArrayAsOutParam(strs))))
+ {
+ for (unsigned int i = 0; i < strs.size(); ++i)
+ {
+ strings.push_back(com::Utf8Str(strs[i]).c_str());
+ }
+ }
+ else
+ return VERR_NOT_FOUND;
+
+ return VINF_SUCCESS;
+}
+
+
+int hostDnsDomain(const ComHostPtr& host, std::string& domainStr)
+{
+ com::Bstr domain;
+ if (SUCCEEDED(host->COMGETTER(DomainName)(domain.asOutParam())))
+ {
+ domainStr = com::Utf8Str(domain).c_str();
+ return VINF_SUCCESS;
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+
+int createNatListener(ComNatListenerPtr& listener, const ComVirtualBoxPtr& vboxptr,
+ NATNetworkEventAdapter *adapter, /* const */ ComEventTypeArray& events)
+{
+ ComObjPtr<NATNetworkListenerImpl> obj;
+ HRESULT hrc = obj.createObject();
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+ hrc = obj->init(new NATNetworkListener(), adapter);
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+ ComPtr<IEventSource> esVBox;
+ hrc = vboxptr->COMGETTER(EventSource)(esVBox.asOutParam());
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+ listener = obj;
+
+ hrc = esVBox->RegisterListener(listener, ComSafeArrayAsInParam(events), true);
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+ return VINF_SUCCESS;
+}
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetARP.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetARP.cpp
index ec5ed275..9cced5d2 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetARP.cpp
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetARP.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -43,7 +43,7 @@ bool VBoxNetArpHandleIt(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF
*/
PCINTNETHDR pHdr = IntNetRingGetNextFrameToRead(&pBuf->Recv);
if ( !pHdr
- || pHdr->u16Type != INTNETHDR_TYPE_FRAME)
+ || pHdr->u8Type != INTNETHDR_TYPE_FRAME)
return false;
size_t cbFrame = pHdr->cbFrame;
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
index 435a1cb8..8e0cfd27 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
@@ -21,6 +21,16 @@
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_NET_SERVICE
+#include <VBox/com/com.h>
+#include <VBox/com/listeners.h>
+#include <VBox/com/string.h>
+#include <VBox/com/Guid.h>
+#include <VBox/com/array.h>
+#include <VBox/com/ErrorInfo.h>
+#include <VBox/com/errorprint.h>
+#include <VBox/com/VirtualBox.h>
+#include <VBox/com/NativeEventQueue.h>
+
#include <iprt/alloca.h>
#include <iprt/buildconfig.h>
#include <iprt/err.h>
@@ -29,19 +39,24 @@
#include <iprt/initterm.h>
#include <iprt/param.h>
#include <iprt/path.h>
+#include <iprt/process.h>
#include <iprt/stream.h>
#include <iprt/string.h>
#include <iprt/time.h>
+#include <iprt/thread.h>
#include <iprt/mem.h>
+#include <iprt/message.h>
#include <VBox/sup.h>
#include <VBox/intnet.h>
+#include <VBox/intnetinline.h>
#include <VBox/vmm/vmm.h>
#include <VBox/version.h>
#include <vector>
#include <string>
+#include <VBox/err.h>
#include <VBox/log.h>
#include "VBoxNetLib.h"
@@ -56,6 +71,65 @@
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
+struct VBoxNetBaseService::Data
+{
+ Data(const std::string& aName, const std::string& aNetworkName):
+ m_Name(aName),
+ m_Network(aNetworkName),
+ m_enmTrunkType(kIntNetTrunkType_WhateverNone),
+ m_pSession(NIL_RTR0PTR),
+ m_cbSendBuf(128 * _1K),
+ m_cbRecvBuf(256 * _1K),
+ m_hIf(INTNET_HANDLE_INVALID),
+ m_pIfBuf(NULL),
+ m_cVerbosity(0),
+ m_fNeedMain(false),
+ m_EventQ(NULL),
+ m_hThrRecv(NIL_RTTHREAD),
+ fShutdown(false)
+ {
+ int rc = RTCritSectInit(&m_csThis);
+ AssertRC(rc);
+ };
+
+ std::string m_Name;
+ std::string m_Network;
+ std::string m_TrunkName;
+ INTNETTRUNKTYPE m_enmTrunkType;
+
+ RTMAC m_MacAddress;
+ RTNETADDRIPV4 m_Ipv4Address;
+ RTNETADDRIPV4 m_Ipv4Netmask;
+
+ PSUPDRVSESSION m_pSession;
+ uint32_t m_cbSendBuf;
+ uint32_t m_cbRecvBuf;
+ INTNETIFHANDLE m_hIf; /**< The handle to the network interface. */
+ PINTNETBUF m_pIfBuf; /**< Interface buffer. */
+
+ std::vector<PRTGETOPTDEF> m_vecOptionDefs;
+
+ int32_t m_cVerbosity;
+
+ /* cs for syncing */
+ RTCRITSECT m_csThis;
+
+ /* Controls whether service will connect SVC for runtime needs */
+ bool m_fNeedMain;
+ /* Event Queue */
+ com::NativeEventQueue *m_EventQ;
+
+ /** receiving thread, used only if main is used */
+ RTTHREAD m_hThrRecv;
+
+ bool fShutdown;
+ static int recvLoop(RTTHREAD, void *);
+};
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/* Commonly used options for network configuration */
static RTGETOPTDEF g_aGetOptDef[] =
{
{ "--name", 'N', RTGETOPT_REQ_STRING },
@@ -64,50 +138,104 @@ static RTGETOPTDEF g_aGetOptDef[] =
{ "--trunk-type", 'T', RTGETOPT_REQ_STRING },
{ "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
{ "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
+ { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
{ "--verbose", 'v', RTGETOPT_REQ_NOTHING },
+ { "--need-main", 'M', RTGETOPT_REQ_BOOL },
};
-VBoxNetBaseService::VBoxNetBaseService()
+
+
+int VBoxNetBaseService::Data::recvLoop(RTTHREAD, void *pvUser)
{
+ VBoxNetBaseService *pThis = static_cast<VBoxNetBaseService *>(pvUser);
+
+ HRESULT hrc = com::Initialize();
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+ pThis->doReceiveLoop();
+
+ return VINF_SUCCESS;
}
+
+
+VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
+{
+ m = new VBoxNetBaseService::Data(aName, aNetworkName);
+
+ for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
+ m->m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
+}
+
+
VBoxNetBaseService::~VBoxNetBaseService()
{
/*
* Close the interface connection.
*/
- if (m_hIf != INTNET_HANDLE_INVALID)
+ if (m != NULL)
{
- INTNETIFCLOSEREQ CloseReq;
- CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
- CloseReq.Hdr.cbReq = sizeof(CloseReq);
- CloseReq.pSession = m_pSession;
- CloseReq.hIf = m_hIf;
- m_hIf = INTNET_HANDLE_INVALID;
- int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
- AssertRC(rc);
- }
+ shutdown();
+ if (m->m_hIf != INTNET_HANDLE_INVALID)
+ {
+ INTNETIFCLOSEREQ CloseReq;
+ CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+ CloseReq.Hdr.cbReq = sizeof(CloseReq);
+ CloseReq.pSession = m->m_pSession;
+ CloseReq.hIf = m->m_hIf;
+ m->m_hIf = INTNET_HANDLE_INVALID;
+ int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
+ AssertRC(rc);
+ }
- if (m_pSession)
- {
- SUPR3Term(false /*fForced*/);
- m_pSession = NIL_RTR0PTR;
+ if (m->m_pSession != NIL_RTR0PTR)
+ {
+ SUPR3Term(false /*fForced*/);
+ m->m_pSession = NIL_RTR0PTR;
+ }
+
+ RTCritSectDelete(&m->m_csThis);
+
+ delete m;
+ m = NULL;
}
}
+
int VBoxNetBaseService::init()
{
- /* numbers from DrvIntNet */
- m_cbSendBuf = 36 * _1K;
- m_cbRecvBuf = 218 * _1K;
- m_hIf = INTNET_HANDLE_INVALID;
- m_pIfBuf = NULL;
+ if (isMainNeeded())
+ {
+ HRESULT hrc = com::Initialize();
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+ hrc = virtualbox.createLocalObject(CLSID_VirtualBox);
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+ }
- m_cVerbosity = 0;
- m_Name = "VBoxNetNAT";
- m_Network = "intnet";
- for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
- m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
return VINF_SUCCESS;
}
+
+
+bool VBoxNetBaseService::isMainNeeded() const
+{
+ return m->m_fNeedMain;
+}
+
+
+int VBoxNetBaseService::run()
+{
+ /**
+ * If child class need Main we start receving thread which calls doReceiveLoop and enter to event polling loop
+ * and for the rest clients we do receiving on the current (main) thread.
+ */
+ if (isMainNeeded())
+ return startReceiveThreadAndEnterEventLoop();
+ else
+ {
+ doReceiveLoop();
+ return VINF_SUCCESS;
+ }
+}
+
/**
* Parse the arguments.
*
@@ -121,8 +249,12 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
RTGETOPTSTATE State;
PRTGETOPTDEF paOptionArray = getOptionsPtr();
- int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
+ int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
AssertRCReturn(rc, 49);
+#if 0
+ /* default initialization */
+ m_enmTrunkType = kIntNetTrunkType_WhateverNone;
+#endif
Log2(("BaseService: parseArgs enter\n"));
for (;;)
@@ -133,58 +265,74 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
break;
switch (rc)
{
- case 'N':
- m_Name = Val.psz;
+ case 'N': // --name
+ m->m_Name = Val.psz;
break;
- case 'n':
- m_Network = Val.psz;
+
+ case 'n': // --network
+ m->m_Network = Val.psz;
break;
- case 't':
- m_TrunkName = Val.psz;
+
+ case 't': //--trunk-name
+ m->m_TrunkName = Val.psz;
break;
- case 'T':
+
+ case 'T': //--trunk-type
if (!strcmp(Val.psz, "none"))
- m_enmTrunkType = kIntNetTrunkType_None;
+ m->m_enmTrunkType = kIntNetTrunkType_None;
else if (!strcmp(Val.psz, "whatever"))
- m_enmTrunkType = kIntNetTrunkType_WhateverNone;
+ m->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
else if (!strcmp(Val.psz, "netflt"))
- m_enmTrunkType = kIntNetTrunkType_NetFlt;
+ m->m_enmTrunkType = kIntNetTrunkType_NetFlt;
else if (!strcmp(Val.psz, "netadp"))
- m_enmTrunkType = kIntNetTrunkType_NetAdp;
+ m->m_enmTrunkType = kIntNetTrunkType_NetAdp;
else if (!strcmp(Val.psz, "srvnat"))
- m_enmTrunkType = kIntNetTrunkType_SrvNat;
+ m->m_enmTrunkType = kIntNetTrunkType_SrvNat;
else
{
RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
return 1;
}
break;
- case 'a':
- m_MacAddress = Val.MacAddr;
+
+ case 'a': // --mac-address
+ m->m_MacAddress = Val.MacAddr;
break;
- case 'i':
- m_Ipv4Address = Val.IPv4Addr;
+
+ case 'i': // --ip-address
+ m->m_Ipv4Address = Val.IPv4Addr;
break;
- case 'v':
- m_cVerbosity++;
+ case 'm': // --netmask
+ m->m_Ipv4Netmask = Val.IPv4Addr;
break;
- case 'V':
+ case 'v': // --verbose
+ m->m_cVerbosity++;
+ break;
+
+ case 'V': // --version (missed)
RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision());
return 1;
- case 'h':
- RTPrintf("VBoxNetDHCP Version %s\n"
+ case 'M': // --need-main
+ m->m_fNeedMain = true;
+ break;
+
+ case 'h': // --help (missed)
+ RTPrintf("%s Version %sr%u\n"
"(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
"All rights reserved.\n"
"\n"
- "Usage: VBoxNetDHCP <options>\n"
+ "Usage: %s <options>\n"
"\n"
"Options:\n",
- RTBldCfgVersion());
- for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++)
- RTPrintf(" -%c, %s\n", m_vecOptionDefs[i]->iShort, m_vecOptionDefs[i]->pszLong);
+ RTProcShortName(),
+ RTBldCfgVersion(),
+ RTBldCfgRevision(),
+ RTProcShortName());
+ for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
+ RTPrintf(" -%c, %s\n", m->m_vecOptionDefs[i]->iShort, m->m_vecOptionDefs[i]->pszLong);
usage(); /* to print Service Specific usage */
return 1;
@@ -203,17 +351,18 @@ int VBoxNetBaseService::parseArgs(int argc, char **argv)
return rc;
}
+
int VBoxNetBaseService::tryGoOnline(void)
{
/*
* Open the session, load ring-0 and issue the request.
*/
- int rc = SUPR3Init(&m_pSession);
+ int rc = SUPR3Init(&m->m_pSession);
if (RT_FAILURE(rc))
{
- m_pSession = NIL_RTR0PTR;
+ m->m_pSession = NIL_RTR0PTR;
LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
- return 1;
+ return rc;
}
char szPath[RTPATH_MAX];
@@ -221,14 +370,14 @@ int VBoxNetBaseService::tryGoOnline(void)
if (RT_FAILURE(rc))
{
LogRel(("VBoxNetBaseService: RTPathExecDir -> %Rrc\n", rc));
- return 1;
+ return rc;
}
rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
if (RT_FAILURE(rc))
{
LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
- return 1;
+ return rc;
}
/*
@@ -238,15 +387,15 @@ int VBoxNetBaseService::tryGoOnline(void)
INTNETOPENREQ OpenReq;
OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
OpenReq.Hdr.cbReq = sizeof(OpenReq);
- OpenReq.pSession = m_pSession;
- strncpy(OpenReq.szNetwork, m_Network.c_str(), sizeof(OpenReq.szNetwork));
+ OpenReq.pSession = m->m_pSession;
+ strncpy(OpenReq.szNetwork, m->m_Network.c_str(), sizeof(OpenReq.szNetwork));
OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
- strncpy(OpenReq.szTrunk, m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
+ strncpy(OpenReq.szTrunk, m->m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
- OpenReq.enmTrunkType = m_enmTrunkType;
+ OpenReq.enmTrunkType = m->m_enmTrunkType;
OpenReq.fFlags = 0; /** @todo check this */
- OpenReq.cbSend = m_cbSendBuf;
- OpenReq.cbRecv = m_cbRecvBuf;
+ OpenReq.cbSend = m->m_cbSendBuf;
+ OpenReq.cbRecv = m->m_cbRecvBuf;
OpenReq.hIf = INTNET_HANDLE_INVALID;
/*
@@ -257,10 +406,10 @@ int VBoxNetBaseService::tryGoOnline(void)
if (RT_FAILURE(rc))
{
Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
- goto bad;
+ return rc;
}
- m_hIf = OpenReq.hIf;
- Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m_hIf));
+ m->m_hIf = OpenReq.hIf;
+ Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
/*
* Get the ring-3 address of the shared interface buffer.
@@ -268,20 +417,20 @@ int VBoxNetBaseService::tryGoOnline(void)
INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
- GetBufferPtrsReq.pSession = m_pSession;
- GetBufferPtrsReq.hIf = m_hIf;
+ GetBufferPtrsReq.pSession = m->m_pSession;
+ GetBufferPtrsReq.hIf = m->m_hIf;
GetBufferPtrsReq.pRing3Buf = NULL;
GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
if (RT_FAILURE(rc))
{
Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
- goto bad;
+ return rc;
}
pBuf = GetBufferPtrsReq.pRing3Buf;
Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
- m_pIfBuf = pBuf;
+ m->m_pIfBuf = pBuf;
/*
* Activate the interface.
@@ -289,8 +438,8 @@ int VBoxNetBaseService::tryGoOnline(void)
INTNETIFSETACTIVEREQ ActiveReq;
ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
- ActiveReq.pSession = m_pSession;
- ActiveReq.hIf = m_hIf;
+ ActiveReq.pSession = m->m_pSession;
+ ActiveReq.hIf = m->m_hIf;
ActiveReq.fActive = true;
rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
if (RT_SUCCESS(rc))
@@ -299,26 +448,313 @@ int VBoxNetBaseService::tryGoOnline(void)
/* bail out */
Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
- return 0;
- bad:
- return 1;
+ return VINF_SUCCESS;
}
+
void VBoxNetBaseService::shutdown(void)
{
+ syncEnter();
+ m->fShutdown = true;
+ syncLeave();
+}
+
+
+int VBoxNetBaseService::syncEnter()
+{
+ return RTCritSectEnter(&m->m_csThis);
+}
+
+
+int VBoxNetBaseService::syncLeave()
+{
+ return RTCritSectLeave(&m->m_csThis);
+}
+
+
+int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
+{
+ int rc = VINF_SUCCESS;
+ INTNETIFWAITREQ WaitReq;
+ LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
+ WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+ WaitReq.Hdr.cbReq = sizeof(WaitReq);
+ WaitReq.pSession = m->m_pSession;
+ WaitReq.hIf = m->m_hIf;
+ WaitReq.cMillies = cMillis;
+
+ rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/* S/G API */
+int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
+{
+ PINTNETHDR pHdr = NULL;
+ uint8_t *pu8Frame = NULL;
+
+ /* Allocate frame */
+ int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
+ AssertRCReturn(rc, rc);
+
+ /* Now we fill pvFrame with S/G above */
+ int offFrame = 0;
+ for (int idxSg = 0; idxSg < cSg; ++idxSg)
+ {
+ memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
+ offFrame+=pcSg[idxSg].cb;
+ }
+
+ /* Commit */
+ IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
}
/**
- * Print debug message depending on the m_cVerbosity level.
- *
- * @param iMinLevel The minimum m_cVerbosity level for this message.
- * @param fMsg Whether to dump parts for the current DHCP message.
- * @param pszFmt The message format string.
- * @param ... Optional arguments.
+ * forcible ask for send packet on the "wire"
*/
-inline void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
+void VBoxNetBaseService::flushWire()
{
- if (iMinLevel <= m_cVerbosity)
+ int rc = VINF_SUCCESS;
+ INTNETIFSENDREQ SendReq;
+ SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+ SendReq.Hdr.cbReq = sizeof(SendReq);
+ SendReq.pSession = m->m_pSession;
+ SendReq.hIf = m->m_hIf;
+ rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
+ AssertRCReturnVoid(rc);
+ LogFlowFuncLeave();
+
+}
+
+
+int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+ void const *pvData, size_t cbData) const
+{
+ return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
+ m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
+ uDstPort, pvData, cbData);
+
+}
+
+
+const std::string VBoxNetBaseService::getName() const
+{
+ return m->m_Name;
+}
+
+
+void VBoxNetBaseService::setName(const std::string& aName)
+{
+ m->m_Name = aName;
+}
+
+
+const std::string VBoxNetBaseService::getNetwork() const
+{
+ return m->m_Network;
+}
+
+
+void VBoxNetBaseService::setNetwork(const std::string& aNetwork)
+{
+ m->m_Network = aNetwork;
+}
+
+
+const RTMAC VBoxNetBaseService::getMacAddress() const
+{
+ return m->m_MacAddress;
+}
+
+
+void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
+{
+ m->m_MacAddress = aMac;
+}
+
+
+const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
+{
+ return m->m_Ipv4Address;
+}
+
+
+void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
+{
+ m->m_Ipv4Address = aAddress;
+}
+
+
+const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
+{
+ return m->m_Ipv4Netmask;
+}
+
+
+void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
+{
+ m->m_Ipv4Netmask = aNetmask;
+}
+
+
+uint32_t VBoxNetBaseService::getSendBufSize() const
+{
+ return m->m_cbSendBuf;
+}
+
+
+void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
+{
+ m->m_cbSendBuf = cbBuf;
+}
+
+
+uint32_t VBoxNetBaseService::getRecvBufSize() const
+{
+ return m->m_cbRecvBuf;
+}
+
+
+void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
+{
+ m->m_cbRecvBuf = cbBuf;
+}
+
+
+int32_t VBoxNetBaseService::getVerbosityLevel() const
+{
+ return m->m_cVerbosity;
+}
+
+
+void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
+{
+ m->m_cVerbosity = aVerbosity;
+}
+
+
+void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
+{
+ m->m_vecOptionDefs.push_back(optDef);
+}
+
+
+void VBoxNetBaseService::doReceiveLoop()
+{
+ int rc;
+ /* Well we're ready */
+ PINTNETRINGBUF pRingBuf = &m->m_pIfBuf->Recv;
+
+ for (;;)
+ {
+ /*
+ * Wait for a packet to become available.
+ */
+ /* 2. waiting for request for */
+ rc = waitForIntNetEvent(2000);
+ if (RT_FAILURE(rc))
+ {
+ if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
+ {
+ /* do we want interrupt anyone ??? */
+ continue;
+ }
+ LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
+ AssertRCReturnVoid(rc);
+ }
+
+ /*
+ * Process the receive buffer.
+ */
+ PCINTNETHDR pHdr;
+
+ while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
+ {
+ uint8_t const u8Type = pHdr->u8Type;
+ size_t cbFrame = pHdr->cbFrame;
+ switch (u8Type)
+ {
+
+ case INTNETHDR_TYPE_FRAME:
+ {
+ void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
+ rc = processFrame(pvFrame, cbFrame);
+ if (RT_FAILURE(rc) && rc == VERR_IGNORED)
+ {
+ /* XXX: UDP + ARP for DHCP */
+ VBOXNETUDPHDRS Hdrs;
+ size_t cb;
+ void *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
+ VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST
+ | VBOXNETUDP_MATCH_CHECKSUM
+ | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
+ &Hdrs, &cb);
+ if (pv && cb)
+ processUDP(pv, cb);
+ else
+ VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
+ }
+ }
+ break;
+ case INTNETHDR_TYPE_GSO:
+ {
+ PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
+ rc = processGSO(pGso, cbFrame);
+ if (RT_FAILURE(rc) && rc == VERR_IGNORED)
+ break;
+ }
+ break;
+ case INTNETHDR_TYPE_PADDING:
+ break;
+ default:
+ break;
+ }
+ IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
+
+ } /* loop */
+ }
+
+}
+
+
+int VBoxNetBaseService::startReceiveThreadAndEnterEventLoop()
+{
+ AssertMsgReturn(isMainNeeded(), ("It's expected that we need Main"), VERR_INTERNAL_ERROR);
+
+ /* start receiving thread */
+ int rc = RTThreadCreate(&m->m_hThrRecv, /* thread handle*/
+ &VBoxNetBaseService::Data::recvLoop, /* routine */
+ this, /* user data */
+ 128 * _1K, /* stack size */
+ RTTHREADTYPE_IO, /* type */
+ 0, /* flags, @todo: waitable ?*/
+ "RECV");
+ AssertRCReturn(rc,rc);
+
+ m->m_EventQ = com::NativeEventQueue::getMainEventQueue();
+ AssertPtrReturn(m->m_EventQ, VERR_INTERNAL_ERROR);
+
+ while(true)
+ {
+ m->m_EventQ->processEventQueue(0);
+
+ if (m->fShutdown)
+ break;
+
+ m->m_EventQ->processEventQueue(500);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
+{
+ if (iMinLevel <= m->m_cVerbosity)
{
va_list va;
va_start(va, pszFmt);
@@ -332,32 +768,37 @@ inline void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const c
* Print debug message depending on the m_cVerbosity level.
*
* @param iMinLevel The minimum m_cVerbosity level for this message.
- * @param fMsg Whether to dump parts for the current DHCP message.
+ * @param fMsg Whether to dump parts for the current service message.
* @param pszFmt The message format string.
* @param va Optional arguments.
*/
void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
{
- if (iMinLevel <= m_cVerbosity)
+ if (iMinLevel <= m->m_cVerbosity)
{
va_list vaCopy; /* This dude is *very* special, thus the copy. */
va_copy(vaCopy, va);
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);
+ RTStrmPrintf(g_pStdErr, "%s: %s: %N\n",
+ RTProcShortName(),
+ iMinLevel >= 2 ? "debug" : "info",
+ pszFmt,
+ &vaCopy);
va_end(vaCopy);
}
}
+
PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
{
PRTGETOPTDEF pOptArray = NULL;
- pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m_vecOptionDefs.size());
+ pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
if (!pOptArray)
return NULL;
- for (unsigned int i = 0; i < m_vecOptionDefs.size(); ++i)
+ for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
{
- PRTGETOPTDEF pOpt = m_vecOptionDefs[i];
- memcpy(&pOptArray[i], m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
+ PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
+ memcpy(&pOptArray[i], m->m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
}
return pOptArray;
}
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
index eab9a515..a551bc88 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -17,45 +17,127 @@
#ifndef ___VBoxNetBaseService_h___
#define ___VBoxNetBaseService_h___
-class VBoxNetBaseService
+
+#include <iprt/critsect.h>
+
+
+class VBoxNetHlpUDPService
{
public:
- VBoxNetBaseService();
+virtual int hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+ void const *pvData, size_t cbData) const = 0;
+};
+
+
+class VBoxNetLockee
+{
+public:
+ virtual int syncEnter() = 0;
+ virtual int syncLeave() = 0;
+};
+
+
+class VBoxNetALock
+{
+public:
+ VBoxNetALock(VBoxNetLockee *a_lck):m_lck(a_lck)
+ {
+ if (m_lck)
+ m_lck->syncEnter();
+ }
+
+ ~VBoxNetALock()
+ {
+ if (m_lck)
+ m_lck->syncLeave();
+ }
+
+private:
+ VBoxNetLockee *m_lck;
+};
+
+# ifndef BASE_SERVICES_ONLY
+class VBoxNetBaseService: public VBoxNetHlpUDPService, public VBoxNetLockee
+{
+public:
+ VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName);
virtual ~VBoxNetBaseService();
int parseArgs(int argc, char **argv);
int tryGoOnline(void);
void shutdown(void);
+ int syncEnter();
+ int syncLeave();
+ int waitForIntNetEvent(int cMillis);
+ int sendBufferOnWire(PCINTNETSEG pSg, int cSg, size_t cbBuffer);
+ void flushWire();
+
+ virtual int hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+ void const *pvData, size_t cbData) const;
virtual void usage(void) = 0;
- virtual void run(void) = 0;
- virtual int init(void);
virtual int parseOpt(int rc, const RTGETOPTUNION& getOptVal) = 0;
+ virtual int processFrame(void *, size_t) = 0;
+ virtual int processGSO(PCPDMNETWORKGSO, size_t) = 0;
+ virtual int processUDP(void *, size_t) = 0;
- inline void debugPrint( int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const;
- void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
-public:
- /** @name The server configuration data members.
- * @{ */
- std::string m_Name;
- std::string m_Network;
- std::string m_TrunkName;
- INTNETTRUNKTYPE m_enmTrunkType;
- RTMAC m_MacAddress;
- RTNETADDRIPV4 m_Ipv4Address;
- /** @} */
- /** @name The network interface
- * @{ */
- PSUPDRVSESSION m_pSession;
- uint32_t m_cbSendBuf;
- uint32_t m_cbRecvBuf;
- INTNETIFHANDLE m_hIf; /**< The handle to the network interface. */
- PINTNETBUF m_pIfBuf; /**< Interface buffer. */
- std::vector<PRTGETOPTDEF> m_vecOptionDefs;
- /** @} */
- /** @name Debug stuff
- * @{ */
- int32_t m_cVerbosity;
-private:
+
+ virtual int init(void);
+ virtual int run(void);
+ virtual bool isMainNeeded() const;
+
+protected:
+ const std::string getName() const;
+ void setName(const std::string&);
+
+ const std::string getNetwork() const;
+ void setNetwork(const std::string&);
+
+ const RTMAC getMacAddress() const;
+ void setMacAddress(const RTMAC&);
+
+ const RTNETADDRIPV4 getIpv4Address() const;
+ void setIpv4Address(const RTNETADDRIPV4&);
+
+ const RTNETADDRIPV4 getIpv4Netmask() const;
+ void setIpv4Netmask(const RTNETADDRIPV4&);
+
+ uint32_t getSendBufSize() const;
+ void setSendBufSize(uint32_t);
+
+ uint32_t getRecvBufSize() const;
+ void setRecvBufSize(uint32_t);
+
+ int32_t getVerbosityLevel() const;
+ void setVerbosityLevel(int32_t);
+
+ void addCommandLineOption(const PRTGETOPTDEF);
+
+ /**
+ * Print debug message depending on the m_cVerbosity level.
+ *
+ * @param iMinLevel The minimum m_cVerbosity level for this message.
+ * @param fMsg Whether to dump parts for the current DHCP message.
+ * @param pszFmt The message format string.
+ * @param ... Optional arguments.
+ */
+ void debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const;
+ virtual void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
+
+ private:
+ void doReceiveLoop();
+
+ /** starts receiving thread and enter event polling loop. */
+ int startReceiveThreadAndEnterEventLoop();
+
+ protected:
+ /* VirtualBox instance */
+ ComPtr<IVirtualBox> virtualbox;
+
+ private:
+ struct Data;
+ Data *m;
+
+ private:
PRTGETOPTDEF getOptionsPtr();
- /** @} */
};
+# endif
#endif
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp
index 74a3998a..f9f7388f 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetLib.h b/src/VBox/NetworkServices/NetLib/VBoxNetLib.h
index e1150bfb..2f7f699d 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetLib.h
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetLib.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetPortForwardString.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetPortForwardString.cpp
new file mode 100644
index 00000000..c5333025
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetPortForwardString.cpp
@@ -0,0 +1,349 @@
+/* $Id: VBoxNetPortForwardString.cpp $ */
+/** @file
+ * VBoxNetPortForwardString - Routines for managing port-forward strings.
+ */
+
+/*
+ * Copyright (C) 2006-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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#ifndef RT_OS_WINDOWS
+#include <netinet/in.h>
+#else
+# include <Winsock2.h>
+# include <Ws2ipdef.h>
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/cidr.h>
+#include <iprt/param.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/string.h>
+#include <iprt/net.h>
+#include <iprt/getopt.h>
+#include <iprt/ctype.h>
+
+
+#include <VBox/log.h>
+
+#include "VBoxPortForwardString.h"
+
+
+#define PF_FIELD_SEPARATOR ':'
+#define PF_ADDRESS_FIELD_STARTS '['
+#define PF_ADDRESS_FIELD_ENDS ']'
+
+#define PF_STR_FIELD_SEPARATOR ":"
+#define PF_STR_ADDRESS_FIELD_STARTS "["
+#define PF_STR_ADDRESS_FIELD_ENDS "]"
+
+static int netPfStrAddressParse(char *pszRaw, int cbRaw,
+ char *pszAddress, int cbAddress,
+ bool fEmptyAcceptable)
+{
+ int idxRaw = 0;
+ int cbField = 0;
+
+ AssertPtrReturn(pszRaw, -1);
+ AssertPtrReturn(pszAddress, -1);
+ AssertReturn(pszRaw[0] == PF_ADDRESS_FIELD_STARTS, -1);
+
+ if (pszRaw[0] == PF_ADDRESS_FIELD_STARTS)
+ {
+ /* shift pszRaw to next symbol */
+ pszRaw++;
+ cbRaw--;
+
+
+ /* we shouldn't face with ending here */
+ AssertReturn(cbRaw > 0, VERR_INVALID_PARAMETER);
+
+ char *pszEndOfAddress = RTStrStr(pszRaw, PF_STR_ADDRESS_FIELD_ENDS);
+
+ /* no pair closing sign */
+ AssertPtrReturn(pszEndOfAddress, VERR_INVALID_PARAMETER);
+
+ cbField = pszEndOfAddress - pszRaw;
+
+ /* field should be less then the rest of the string */
+ AssertReturn(cbField < cbRaw, VERR_INVALID_PARAMETER);
+
+ if (cbField != 0)
+ RTStrCopy(pszAddress, RT_MIN(cbField + 1, cbAddress), pszRaw);
+ else if (!fEmptyAcceptable)
+ return -1;
+ }
+
+ AssertReturn(pszRaw[cbField] == PF_ADDRESS_FIELD_ENDS, -1);
+
+ return cbField + 2; /* length of the field and closing braces */
+}
+
+
+static int netPfStrPortParse(char *pszRaw, int cbRaw, uint16_t *pu16Port)
+{
+ char *pszEndOfPort = NULL;
+ uint16_t u16Port = 0;
+ int idxRaw = 1; /* we increment pszRaw after checks. */
+ int cbRest = 0;
+ size_t cbPort = 0;
+
+ AssertPtrReturn(pszRaw, -1);
+ AssertPtrReturn(pu16Port, -1);
+ AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, -1);
+
+ pszRaw++; /* skip line separator */
+ cbRaw --;
+
+ pszEndOfPort = RTStrStr(pszRaw, ":");
+ if (!pszEndOfPort)
+ {
+ cbRest = strlen(pszRaw);
+
+ Assert(cbRaw == cbRest);
+
+ /* XXX: Assumption that if string is too big, it will be reported by
+ * RTStrToUint16.
+ */
+ if (cbRest > 0)
+ {
+ pszEndOfPort = pszRaw + cbRest;
+ cbPort = cbRest;
+ }
+ else
+ return -1;
+ }
+ else
+ cbPort = pszEndOfPort - pszRaw;
+
+
+ idxRaw += cbPort;
+
+ Assert(cbRest || pszRaw[idxRaw - 1] == PF_FIELD_SEPARATOR); /* we are 1 char ahead */
+
+ char szPort[10];
+ RT_ZERO(szPort);
+
+ Assert(idxRaw > 0);
+ RTStrCopy(szPort, RT_MIN(sizeof(szPort), (size_t)(cbPort) + 1), pszRaw);
+
+ if (!(u16Port = RTStrToUInt16(szPort)))
+ return -1;
+
+ *pu16Port = u16Port;
+
+ return idxRaw;
+}
+
+
+static int netPfStrAddressPortPairParse(char *pszRaw, int cbRaw,
+ char *pszAddress, int cbAddress,
+ bool fEmptyAddressAcceptable,
+ uint16_t *pu16Port)
+{
+ int idxRaw = 0;
+ int idxRawTotal = 0;
+
+ AssertPtrReturn(pszRaw, -1);
+ AssertPtrReturn(pszAddress, -1);
+ AssertPtrReturn(pu16Port, -2);
+
+ /* XXX: Here we should check 0 - ':' and 1 - '[' */
+ Assert( pszRaw[0] == PF_FIELD_SEPARATOR
+ && pszRaw[1] == PF_ADDRESS_FIELD_STARTS);
+
+ pszRaw++; /* field separator skip */
+ cbRaw--;
+ AssertReturn(cbRaw > 0, VERR_INVALID_PARAMETER);
+
+ idxRaw = 0;
+
+ if (pszRaw[0] == PF_ADDRESS_FIELD_STARTS)
+ {
+ idxRaw += netPfStrAddressParse(pszRaw,
+ cbRaw - idxRaw,
+ pszAddress,
+ cbAddress,
+ fEmptyAddressAcceptable);
+ if (idxRaw == -1)
+ return -1;
+
+ Assert(pszRaw[idxRaw] == PF_FIELD_SEPARATOR);
+ }
+ else return -1;
+
+ pszRaw += idxRaw;
+ idxRawTotal += idxRaw;
+ cbRaw -= idxRaw;
+
+ AssertReturn(cbRaw > 0, VERR_INVALID_PARAMETER);
+
+ idxRaw = 0;
+
+ Assert(pszRaw[0] == PF_FIELD_SEPARATOR);
+
+ if (pszRaw[0] == PF_FIELD_SEPARATOR)
+ {
+ idxRaw = netPfStrPortParse(pszRaw, strlen(pszRaw), pu16Port);
+
+ Assert(strlen(&pszRaw[idxRaw]) == 0 || pszRaw[idxRaw] == PF_FIELD_SEPARATOR);
+
+ if (idxRaw == -1)
+ return -2;
+
+ idxRawTotal += idxRaw;
+
+ return idxRawTotal + 1;
+ }
+ else return -1; /* trailing garbage in the address */
+}
+
+/* XXX: Having fIPv6 we might emprove adress verification comparing address length
+ * with INET[6]_ADDRLEN
+ */
+int netPfStrToPf(const char *pcszStrPortForward, int fIPv6, PPORTFORWARDRULE pPfr)
+{
+ char *pszName;
+ int proto;
+ char *pszHostAddr;
+ char *pszGuestAddr;
+ uint16_t u16HostPort;
+ uint16_t u16GuestPort;
+ bool fTcpProto = false;
+
+ char *pszRawBegin = NULL;
+ char *pszRaw = NULL;
+ int idxRaw = 0;
+ int cbToken = 0;
+ int cbRaw = 0;
+ int rc = VINF_SUCCESS;
+
+ AssertPtrReturn(pcszStrPortForward, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pPfr, VERR_INVALID_PARAMETER);
+
+ memset(pPfr, 0, sizeof(PORTFORWARDRULE));
+
+ pszHostAddr = &pPfr->szPfrHostAddr[0];
+ pszGuestAddr = &pPfr->szPfrGuestAddr[0];
+ pszName = &pPfr->szPfrName[0];
+
+ cbRaw = strlen(pcszStrPortForward);
+
+ /* Minimal rule ":tcp:[]:0:[]:0" has got lenght 14 */
+ AssertReturn(cbRaw > 14, VERR_INVALID_PARAMETER);
+
+ pszRaw = RTStrDup(pcszStrPortForward);
+
+ AssertPtrReturn(pszRaw, VERR_NO_MEMORY);
+
+ pszRawBegin = pszRaw;
+
+ /* name */
+ if (pszRaw[idxRaw] == PF_FIELD_SEPARATOR)
+ idxRaw = 1; /* begin of the next segment */
+ else
+ {
+ char *pszEndOfName = RTStrStr(pszRaw + 1, PF_STR_FIELD_SEPARATOR);
+ if (!pszEndOfName)
+ goto invalid_parameter;
+
+ cbToken = (pszEndOfName) - pszRaw; /* don't take : into account */
+ /* XXX it's unacceptable to have only name entry in PF */
+ AssertReturn(cbToken < cbRaw, VERR_INVALID_PARAMETER);
+
+ if ( cbToken < 0
+ || (size_t)cbToken >= PF_NAMELEN)
+ goto invalid_parameter;
+
+ RTStrCopy(pszName,
+ RT_MIN((size_t)cbToken + 1, PF_NAMELEN),
+ pszRaw);
+ pszRaw += cbToken; /* move to separator */
+ }
+
+ AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, VERR_INVALID_PARAMETER);
+ /* protocol */
+
+ pszRaw++; /* skip separator */
+ idxRaw = 0;
+
+ cbRaw--;
+
+ if ( (( fTcpProto = (RTStrNICmp(pszRaw, "tcp", 3) == 0)
+ || (RTStrNICmp(pszRaw, "udp", 3) == 0))
+ && (pszRaw[3] == PF_FIELD_SEPARATOR)))
+ {
+ proto = (fTcpProto ? IPPROTO_TCP : IPPROTO_UDP);
+ idxRaw = 3;
+ }
+ else
+ goto invalid_parameter;
+
+ pszRaw += idxRaw;
+ cbRaw -= idxRaw;
+ idxRaw = 0;
+
+ idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw,
+ pszHostAddr, INET6_ADDRSTRLEN,
+ true, &u16HostPort);
+ if (idxRaw < 0)
+ return VERR_INVALID_PARAMETER;
+
+ pszRaw += idxRaw;
+ cbRaw -= idxRaw;
+
+ Assert(pszRaw[0] == PF_FIELD_SEPARATOR);
+
+ idxRaw = 0;
+
+ idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw,
+ pszGuestAddr,
+ INET6_ADDRSTRLEN,
+ false,
+ &u16GuestPort);
+
+ if (idxRaw < 0)
+ goto invalid_parameter;
+
+ /* XXX: fill the rule */
+ pPfr->fPfrIPv6 = fIPv6;
+ pPfr->iPfrProto = proto;
+
+ pPfr->u16PfrHostPort = u16HostPort;
+
+ if (*pszGuestAddr == '\0')
+ goto invalid_parameter; /* guest address should be defined */
+
+ pPfr->u16PfrGuestPort = u16GuestPort;
+
+ Log(("name: %s\n"
+ "proto: %d\n"
+ "host address: %s\n"
+ "host port: %d\n"
+ "guest address: %s\n"
+ "guest port:%d\n",
+ pszName, proto,
+ pszHostAddr, u16HostPort,
+ pszGuestAddr, u16GuestPort));
+
+ RTStrFree(pszRawBegin);
+ return VINF_SUCCESS;
+
+invalid_parameter:
+ RTStrFree(pszRawBegin);
+ if (pPfr)
+ memset(pPfr, 0, sizeof(PORTFORWARDRULE));
+ return VERR_INVALID_PARAMETER;
+}
diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp
index 79c40c27..508e07d8 100644
--- a/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp
+++ b/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -61,14 +61,14 @@ void *VBoxNetUDPMatch(PINTNETBUF pBuf, unsigned uDstPort, PCRTMAC pDstMac, uint3
*/
PCINTNETHDR pHdr = IntNetRingGetNextFrameToRead(&pBuf->Recv);
if ( !pHdr
- || ( pHdr->u16Type != INTNETHDR_TYPE_FRAME
- && pHdr->u16Type != INTNETHDR_TYPE_GSO))
+ || ( pHdr->u8Type != INTNETHDR_TYPE_FRAME
+ && pHdr->u8Type != INTNETHDR_TYPE_GSO))
return NULL;
size_t cbFrame = pHdr->cbFrame;
const void *pvFrame = IntNetHdrGetFramePtr(pHdr, pBuf);
PCPDMNETWORKGSO pGso = NULL;
- if (pHdr->u16Type == INTNETHDR_TYPE_GSO)
+ if (pHdr->u8Type == INTNETHDR_TYPE_GSO)
{
pGso = (PCPDMNETWORKGSO)pvFrame;
if (!PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(*pGso)))
diff --git a/src/VBox/NetworkServices/NetLib/VBoxPortForwardString.h b/src/VBox/NetworkServices/NetLib/VBoxPortForwardString.h
new file mode 100644
index 00000000..30264526
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/VBoxPortForwardString.h
@@ -0,0 +1,56 @@
+/* $Id: VBoxPortForwardString.h $ */
+/** @file
+ * VBoxPortForwardString
+ */
+
+/*
+ * Copyright (C) 2009-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+#ifndef ___VBoxPortForwardString_h___
+#define ___VBoxPortForwardString_h___
+
+#include <iprt/net.h>
+#include <VBox/intnet.h>
+
+RT_C_DECLS_BEGIN
+
+#define PF_NAMELEN 64
+/*
+ * TBD: Here is shared implementation of parsing port-forward string
+ * of format:
+ * name:[ipv4 or ipv6 address]:host-port:[ipv4 or ipv6 guest addr]:guest port
+ *
+ * This code supposed to be used in NetService and Frontend and perhaps in corresponding
+ * services.
+ *
+ * Note: ports are in host format.
+ */
+
+typedef struct PORTFORWARDRULE
+{
+ char szPfrName[PF_NAMELEN];
+ /* true if ipv6 and false otherwise */
+ int fPfrIPv6;
+ /* IPPROTO_{UDP,TCP} */
+ int iPfrProto;
+ char szPfrHostAddr[INET6_ADDRSTRLEN];
+ uint16_t u16PfrHostPort;
+ char szPfrGuestAddr[INET6_ADDRSTRLEN];
+ uint16_t u16PfrGuestPort;
+} PORTFORWARDRULE, *PPORTFORWARDRULE;
+
+int netPfStrToPf(const char *pcszStrPortForward,int fIPv6, PPORTFORWARDRULE pPfr);
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/src/VBox/NetworkServices/NetLib/cpp/utils.h b/src/VBox/NetworkServices/NetLib/cpp/utils.h
new file mode 100644
index 00000000..21224b36
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/cpp/utils.h
@@ -0,0 +1,34 @@
+/* $Id$ */
+/** @file
+ * NetLib/cpp/utils.h
+ */
+
+/*
+ * 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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+#ifndef _NETLIB_CPP_UTILS_H_
+# define _NETLIB_CPP_UTILS_H_
+
+/* less operator for IPv4 addresess */
+static bool operator <(const RTNETADDRIPV4& a, const RTNETADDRIPV4& b)
+{
+ return (RT_N2H_U32(a.u) < RT_N2H_U32(b.u));
+}
+
+/* Compares MAC addresses */
+static bool operator== (const RTMAC& lhs, const RTMAC& rhs)
+{
+ return ( lhs.au16[0] == rhs.au16[0]
+ && lhs.au16[1] == rhs.au16[1]
+ && lhs.au16[2] == rhs.au16[2]);
+}
+#endif
diff --git a/src/VBox/NetworkServices/NetLib/shared_ptr.h b/src/VBox/NetworkServices/NetLib/shared_ptr.h
new file mode 100644
index 00000000..ad892de7
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/shared_ptr.h
@@ -0,0 +1,82 @@
+#ifndef __SHARED_PTR_H__
+#define __SHARED_PTR_H__
+
+#ifdef __cplusplus
+template<typename T>
+class SharedPtr
+{
+ struct imp
+ {
+ imp(T *pTrg = NULL, int cnt = 1): ptr(pTrg),refcnt(cnt){}
+ ~imp() { if (ptr) delete ptr;}
+
+ T *ptr;
+ int refcnt;
+ };
+
+
+ public:
+ SharedPtr(T *t = NULL):p(NULL)
+ {
+ p = new imp(t);
+ }
+
+ ~SharedPtr()
+ {
+ p->refcnt--;
+
+ if (p->refcnt == 0)
+ delete p;
+ }
+
+
+ SharedPtr(const SharedPtr& rhs)
+ {
+ p = rhs.p;
+ p->refcnt++;
+ }
+
+ const SharedPtr& operator= (const SharedPtr& rhs)
+ {
+ if (p == rhs.p) return *this;
+
+ p->refcnt--;
+ if (p->refcnt == 0)
+ delete p;
+
+ p = rhs.p;
+ p->refcnt++;
+
+ return *this;
+ }
+
+
+ T *get() const
+ {
+ return p->ptr;
+ }
+
+
+ T *operator->()
+ {
+ return p->ptr;
+ }
+
+
+ const T*operator->() const
+ {
+ return p->ptr;
+ }
+
+
+ int use_count()
+ {
+ return p->refcnt;
+ }
+
+ private:
+ imp *p;
+};
+#endif
+
+#endif
diff --git a/src/VBox/NetworkServices/NetLib/utils.h b/src/VBox/NetworkServices/NetLib/utils.h
new file mode 100644
index 00000000..d96b5c03
--- /dev/null
+++ b/src/VBox/NetworkServices/NetLib/utils.h
@@ -0,0 +1,133 @@
+/* $Id: utils.h $ */
+/** @file
+ * ComHostUtils.cpp
+ */
+
+/*
+ * 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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#ifndef _NETLIB_UTILS_H_
+#define _NETLIB_UTILS_H_
+
+#include "cpp/utils.h"
+
+typedef ComPtr<IVirtualBox> ComVirtualBoxPtr;
+typedef ComPtr<IDHCPServer> ComDhcpServerPtr;
+typedef ComPtr<IHost> ComHostPtr;
+typedef ComPtr<INATNetwork> ComNatPtr;
+typedef com::SafeArray<BSTR> ComBstrArray;
+
+typedef std::vector<RTNETADDRIPV4> AddressList;
+typedef std::map<RTNETADDRIPV4, int> AddressToOffsetMapping;
+
+
+inline bool isDhcpRequired(const ComNatPtr& nat)
+{
+ BOOL fNeedDhcpServer = false;
+ if (FAILED(nat->COMGETTER(NeedDhcpServer)(&fNeedDhcpServer)))
+ return false;
+
+ return fNeedDhcpServer;
+}
+
+
+inline int findDhcpServer(const ComVirtualBoxPtr& vbox, const std::string& name, ComDhcpServerPtr& dhcp)
+{
+ HRESULT hrc = vbox->FindDHCPServerByNetworkName(com::Bstr(name.c_str()).raw(),
+ dhcp.asOutParam());
+ AssertComRCReturn(hrc, VERR_NOT_FOUND);
+
+ return VINF_SUCCESS;
+}
+
+
+inline int findNatNetwork(const ComVirtualBoxPtr& vbox, const std::string& name, ComNatPtr& nat)
+{
+ HRESULT hrc = vbox->FindNATNetworkByName(com::Bstr(name.c_str()).raw(),
+ nat.asOutParam());
+
+ AssertComRCReturn(hrc, VERR_NOT_FOUND);
+
+ return VINF_SUCCESS;
+}
+
+
+inline RTNETADDRIPV4 networkid(const RTNETADDRIPV4& addr, const RTNETADDRIPV4& netmask)
+{
+ RTNETADDRIPV4 netid;
+ netid.u = addr.u & netmask.u;
+ return netid;
+}
+
+
+int localMappings(const ComNatPtr&, AddressToOffsetMapping&);
+int hostDnsServers(const ComHostPtr&, const RTNETADDRIPV4&,/* const */ AddressToOffsetMapping&, AddressList&);
+int hostDnsSearchList(const ComHostPtr&, std::vector<std::string>&);
+int hostDnsDomain(const ComHostPtr&, std::string& domainStr);
+
+
+class NATNetworkEventAdapter
+{
+ public:
+ virtual HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent) = 0;
+};
+
+
+class NATNetworkListener
+{
+ public:
+ NATNetworkListener():m_pNAT(NULL){}
+
+ HRESULT init(NATNetworkEventAdapter *pNAT)
+ {
+ AssertPtrReturn(pNAT, E_INVALIDARG);
+
+ m_pNAT = pNAT;
+ return S_OK;
+ }
+
+ HRESULT init()
+ {
+ m_pNAT = NULL;
+ return S_OK;
+ }
+
+ void uninit() { m_pNAT = NULL; }
+
+ HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
+ {
+ if (m_pNAT)
+ return m_pNAT->HandleEvent(aEventType, pEvent);
+ else
+ return E_FAIL;
+ }
+
+ private:
+ NATNetworkEventAdapter *m_pNAT;
+};
+typedef ListenerImpl<NATNetworkListener, NATNetworkEventAdapter*> NATNetworkListenerImpl;
+
+# if VBOX_WITH_XPCOM
+class NS_CLASSINFO_NAME(NATNetworkListenerImpl);
+# endif
+
+typedef ComPtr<NATNetworkListenerImpl> ComNatListenerPtr;
+typedef com::SafeArray<VBoxEventType_T> ComEventTypeArray;
+
+/* XXX: const is commented out because of compilation erro on Windows host, but it's intended that this function
+ isn't modify event type array */
+int createNatListener(ComNatListenerPtr& listener, const ComVirtualBoxPtr& vboxptr,
+ NATNetworkEventAdapter *adapter, /* const */ ComEventTypeArray& events);
+#endif