DrvTAP.cpp revision ff88d4153cd65650577e8c2d1a5a3fdfa0404a80
c97989161fbe75bc14cea477a5443bbf474dd3advboxsync * Universial TAP network transport driver.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
38856343f90103280eb83b5e697f9f618b407d83vboxsync * available from http://www.virtualbox.org. This file is free software;
38856343f90103280eb83b5e697f9f618b407d83vboxsync * you can redistribute it and/or modify it under the terms of the GNU
c97989161fbe75bc14cea477a5443bbf474dd3advboxsync * General Public License (GPL) as published by the Free Software
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
38856343f90103280eb83b5e697f9f618b407d83vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
38856343f90103280eb83b5e697f9f618b407d83vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * additional information or have any questions.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync/*******************************************************************************
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync* Header Files *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync*******************************************************************************/
38856343f90103280eb83b5e697f9f618b407d83vboxsync/*******************************************************************************
38856343f90103280eb83b5e697f9f618b407d83vboxsync* Structures and Typedefs *
38856343f90103280eb83b5e697f9f618b407d83vboxsync*******************************************************************************/
428abad07de993cca3284d577dc65f3b1acd17d5vboxsync * Block driver instance data.
38856343f90103280eb83b5e697f9f618b407d83vboxsynctypedef struct DRVTAP
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The network interface. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The network interface. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** Pointer to the driver instance. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** TAP device file handle. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The configured TAP device name. */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** Crossbow: MAC address of the device. */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** Crossbow: Handle of the NIC. */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** IP device file handle (/dev/udp). */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** Whether device name is obtained from setup application. */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** TAP setup application. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** TAP terminate application. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The write end of the control pipe. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The read end of the control pipe. */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** Reader thread. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** Number of sent packets. */
b0553043536ae0bdf9921b91597f9dc6c316b1b4vboxsync /** Number of sent bytes. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** Number of received packets. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** Number of received bytes. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** Profiling packet transmit runs. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** Profiling packet receive runs. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync#endif /* VBOX_WITH_STATISTICS */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The nano ts of the last transfer. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync /** The nano ts of the last receive. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync/** Converts a pointer to TAP::INetworkConnector to a PRDVTAP. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync#define PDMINETWORKCONNECTOR_2_DRVTAP(pInterface) ( (PDRVTAP)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAP, INetworkConnector)) )
38856343f90103280eb83b5e697f9f618b407d83vboxsync/*******************************************************************************
38856343f90103280eb83b5e697f9f618b407d83vboxsync* Internal Functions *
38856343f90103280eb83b5e697f9f618b407d83vboxsync*******************************************************************************/
#ifdef LOG_ENABLED
return rc;
static DECLCALLBACK(void) drvTAPSetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous)
static DECLCALLBACK(void) drvTAPNotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState)
return VINF_SUCCESS;
errno=0;
if ( rc > 0
#ifdef VBOX_WITH_CROSSBOW
#ifdef LOG_ENABLED
else if ( rc > 0
LogFlow(("drvTAPAsyncIoThread: Control message: enmState=%d revents=%#x\n", pThread->enmState, aFDs[1].revents));
char ch;
Log(("rc=%d revents=%#x,%#x errno=%p %s\n", rc, aFDs[0].revents, aFDs[1].revents, errno, strerror(errno)));
AssertMsgFailed(("rc=%d revents=%#x,%#x errno=%p %s\n", rc, aFDs[0].revents, aFDs[1].revents, errno, strerror(errno)));
return VINF_SUCCESS;
return VINF_SUCCESS;
#if defined(RT_OS_SOLARIS)
* Calls OS-specific TAP setup application/script.
#ifdef VBOX_WITH_CROSSBOW
for (unsigned int i = 0; i < sizeof(RTMAC); i++)
*pMacAddr8++;
if (pfSetupHandle == 0)
return VERR_HOSTIF_INIT_FAILED;
return VERR_HOSTIF_INIT_FAILED;
return VERR_HOSTIF_INIT_FAILED;
return VERR_HOSTIF_INIT_FAILED;
return VINF_SUCCESS;
* Calls OS-specific TAP terminate application/script.
Log2(("Starting TAP terminate application: %s %s\n", pThis->pszTerminateApplication, pThis->pszDeviceName));
return VINF_SUCCESS;
LogRel(("TAP#%d: Error running TAP terminate application: %s\n", pThis->pDrvIns->iInstance, pThis->pszTerminateApplication));
LogRel(("TAP#%d: RTProcWait failed for: %s\n", pThis->pDrvIns->iInstance, pThis->pszTerminateApplication));
LogRel(("TAP#%d: Failed to fork() process for running TAP terminate application: %s\n", pThis->pDrvIns->iInstance,
return VERR_HOSTIF_TERM_FAILED;
#ifdef RT_OS_SOLARIS
# ifdef VBOX_WITH_CROSSBOW
rc = g_pfnLibDlpiSetPhysAddr(pThis->pDeviceHandle, DL_CURR_PHYS_ADDR, &pThis->MacAddress, ETHERADDRL);
return VINF_SUCCESS;
return rc;
switch (rc)
case DLPI_EVERNOTSUP:
case DLPI_EMODENOTSUP:
case DLPI_ERAWNOTSUP:
case DLPI_ENOLINK:
case DLPI_EBADLINK:
case DLPI_EBADMSG:
return VERR_UNRESOLVED_ERROR;
if (IPFileDes < 0)
if (TapFileDes < 0)
if (iPPA < 0)
if (!InterfaceFD)
LogRel(("TAP#%d: Failed to get interface flags after setting PPA. errno=%d\n", pThis->pDrvIns->iInstance, errno));
#ifdef VBOX_SOLARIS_TAP_ARP
LogRel(("TAP#%d: Failed to push ARP to Interface FD. errno=%d\n", pThis->pDrvIns->iInstance, errno));
if (ARPFileDes < 0)
LogRel(("TAP#%d: Failed to open for /dev/tap for ARP. errno=%d", pThis->pDrvIns->iInstance, errno));
#ifdef VBOX_SOLARIS_TAP_ARP
#ifdef VBOX_SOLARIS_TAP_ARP
#ifdef VBOX_SOLARIS_TAP_ARP
#ifdef VBOX_SOLARIS_TAP_ARP
return VINF_SUCCESS;
switch (enmInterface)
case PDMINTERFACE_BASE:
return NULL;
#ifdef RT_OS_SOLARIS
/** @todo r=bird: This *does* need checking against ConsoleImpl2.cpp if used on non-solaris systems. */
# ifndef VBOX_WITH_CROSSBOW
#ifdef RT_OS_SOLARIS
#ifdef RT_OS_SOLARIS
# ifdef VBOX_WITH_CROSSBOW
if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0InitProg\0TermProg\0FileHandle\0TAPSetupApplication\0TAPTerminateApplication\0MAC"))
pThis->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);
#if defined(RT_OS_SOLARIS) /** @todo Other platforms' TAP code should be moved here from ConsoleImpl & VBoxBFE. */
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Configuration error: failed to query \"TAPTerminateApplication\""));
rc = CFGMR3QueryStringAlloc(pCfgHandle, "TAPTerminateApplication", &pThis->pszTerminateApplication);
return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Configuration error: failed to query \"TAPTerminateApplication\""));
# ifdef VBOX_WITH_CROSSBOW
# ifdef VBOX_WITH_CROSSBOW
if (!VBoxLibDlpiFound())
return rc;
#ifdef RT_OS_L4
return rc;
rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPAsyncIoThread, drvTapAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "TAP");
#ifdef VBOX_WITH_STATISTICS
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSent, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of sent packets.", "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance);
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSentBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of sent bytes.", "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance);
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecv, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of received packets.", "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance);
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecvBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Number of received bytes.", "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance);
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.", "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
return rc;
sizeof(DRVTAP),
NULL,
NULL,
NULL,
NULL,
NULL,