VBoxNetBaseService.cpp revision 9b11211f1a9ed6c980794d624ce1af60f2033f2a
/* $Id$ */
/** @file
* VBoxNetDHCP - DHCP Service for connecting to IntNet.
*/
/** @todo r=bird: Cut&Past rules... Please fix DHCP refs! */
/*
* 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;
* 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 *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_NET_SERVICE
#include <iprt/buildconfig.h>
#include <iprt/initterm.h>
#include <VBox/intnetinline.h>
#include <vector>
#include <string>
#include "VBoxNetLib.h"
#include "VBoxNetBaseService.h"
#ifdef RT_OS_WINDOWS /* WinMain */
# include <Windows.h>
# include <stdlib.h>
#endif
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
struct VBoxNetBaseService::Data
{
m_cVerbosity(0),
m_fNeedMain(false),
fShutdown(false)
{
};
/* cs for syncing */
/* Controls whether service will connect SVC for runtime needs */
bool m_fNeedMain;
/* Event Queue */
/** receiving thread, used only if main is used */
bool fShutdown;
};
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/* Commonly used options for network configuration */
static RTGETOPTDEF g_aGetOptDef[] =
{
};
{
pThis->doReceiveLoop();
return VINF_SUCCESS;
}
VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
{
for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
}
{
/*
* Close the interface connection.
*/
if (m != NULL)
{
shutdown();
if (m->m_hIf != INTNET_HANDLE_INVALID)
{
m->m_hIf = INTNET_HANDLE_INVALID;
}
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()
{
if (isMainNeeded())
{
}
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
{
return VINF_SUCCESS;
}
}
/**
* Parse the arguments.
*
* @returns 0 on success, fully bitched exit code on failure.
*
* @param argc Argument count.
* @param argv Argument vector.
*/
{
int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
#if 0
/* default initialization */
#endif
Log2(("BaseService: parseArgs enter\n"));
for (;;)
{
if (!rc)
break;
switch (rc)
{
case 'N': // --name
break;
case 'n': // --network
break;
case 't': //--trunk-name
break;
case 'T': //--trunk-type
else
{
return 1;
}
break;
case 'a': // --mac-address
break;
case 'i': // --ip-address
break;
case 'm': // --netmask
break;
case 'v': // --verbose
m->m_cVerbosity++;
break;
case 'V': // --version (missed)
return 1;
case 'M': // --need-main
m->m_fNeedMain = true;
break;
case 'h': // --help (missed)
RTPrintf("%s Version %sr%u\n"
"All rights reserved.\n"
"\n"
"Usage: %s <options>\n"
"\n"
"Options:\n",
RTProcShortName());
for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
usage(); /* to print Service Specific usage */
return 1;
default:
if (RT_FAILURE(rc1))
{
RTPrintf("Use --help for more information.\n");
return rc;
}
}
}
return rc;
}
int VBoxNetBaseService::tryGoOnline(void)
{
/*
* Open the session, load ring-0 and issue the request.
*/
if (RT_FAILURE(rc))
{
m->m_pSession = NIL_RTR0PTR;
return rc;
}
char szPath[RTPATH_MAX];
if (RT_FAILURE(rc))
{
return rc;
}
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Create the open request.
*/
/*
* Issue the request.
*/
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Get the ring-3 address of the shared interface buffer.
*/
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));
return rc;
}
Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
/*
* Activate the interface.
*/
if (RT_SUCCESS(rc))
return 0;
/* bail out */
Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
/* ignore this error */
return VINF_SUCCESS;
}
void VBoxNetBaseService::shutdown(void)
{
syncEnter();
m->fShutdown = true;
if (m->m_hThrRecv != NIL_RTTHREAD)
{
if (RT_SUCCESS(rc))
{
if (RT_FAILURE(rc))
}
else
{
AssertMsgFailed(("interruptEventQueueProcessing() failed\n"));
}
}
syncLeave();
}
int VBoxNetBaseService::syncEnter()
{
return RTCritSectEnter(&m->m_csThis);
}
int VBoxNetBaseService::syncLeave()
{
return RTCritSectLeave(&m->m_csThis);
}
{
int rc = VINF_SUCCESS;
return rc;
}
/* S/G API */
{
/* Allocate frame */
/* Now we fill pvFrame with S/G above */
int offFrame = 0;
{
}
/* Commit */
return rc;
}
/**
* forcible ask for send packet on the "wire"
*/
void VBoxNetBaseService::flushWire()
{
int rc = VINF_SUCCESS;
}
{
}
{
return m->m_Name;
}
{
}
{
return m->m_Network;
}
{
}
{
return m->m_MacAddress;
}
{
m->m_MacAddress = aMac;
}
{
return m->m_Ipv4Address;
}
{
m->m_Ipv4Address = aAddress;
}
{
return m->m_Ipv4Netmask;
}
{
m->m_Ipv4Netmask = aNetmask;
}
{
return m->m_cbSendBuf;
}
{
m->m_cbSendBuf = cbBuf;
}
{
return m->m_cbRecvBuf;
}
{
m->m_cbRecvBuf = cbBuf;
}
{
return m->m_cVerbosity;
}
{
m->m_cVerbosity = aVerbosity;
}
{
}
void VBoxNetBaseService::doReceiveLoop()
{
int rc;
/* Well we're ready */
for (;;)
{
/*
* Wait for a packet to become available.
*/
/* 2. waiting for request for */
if (RT_FAILURE(rc))
{
{
/* do we want interrupt anyone ??? */
continue;
}
}
/*
* Process the receive buffer.
*/
{
switch (u8Type)
{
case INTNETHDR_TYPE_FRAME:
{
{
/* XXX: UDP + ARP for DHCP */
else
}
}
break;
case INTNETHDR_TYPE_GSO:
{
break;
}
break;
case INTNETHDR_TYPE_PADDING:
break;
default:
break;
}
} /* loop */
}
}
{
/* start receiving thread */
this, /* user data */
RTTHREADTYPE_IO, /* type */
0, /* flags, @todo: waitable ?*/
"RECV");
while (!m->fShutdown)
{
if (rc == VERR_INTERRUPTED)
{
break;
}
}
return VINF_SUCCESS;
}
{
if (iMinLevel <= m->m_cVerbosity)
{
}
}
/**
* 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 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->m_cVerbosity)
{
&vaCopy);
}
}
{
if (!pOptArray)
return NULL;
for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
{
}
return pOptArray;
}