VBoxNetFlt-darwin.cpp revision c0b6af690ad705bddfa87c643b89770a7a0aaf5a
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VBoxNetFlt - Network Filter Driver (Host), Darwin Specific Code.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Copyright (C) 2006-2014 Oracle Corporation
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * available from http://www.virtualbox.org. This file is free software;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f44080df90cb90c1e524d97c8e327b40298f3c6vboxsync * General Public License (GPL) as published by the Free Software
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync* Header Files *
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync*******************************************************************************/
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * Deal with conflicts first.
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * PVM - BSD mess, that FreeBSD has correct a long time ago.
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * iprt/types.h before sys/param.h - prevents UINT32_C and friends.
2f44080df90cb90c1e524d97c8e327b40298f3c6vboxsync#include "../../darwin/VBoxNetSend.h"
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsyncRT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync/*******************************************************************************
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync* Defined Constants And Macros *
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync*******************************************************************************/
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync/** The maximum number of SG segments.
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync * Used to prevent stack overflow and similar bad stuff. */
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync/** For testing extremely segmented frames. */
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync/*******************************************************************************
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync* Internal Functions *
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync*******************************************************************************/
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsyncstatic kern_return_t VBoxNetFltDarwinStart(struct kmod_info *pKModInfo, void *pvData);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic kern_return_t VBoxNetFltDarwinStop(struct kmod_info *pKModInfo, void *pvData);
2f44080df90cb90c1e524d97c8e327b40298f3c6vboxsync/*******************************************************************************
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync* Structures and Typedefs *
a0d1e40cc56a54314af0a1a4b5e13905ffd78393vboxsync*******************************************************************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * The mbuf tag data.
befdf0665bb07332302fed3ded8f2bc6a9695c52vboxsync * We have to associate the ethernet header with each packet we're sending
befdf0665bb07332302fed3ded8f2bc6a9695c52vboxsync * because things like icmp will inherit the tag it self so the tag along
befdf0665bb07332302fed3ded8f2bc6a9695c52vboxsync * isn't sufficient to identify our mbufs. For the icmp scenario the ethernet
befdf0665bb07332302fed3ded8f2bc6a9695c52vboxsync * header naturally changes before the packet is send pack, so let check it.
befdf0665bb07332302fed3ded8f2bc6a9695c52vboxsync /** The ethernet header of the outgoing frame. */
befdf0665bb07332302fed3ded8f2bc6a9695c52vboxsync/** Pointer to a VBoxNetFlt mbuf tag. */
static unsigned g_offIfNetPCount = sizeof(void *) * (1 /*if_softc*/ + 1 /*if_name*/ + 2 /*if_link*/ + 2 /*if_addrhead*/ + 1 /*if_check_multi*/)
static bool g_fNetPCountFound = false;
if (g_fNetPCountFound)
Log(("VBoxNetFltDarwinDetectPCountOffset: Adjusted if_pcount offset to %x from %x.\n", offTry1, g_offIfNetPCount));
g_fNetPCountFound = true;
LogRel(("VBoxNetFlt: Failed to detect promiscuous count, all traffic may reach wire (%x != %x).\n", g_offIfNetPCount, offTry1));
int rc;
if (!err)
return KMOD_RETURN_SUCCESS;
RTR0Term();
return KMOD_RETURN_FAILURE;
return KMOD_RETURN_FAILURE;
RTR0Term();
return KMOD_RETURN_SUCCESS;
if (pIfNet)
return pIfNet;
if (pIfNet)
if (err)
if (!pEthHdr)
if (!pEthHdr)
if (!err)
if (!err)
err = mbuf_tag_allocate(pPkt, g_idTag, 0 /* type */, sizeof(VBOXNETFLTTAG) /* tag len */, How, (void **)&pTagData);
if (!err)
return pPkt;
return NULL;
DECLINLINE(unsigned) vboxNetFltDarwinMBufCalcSGSegs(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame)
unsigned cSegs = 0;
cSegs++;
else if ( !cSegs
&& pvFrame
cSegs++;
#ifdef PADD_RUNT_FRAMES_FROM_HOST
cSegs++;
DECLINLINE(void) vboxNetFltDarwinMBufToSG(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
unsigned iSeg = 0;
if (cbSeg)
Assert(pvStart && pvSeg && offSeg < mbuf_maxlen(pMBuf) && offSegEnd <= mbuf_maxlen(pMBuf)); NOREF(offSegEnd);
AssertMsgFailed(("pvFrame=%p pvStart=%p pvSeg=%p offSeg=%p cbSeg=%#zx offSegEnd=%p offFrame=%p maxlen=%#zx\n",
iSeg++;
else if ( !iSeg
&& pvFrame
iSeg++;
#ifdef PADD_RUNT_FRAMES_FROM_HOST
while (iSrc > 0)
iDst--;
iSrc--;
iDst = 0;
iDst++;
bool fRc = false;
if (pIfNet)
return fRc;
if (pIfNet)
static errno_t vboxNetFltDarwinIffIoCtl(void *pvThis, ifnet_t pIfNet, protocol_family_t eProtocol, u_long uCmd, void *pvArg)
return EOPNOTSUPP;
static void vboxNetFltDarwinIffEvent(void *pvThis, ifnet_t pIfNet, protocol_family_t eProtocol, const struct kev_msg *pEvMsg)
if (!err)
Log(("vboxNetFltDarwinIffEvent: enabled promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pIfNet)));
Log(("vboxNetFltDarwinIffEvent: ifnet_set_promiscuous failed on %s, err=%d (%d)\n", pThis->szName, err, VBOX_GET_PCOUNT(pIfNet)));
if (!err)
Log(("vboxNetFltDarwinIffEvent: fixed IFF_PROMISC on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pIfNet)));
Log(("vboxNetFltDarwinIffEvent: online, '%s'. flags=%#x (%d)\n", pThis->szName, ifnet_flags(pIfNet), VBOX_GET_PCOUNT(pIfNet)));
Log(("vboxNetFltDarwinIffEvent: pThis->u.s.pIfNet=%p pIfNet=%p (%d)\n", pThis->u.s.pIfNet, pIfNet, VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : -1));
static errno_t vboxNetFltDarwinIffInputOutputWorker(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame,
if (!pMBuf)
bool fDropIt = false;
if (fDropIt)
fDropIt = false;
static errno_t vboxNetFltDarwinIffOutput(void *pvThis, ifnet_t pIfNet, protocol_family_t eProtocol, mbuf_t *ppMBuf)
return vboxNetFltDarwinIffInputOutputWorker((PVBOXNETFLTINS)pvThis, *ppMBuf, NULL, INTNETTRUNKDIR_HOST, eProtocol);
static errno_t vboxNetFltDarwinIffInput(void *pvThis, ifnet_t pIfNet, protocol_family_t eProtocol, mbuf_t *ppMBuf, char **ppchFrame)
return vboxNetFltDarwinIffInputOutputWorker((PVBOXNETFLTINS)pvThis, *ppMBuf, *ppchFrame, INTNETTRUNKDIR_WIRE, eProtocol);
LogFlow(("vboxNetFltSendDummy: a dummy packet has been successfully sent in order to prevent stuck-in-dock issue\n"));
LogFlow(("vboxNetFltSendDummy: unable to send dummy packet in order to prevent stuck-in-dock issue\n"));
if (err)
if (!fRediscovery)
return VERR_INTNET_FLT_IF_NOT_FOUND;
if (!err)
if ( !pIfNet
pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltDarwinIsPromiscuous(pThis));
pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
if (pIfNet)
LogRel(("VBoxFltDrv: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr));
return rc;
if (pIfNet)
if (pMBuf)
if (err)
if (pMBuf)
if (err)
return rc;
if (pIfNet)
if (fActive)
if (fActive)
if (!err)
if (!err)
if (!err)
if (!err)
Log(("vboxNetFlt: fixed IFF_PROMISC on %s (%d->%d)\n", pThis->szName, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
Log(("VBoxNetFlt: ifnet_set_promiscuous -> err=%d grr! (%d->%d)\n", err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
else if (!err)
Log(("VBoxNetFlt: Waiting for the link to come up... (%d->%d)\n", cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
if (err)
LogRel(("VBoxNetFlt: Failed to put '%s' into promiscuous mode, err=%d (%d->%d)\n", pThis->szName, err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
return VINF_SUCCESS;
return VINF_SUCCESS;
if (pIfFilter)
if (pIfFilter)
//pThis->u.s.MacAddr = {0};
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;