VBoxNetNAT.cpp revision 82bcaaf8077ba892f39afb721dca149353c63d2c
/* $Id$ */
/** @file
* VBoxNetNAT - NAT Service for connecting to IntNet.
*/
/*
* Copyright (C) 2009 Sun Microsystems, Inc.
*
* 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.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/** @page pg_net_nat VBoxNetNAT
*
* Write a few words...
*
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/initterm.h>
#include <iprt/semaphore.h>
#define LOG_GROUP LOG_GROUP_NAT_SERVICE
#include <VBox/intnetinline.h>
#include <vector>
#include <string>
#include "../NetLib/VBoxNetLib.h"
#include "../NetLib/VBoxNetBaseService.h"
#include <libslirp.h>
#ifdef RT_OS_WINDOWS /* WinMain */
# include <Windows.h>
# include <stdlib.h>
#else
# include <errno.h>
#endif
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
class VBoxNetNAT : public VBoxNetBaseService
{
public:
VBoxNetNAT();
virtual ~VBoxNetNAT();
void usage(void);
void run(void);
void init(void);
public:
bool m_fPassDomain;
#ifdef RT_OS_WINDOWS
#else
#endif
/** Queue for NAT-thread-external events. */
/** event to wakeup the guest receive thread */
/** event to wakeup the guest urgent receive thread */
bool fIsRunning;
};
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** Pointer to the NAT server. */
class VBoxNetNAT *g_pNAT;
static void natNotifyNATThread();
void slirp_arm_fast_timer(void *pvUser)
{
}
void slirp_arm_slow_timer(void *pvUser)
{
}
{
}
{
}
static void natNotifyNATThread()
{
int rc;
#ifndef RT_OS_WINDOWS
/* kick select() */
#else
/* kick WSAWaitForMultipleEvents */
#endif
}
{
#if defined(RT_OS_WINDOWS)
/*@todo check if we can remove this*/
#endif
m_TrunkName = "";
m_Ipv4Netmask.u = 0xffff0000;
cPkt = 0;
cUrgPkt = 0;
}
VBoxNetNAT::~VBoxNetNAT() { }
void VBoxNetNAT::init()
{
int rc;
/*
* Initialize slirp.
*/
#ifndef RT_OS_WINDOWS
/*
* Create the control pipe.
*/
int fds[2];
{
return;
}
m_PipeRead = fds[0];
#else
#endif
rc = RTThreadCreate(&m_ThrSndNAT, natSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "SndNAT");
rc = RTThreadCreate(&m_ThrUrgSndNAT, natUrgSndThread, this, 128 * _1K, RTTHREADTYPE_DEFAULT, 0, "UrgSndNAT");
}
/* Mandatory functions */
void VBoxNetNAT::run()
{
/*
* The loop.
*/
fIsRunning = true;
//RTThreadSetType(RTThreadSelf(), RTTHREADTYPE_IO);
for (;;)
{
/*
* Wait for a packet to become available.
*/
WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */ /** @todo fix interruptability in SrvIntNet! */
#if 0
RTReqProcess(m_pSendQueue, 0);
#endif
if (RT_FAILURE(rc))
{
if (rc == VERR_TIMEOUT)
continue;
return;
}
/*
* Process the receive buffer.
*/
{
{
void *pvSlirpFrame;
if (!m)
{
LogRel(("NAT: Can't allocate send buffer\n"));
break;
}
/* don't wait, we have to wakeup the NAT thread fist */
#ifndef RT_OS_WINDOWS
/* kick select() */
#else
/* kick WSAWaitForMultipleEvents */
#endif
}
else
{
}
}
}
fIsRunning = false;
}
void VBoxNetNAT::usage()
{
}
/**
* Entry point.
*/
{
Log2(("NAT: main\n"));
g_pNAT = new VBoxNetNAT();
Log2(("NAT: parsing command line\n"));
Log2(("NAT: initialization\n"));
Log2(("NAT: try go online\n"));
g_pNAT->tryGoOnline();
Log2(("NAT: main loop\n"));
delete g_pNAT;
return 0;
}
/** slirp's hooks */
{
return 1;
}
{
int rc = RTReqCallEx(g_pNAT->m_pUrgSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
}
{
int rc = RTReqCallEx(g_pNAT->m_pSendQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
}
/**
* Worker function for drvNATSend().
* @thread "NAT" thread.
*/
{
}
{
Log2(("VBoxNetNAT: going to send some bytes ... \n"));
int rc;
if (!urg)
{
}
else
{
}
if (RT_FAILURE(rc))
{
}
if (RT_SUCCESS(rc))
{
}
if (RT_FAILURE(rc))
if (!urg)
{
}
else {
}
#ifdef VBOX_WITH_SLIRP_BSD_MBUF
#endif
}
{
int nFDs = -1;
unsigned int ms;
#ifdef RT_OS_WINDOWS
unsigned int cBreak = 0;
#else /* RT_OS_WINDOWS */
unsigned int cPollNegRet = 0;
#endif /* !RT_OS_WINDOWS */
#ifdef RT_OS_WINDOWS
#endif /* RT_OS_WINDOWS */
/*
* Polling loop.
*/
for(;;)
{
nFDs = -1;
/*
*/
#ifndef RT_OS_WINDOWS
/* allocation for all sockets + Management pipe */
return VERR_NO_MEMORY;
/* don't pass the managemant pipe */
/* POLLRDBAND usually doesn't used on Linux but seems used on Solaris */
if (cChangedFDs < 0)
{
{
Log2(("NAT: signal was caught while sleep on poll\n"));
/* No error, just process all outstanding requests but don't wait */
cChangedFDs = 0;
}
else if (cPollNegRet++ > 128)
{
cPollNegRet = 0;
}
}
if (cChangedFDs >= 0)
{
{
/* drain the pipe */
char ch[1];
int counter = 0;
/*
* drvNATSend decoupled so we don't know how many times
* device's thread sends before we've entered multiplex,
* so to avoid false alarm drain pipe here to the very end
*
* @todo: Probably we should counter drvNATSend to count how
* deep pipe has been filed before drain.
*
* XXX:Make it reading exactly we need to drain the pipe.
*/
}
}
/* process _all_ outstanding requests but don't wait */
#else /* RT_OS_WINDOWS */
&& event != WSA_WAIT_TIMEOUT)
{
int error = WSAGetLastError();
}
if (event == WSA_WAIT_TIMEOUT)
{
continue;
}
/* poll the sockets in any case */
/* process _all_ outstanding requests but don't wait */
#endif /* RT_OS_WINDOWS */
}
return VINF_SUCCESS;
}
{
while (g_pNAT->fIsRunning)
return VINF_SUCCESS;
}
{
while (g_pNAT->fIsRunning)
return VINF_SUCCESS;
}
#ifndef VBOX_WITH_HARDENING
{
int rc = RTR3InitAndSUPLib();
if (RT_FAILURE(rc))
{
return 1;
}
}
# if defined(RT_OS_WINDOWS)
)
{
if(uMsg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
}
{
bool bExit = false;
/* Register the Window Class. */
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(void *);
if (atomWindowClass != 0)
{
/* Create the window. */
if (hwnd)
{
{
}
bExit = true;
}
}
if(bExit)
{
/* no need any accuracy here, in anyway the DHCP server usually gets terminated with TerminateProcess */
exit(0);
}
return 0;
}
/** (We don't want a console usually.) */
{
#if 0
NULL, /*__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, */
0, /*__in SIZE_T dwStackSize, */
MsgThreadProc, /*__in LPTHREAD_START_ROUTINE lpStartAddress,*/
NULL, /*__in_opt LPVOID lpParameter,*/
0, /*__in DWORD dwCreationFlags,*/
NULL /*__out_opt LPDWORD lpThreadId*/
);
#endif
}
# endif /* RT_OS_WINDOWS */
#endif /* !VBOX_WITH_HARDENING */