VBoxNetAdp-darwin.cpp revision e8a169f512c942da921be71296b4234f787c7e3b
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/* $Id$ */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/** @file
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * VBoxNetAdp - Virtual Network Adapter Driver (Host), Darwin Specific Code.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/*
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * available from http://www.virtualbox.org. This file is free software;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * General Public License (GPL) as published by the Free Software
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * additional information or have any questions.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/*******************************************************************************
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync* Header Files *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync*******************************************************************************/
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Deal with conflicts first.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * PVM - BSD mess, that FreeBSD has correct a long time ago.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * iprt/types.h before sys/param.h - prevents UINT32_C and friends.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/types.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <sys/param.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#undef PVM
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <VBox/log.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <VBox/err.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <VBox/version.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/assert.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/initterm.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/semaphore.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/spinlock.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/string.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/uuid.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <iprt/alloca.h>
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <sys/systm.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync__BEGIN_DECLS /* Buggy 10.4 headers, fixed in 10.5. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <sys/kpi_mbuf.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync__END_DECLS
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <net/ethernet.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <net/if_ether.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <net/if_types.h>
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#include <sys/socket.h>
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#include <net/if.h>
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#include <net/if_dl.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <sys/errno.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include <sys/param.h>
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_OS_SPECFIC 1
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#include "../VBoxNetAdpInternal.h"
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/*******************************************************************************
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync* Defined Constants And Macros *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync*******************************************************************************/
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/** The maximum number of SG segments.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Used to prevent stack overflow and similar bad stuff. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_DARWIN_MAX_SEGS 32
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_DARWIN_MAX_FAMILIES 4
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_DARWIN_NAME "vboxnet"
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_DARWIN_MTU 1500
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_DARWIN_DETACH_TIMEOUT 500
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#define VBOXNETADP_FROM_IFACE(iface) ((PVBOXNETADP) ifnet_softc(iface))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/*******************************************************************************
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync* Internal Functions *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync*******************************************************************************/
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync__BEGIN_DECLS
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic kern_return_t VBoxNetAdpDarwinStart(struct kmod_info *pKModInfo, void *pvData);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic kern_return_t VBoxNetAdpDarwinStop(struct kmod_info *pKModInfo, void *pvData);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync__END_DECLS
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/*******************************************************************************
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync* Global Variables *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync*******************************************************************************/
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Declare the module stuff.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync__BEGIN_DECLS
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncextern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncextern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncKMOD_EXPLICIT_DECL(VBoxNetAdp, VBOX_VERSION_STRING, _start, _stop)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncDECLHIDDEN(kmod_start_func_t *) _realmain = VBoxNetAdpDarwinStart;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncDECLHIDDEN(kmod_stop_func_t *) _antimain = VBoxNetAdpDarwinStop;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncDECLHIDDEN(int) _kext_apple_cc = __APPLE_CC__;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync__END_DECLS
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The (common) global data.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic VBOXNETADPGLOBALS g_VBoxNetAdpGlobals;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Generate a suitable MAC address.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pThis The instance.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pMac Where to return the MAC address.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncDECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#if 0 /* Use a locally administered version of the OUI we use for the guest NICs. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[0] = 0x08 | 2;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[1] = 0x00;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[2] = 0x27;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#else /* this is what \0vb comes down to. It seems to be unassigned atm. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[0] = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[1] = 0x76;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[2] = 0x62;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[3] = 0; /* pThis->uUnit >> 16; */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[4] = 0; /* pThis->uUnit >> 8; */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pMac->au8[5] = pThis->uUnit;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic void vboxNetAdpDarwinComposeUUID(PVBOXNETADP pThis, PRTUUID pUuid)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Generate UUID from name and MAC address. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTUuidClear(pUuid);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memcpy(pUuid->au8, "vboxnet", 7);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pUuid->Gen.u8ClockSeqHiAndReserved = (pUuid->Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pUuid->Gen.u16TimeHiAndVersion = (pUuid->Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pUuid->Gen.u8ClockSeqLow = pThis->uUnit;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpComposeMACAddress(pThis, (PRTMAC)pUuid->Gen.au8Node);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Reads and retains the host interface handle.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @returns The handle, NULL if detached.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pThis
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncDECLINLINE(ifnet_t) vboxNetAdpDarwinRetainIfNet(PVBOXNETADP pThis)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (pThis->u.s.pIface)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync ifnet_reference(pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return pThis->u.s.pIface;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Release the host interface handle previously retained
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * by vboxNetAdpDarwinRetainIfNet.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pThis The instance.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pIfNet The vboxNetAdpDarwinRetainIfNet return value, NULL is fine.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncDECLINLINE(void) vboxNetAdpDarwinReleaseIfNet(PVBOXNETADP pThis, ifnet_t pIfNet)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync NOREF(pThis);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (pIfNet)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync ifnet_release(pIfNet);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Internal worker that create a darwin mbuf for a (scatter/)gather list.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Taken from VBoxNetAdp-darwin.cpp.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @returns Pointer to the mbuf.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pThis The instance.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pSG The (scatter/)gather list.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic mbuf_t vboxNetAdpDarwinMBufFromSG(PVBOXNETADP pThis, PINTNETSG pSG)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /// @todo future? mbuf_how_t How = preemtion enabled ? MBUF_DONTWAIT : MBUF_WAITOK;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_how_t How = MBUF_WAITOK;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * We can't make use of the physical addresses on darwin because the way the
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * mbuf / cluster stuffe works (see mbuf_data_to_physical and mcl_to_paddr).
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * So, because we're lazy, we will ASSUME that all SGs coming from INTNET
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * will only contain one single segment.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pSG->cSegsUsed == 1);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pSG->cbTotal == pSG->aSegs[0].cb);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pSG->cbTotal > 0);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * We need some way of getting back to our instance data when
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * the mbuf is freed, so use pvUserData for this.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * -- this is not relevant anylonger! --
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(!pSG->pvUserData || pSG->pvUserData == pThis);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(!pSG->pvUserData2);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->pvUserData = pThis;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Allocate a packet and copy over the data.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Using mbuf_attachcluster() here would've been nice but there are two
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * issues with it: (1) it's 10.5.x only, and (2) the documentation indicates
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * that it's not supposed to be used for really external buffers. The 2nd
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * point might be argued against considering that the only m_clattach user
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * is mallocs memory for the ext mbuf and not doing what's stated in the docs.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * However, it's hard to tell if these m_clattach buffers actually makes it
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * to the NICs or not, and even if they did, the NIC would need the physical
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * addresses for the pages they contain and might end up copying the data
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * to a new mbuf anyway.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * So, in the end it's better to just do it the simple way that will work
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * 100%, even if it involes some extra work (alloc + copy) we really wished
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * to avoid.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_t pPkt = NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync errno_t err = mbuf_allocpacket(How, pSG->cbTotal, NULL, &pPkt);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (!err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Skip zero sized memory buffers (paranoia). */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_t pCur = pPkt;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync while (pCur && !mbuf_maxlen(pCur))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pCur = mbuf_next(pCur);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pCur);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Set the required packet header attributes. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_pkthdr_setlen(pPkt, pSG->cbTotal);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_pkthdr_setheader(pPkt, mbuf_data(pCur));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Special case the single buffer copy. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if ( mbuf_next(pCur)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync && mbuf_maxlen(pCur) >= pSG->cbTotal)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_setlen(pCur, pSG->cbTotal);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memcpy(mbuf_data(pCur), pSG->aSegs[0].pv, pSG->cbTotal);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Multi buffer copying. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync size_t cbSrc = pSG->cbTotal;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync uint8_t const *pbSrc = (uint8_t const *)pSG->aSegs[0].pv;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync while (cbSrc > 0 && pCur)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync size_t cb = mbuf_maxlen(pCur);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (cbSrc < cb)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync cb = cbSrc;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_setlen(pCur, cb);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memcpy(mbuf_data(pCur), pbSrc, cb);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* advance */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pbSrc += cb;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync cbSrc -= cb;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pCur = mbuf_next(pCur);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (!err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return pPkt;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_freem(pPkt);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync AssertMsg(err == ENOMEM || err == EWOULDBLOCK, ("err=%d\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->pvUserData = NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/**
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Calculates the number of segments required to represent the mbuf.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync *
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Taken from VBoxNetAdp-darwin.cpp.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync *
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @returns Number of segments.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pThis The instance.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pMBuf The mbuf.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pvFrame The frame pointer, optional.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsyncDECLINLINE(unsigned) vboxNetAdpDarwinMBufCalcSGSegs(PVBOXNETADP pThis, mbuf_t pMBuf, void *pvFrame)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync{
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync NOREF(pThis);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /*
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Count the buffers in the chain.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync unsigned cSegs = 0;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur))
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (mbuf_len(pCur))
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync cSegs++;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync else if ( !cSegs
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync && pvFrame
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf))
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync cSegs++;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#ifdef PADD_RUNT_FRAMES_FROM_HOST
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /*
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Add one buffer if the total is less than the ethernet minimum 60 bytes.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * This may allocate a segment too much if the ethernet header is separated,
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * but that shouldn't harm us much.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (mbuf_pkthdr_len(pMBuf) < 60)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync cSegs++;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#endif
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /* maximize the number of segments. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync cSegs = RT_MAX(VBOXNETFLT_DARWIN_MAX_SEGS - 1, cSegs);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#endif
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync return cSegs ? cSegs : 1;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Initializes a SG list from an mbuf.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync *
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Taken from VBoxNetAdp-darwin.cpp.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync *
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @returns Number of segments.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pThis The instance.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pMBuf The mbuf.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @param pSG The SG.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pvFrame The frame pointer, optional.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param cSegs The number of segments allocated for the SG.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * This should match the number in the mbuf exactly!
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param fSrc The source of the frame.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsyncDECLINLINE(void) vboxNetAdpDarwinMBufToSG(PVBOXNETADP pThis, mbuf_t pMBuf, void *pvFrame, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync NOREF(pThis);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->pvOwnerData = NULL;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->pvUserData = NULL;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->pvUserData2 = NULL;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->cUsers = 1;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->fFlags = INTNETSG_FLAGS_TEMP;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cSegsAlloc = cSegs;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Walk the chain and convert the buffers to segments.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync unsigned iSeg = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cbTotal = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync size_t cbSeg = mbuf_len(pCur);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (cbSeg)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync void *pvSeg = mbuf_data(pCur);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* deal with pvFrame */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (!iSeg && pvFrame && pvFrame != pvSeg)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync void *pvStart = mbuf_datastart(pMBuf);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync uintptr_t offSeg = (uintptr_t)pvSeg - (uintptr_t)pvStart;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync uintptr_t offSegEnd = offSeg + cbSeg;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pvStart && pvSeg && offSeg < mbuf_maxlen(pMBuf) && offSegEnd <= mbuf_maxlen(pMBuf)); NOREF(offSegEnd);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync uintptr_t offFrame = (uintptr_t)pvFrame - (uintptr_t)pvStart;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (RT_LIKELY(offFrame < offSeg))
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pvSeg = pvFrame;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync cbSeg += offSeg - offFrame;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync AssertMsgFailed(("pvFrame=%p pvStart=%p pvSeg=%p offSeg=%p cbSeg=%#zx offSegEnd=%p offFrame=%p maxlen=%#zx\n",
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pvFrame, pvStart, pvSeg, offSeg, cbSeg, offSegEnd, offFrame, mbuf_maxlen(pMBuf)));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pvFrame = NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync AssertBreak(iSeg < cSegs);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cbTotal += cbSeg;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iSeg].cb = cbSeg;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iSeg].pv = pvSeg;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync iSeg++;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* The pvFrame might be in a now empty buffer. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else if ( !iSeg
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync && pvFrame
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync cbSeg = (uintptr_t)mbuf_datastart(pMBuf) + mbuf_maxlen(pMBuf) - (uintptr_t)pvFrame;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cbTotal += cbSeg;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iSeg].cb = cbSeg;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iSeg].pv = pvFrame;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync iSeg++;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pvFrame = NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(iSeg && iSeg <= cSegs);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cSegsUsed = iSeg;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef PADD_RUNT_FRAMES_FROM_HOST
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Add a trailer if the frame is too small.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Since we're getting to the packet before it is framed, it has not
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * yet been padded. The current solution is to add a segment pointing
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * to a buffer containing all zeros and pray that works for all frames...
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync AssertReturnVoid(iSeg < cSegs);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync static uint8_t const s_abZero[128] = {0};
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cbTotal = 60;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->cSegsUsed++;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Redistribute the segments.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (pSG->cSegsUsed < pSG->cSegsAlloc)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* copy the segments to the end. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync int iSrc = pSG->cSegsUsed;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync int iDst = pSG->cSegsAlloc;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync while (iSrc > 0)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync iDst--;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync iSrc--;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iDst] = pSG->aSegs[iSrc];
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync }
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /* create small segments from the start. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->cSegsUsed = pSG->cSegsAlloc;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync iSrc = iDst;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync iDst = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync while ( iDst < iSrc
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync && iDst < pSG->cSegsAlloc)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iDst].Phys = NIL_RTHCPHYS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pSG->aSegs[iDst].pv = pSG->aSegs[iSrc].pv;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iDst].cb = RT_MIN(pSG->aSegs[iSrc].cb, VBOXNETFLT_DARWIN_TEST_SEG_SIZE);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (pSG->aSegs[iDst].cb != pSG->aSegs[iSrc].cb)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iSrc].cb -= pSG->aSegs[iDst].cb;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->aSegs[iSrc].pv = (uint8_t *)pSG->aSegs[iSrc].pv + pSG->aSegs[iDst].cb;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync }
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync else if (++iSrc >= pSG->cSegsAlloc)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pSG->cSegsUsed = iDst + 1;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync break;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync iDst++;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync AssertMsg(!pvFrame, ("pvFrame=%p pMBuf=%p iSeg=%d\n", pvFrame, pMBuf, iSeg));
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#endif /* VBOXANETADP_DO_NOT_USE_NETFLT */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsyncstatic errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pThis);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (vboxNetAdpPrepareToReceive(pThis))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync unsigned cSegs = vboxNetAdpDarwinMBufCalcSGSegs(pThis, pMBuf, NULL);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (cSegs < VBOXNETADP_DARWIN_MAX_SEGS)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpDarwinMBufToSG(pThis, pMBuf, NULL, pSG, cSegs, INTNETTRUNKDIR_HOST);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpReceive(pThis, pSG);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpCancelReceive(pThis);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif /* VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mbuf_freem_list(pMBuf);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic void vboxNetAdpDarwinAttachFamily(PVBOXNETADP pThis, protocol_family_t Family)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync u_int32_t i;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (pThis->u.s.aAttachedFamilies[i] == 0)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pThis->u.s.aAttachedFamilies[i] = Family;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync break;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic void vboxNetAdpDarwinDetachFamily(PVBOXNETADP pThis, protocol_family_t Family)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync u_int32_t i;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (pThis->u.s.aAttachedFamilies[i] == Family)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pThis->u.s.aAttachedFamilies[i] = 0;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic errno_t vboxNetAdpDarwinAddProto(ifnet_t pIface, protocol_family_t Family, const struct ifnet_demux_desc *pDemuxDesc, u_int32_t nDesc)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pThis);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpDarwinAttachFamily(pThis, Family);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync LogFlow(("vboxNetAdpAddProto: Family=%d.\n", Family));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return ether_add_proto(pIface, Family, pDemuxDesc, nDesc);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic errno_t vboxNetAdpDarwinDelProto(ifnet_t pIface, protocol_family_t Family)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Assert(pThis);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync LogFlow(("vboxNetAdpDelProto: Family=%d.\n", Family));
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync vboxNetAdpDarwinDetachFamily(pThis, Family);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync return ether_del_proto(pIface, Family);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsyncstatic void vboxNetAdpDarwinDetach(ifnet_t pIface)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync{
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Assert(pThis);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Log2(("vboxNetAdpDarwinDetach: Signaling detach to vboxNetAdpUnregisterDevice.\n"));
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /* Let vboxNetAdpDarwinUnregisterDevice know that the interface has been detached. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync RTSemEventSignal(pThis->u.s.hEvtDetached);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsyncint vboxNetAdpPortOsXmit(PVBOXNETADP pThis, PINTNETSG pSG, uint32_t fDst)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync{
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync int rc = VINF_SUCCESS;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync ifnet_t pIfNet = vboxNetAdpDarwinRetainIfNet(pThis); // Really need a wrapper?
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (pIfNet)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /*
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Create a mbuf for the gather list and push it onto the host stack.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync mbuf_t pMBuf = vboxNetAdpDarwinMBufFromSG(pThis, pSG);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (pMBuf)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /* This is what IONetworkInterface::inputPacket does. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync unsigned const cbEthHdr = 14;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync mbuf_pkthdr_setheader(pMBuf, mbuf_data(pMBuf));
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync mbuf_pkthdr_setlen(pMBuf, mbuf_pkthdr_len(pMBuf) - cbEthHdr);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync mbuf_setdata(pMBuf, (uint8_t *)mbuf_data(pMBuf) + cbEthHdr, mbuf_len(pMBuf) - cbEthHdr);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync mbuf_pkthdr_setrcvif(pMBuf, pIfNet); /* will crash without this. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Log(("vboxNetAdpPortOsXmit: calling ifnet_input()\n"));
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync errno_t err = ifnet_input(pIfNet, pMBuf, NULL);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (err)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync rc = RTErrConvertFromErrno(err);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync }
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync else
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Log(("vboxNetAdpPortOsXmit: failed to convert SG to mbuf.\n"));
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync rc = VERR_NO_MEMORY;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync }
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync vboxNetAdpDarwinReleaseIfNet(pThis, pIfNet);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync }
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("vboxNetAdpPortOsXmit: failed to retain the interface.\n"));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return rc;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncbool vboxNetAdpPortOsIsPromiscuous(PVBOXNETADP pThis)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync uint16_t fIf = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync ifnet_t pIfNet = vboxNetAdpDarwinRetainIfNet(pThis);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (pIfNet)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* gather the data */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync fIf = ifnet_flags(pIfNet);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpDarwinReleaseIfNet(pThis, pIfNet);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return fIf & IFF_PROMISC;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncvoid vboxNetAdpPortOsGetMacAddress(PVBOXNETADP pThis, PRTMAC pMac)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *pMac = pThis->u.s.Mac;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncbool vboxNetAdpPortOsIsHostMac(PVBOXNETADP pThis, PCRTMAC pMac)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* ASSUMES that the MAC address never changes. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return pThis->u.s.Mac.au16[0] == pMac->au16[0]
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync && pThis->u.s.Mac.au16[1] == pMac->au16[1]
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync && pThis->u.s.Mac.au16[2] == pMac->au16[2];
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncint vboxNetAdpOsDisconnectIt(PVBOXNETADP pThis)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Nothing to do here. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return VINF_SUCCESS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncint vboxNetAdpOsConnectIt(PVBOXNETADP pThis)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Nothing to do here. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return VINF_SUCCESS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncVBOXNETADP g_vboxnet0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncint vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync int rc;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync struct ifnet_init_params Params;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTUUID uuid;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync struct sockaddr_dl mac;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync rc = RTSemEventCreate(&pThis->u.s.hEvtDetached);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (RT_FAILURE(rc))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return rc;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mac.sdl_len = sizeof(mac);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mac.sdl_family = AF_LINK;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mac.sdl_alen = ETHER_ADDR_LEN;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mac.sdl_nlen = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync mac.sdl_slen = 0;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memcpy(LLADDR(&mac), pMACAddress->au8, mac.sdl_alen);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTStrPrintf(pThis->szName, VBOXNETADP_MAX_NAME_LEN, "%s%d", VBOXNETADP_NAME, pThis->uUnit);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpDarwinComposeUUID(pThis, &uuid);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.uniqueid = uuid.au8;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.uniqueid_len = sizeof(uuid);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.name = VBOXNETADP_NAME;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.unit = pThis->uUnit;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.family = IFNET_FAMILY_ETHERNET;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.type = IFT_ETHER;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.output = vboxNetAdpDarwinOutput;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.demux = ether_demux;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.add_proto = vboxNetAdpDarwinAddProto;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.del_proto = vboxNetAdpDarwinDelProto;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.check_multi = ether_check_multi;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.framer = ether_frameout;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.softc = pThis;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.ioctl = (ifnet_ioctl_func)ether_ioctl;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.set_bpf_tap = NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.detach = vboxNetAdpDarwinDetach;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.event = NULL;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Params.broadcast_addr = "\xFF\xFF\xFF\xFF\xFF\xFF";
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Params.broadcast_len = ETHER_ADDR_LEN;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync errno_t err = ifnet_allocate(&Params, &pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (!err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync err = ifnet_attach(pThis->u.s.pIface, &mac);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (!err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync err = ifnet_set_flags(pThis->u.s.pIface, IFF_RUNNING | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST, 0xFFFF);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (!err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync ifnet_set_mtu(pThis->u.s.pIface, VBOXNETADP_MTU);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return VINF_SUCCESS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("vboxNetAdpDarwinRegisterDevice: Failed to set flags (err=%d).\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync ifnet_detach(pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("vboxNetAdpDarwinRegisterDevice: Failed to attach to interface (err=%d).\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync ifnet_release(pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync Log(("vboxNetAdpDarwinRegisterDevice: Failed to allocate interface (err=%d).\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return RTErrConvertFromErrno(err);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncvoid vboxNetAdpOsDestroy(PVBOXNETADP pThis)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync u_int32_t i;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Bring down the interface */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync int rc = VINF_SUCCESS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync errno_t err;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync AssertPtr(pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Assert(pThis->u.s.hEvtDetached != NIL_RTSEMEVENT);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync err = ifnet_set_flags(pThis->u.s.pIface, 0, IFF_UP | IFF_RUNNING);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("vboxNetAdpDarwinUnregisterDevice: Failed to bring down interface "
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync "(err=%d).\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Detach all protocols. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (pThis->u.s.aAttachedFamilies[i])
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync ifnet_detach_protocol(pThis->u.s.pIface, pThis->u.s.aAttachedFamilies[i]);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync err = ifnet_detach(pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("vboxNetAdpDarwinUnregisterDevice: Failed to detach interface "
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync "(err=%d).\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log2(("vboxNetAdpDarwinUnregisterDevice: Waiting for 'detached' event...\n"));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /* Wait until we get a signal from detach callback. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync rc = RTSemEventWait(pThis->u.s.hEvtDetached, VBOXNETADP_DETACH_TIMEOUT);
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync if (rc == VERR_TIMEOUT)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync LogRel(("VBoxAdpDrv: Failed to detach interface %s%d\n.",
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync VBOXNETADP_NAME, pThis->uUnit));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync err = ifnet_release(pThis->u.s.pIface);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (err)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("vboxNetAdpUnregisterDevice: Failed to release interface (err=%d).\n", err));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTSemEventDestroy(pThis->u.s.hEvtDetached);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncint vboxNetAdpOsInit(PVBOXNETADP pThis)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Init the darwin specific members.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync pThis->u.s.pIface = NULL;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memset(pThis->u.s.aAttachedFamilies, 0, sizeof(pThis->u.s.aAttachedFamilies));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return VINF_SUCCESS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Start the kernel module.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic kern_return_t VBoxNetAdpDarwinStart(struct kmod_info *pKModInfo, void *pvData)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync int rc;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Initialize IPRT and find our module tag id.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * (IPRT is shared with VBoxDrv, it creates the loggers.)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync rc = RTR0Init(0);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (RT_SUCCESS(rc))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("VBoxNetAdpDarwinStart\n"));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Initialize the globals and connect to the support driver.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync *
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * This will call back vboxNetAdpOsOpenSupDrv (and maybe vboxNetAdpOsCloseSupDrv)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * for establishing the connect to the support driver.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memset(&g_VBoxNetAdpGlobals, 0, sizeof(g_VBoxNetAdpGlobals));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync rc = vboxNetAdpInitGlobals(&g_VBoxNetAdpGlobals);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTMAC Mac;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpOsInit(&g_vboxnet0);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpComposeMACAddress(&g_vboxnet0, &Mac);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync rc = vboxNetAdpOsCreate(&g_vboxnet0, &Mac);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (RT_SUCCESS(rc))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync LogRel(("VBoxAdpDrv: version " VBOX_VERSION_STRING " r%d\n", VBOX_SVN_REV));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return KMOD_RETURN_SUCCESS;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync LogRel(("VBoxAdpDrv: failed to initialize device extension (rc=%d)\n", rc));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTR0Term();
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync else
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync printf("VBoxAdpDrv: failed to initialize IPRT (rc=%d)\n", rc);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memset(&g_VBoxNetAdpGlobals, 0, sizeof(g_VBoxNetAdpGlobals));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif /* VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return KMOD_RETURN_FAILURE;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync}
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/**
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Stop the kernel module.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsyncstatic kern_return_t VBoxNetAdpDarwinStop(struct kmod_info *pKModInfo, void *pvData)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync{
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("VBoxNetAdpDarwinStop\n"));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Refuse to unload if anyone is currently using the filter driver.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * This is important as I/O kit / xnu will to be able to do usage
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * tracking for us!
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync int rc = vboxNetAdpTryDeleteGlobals(&g_VBoxNetAdpGlobals);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync if (RT_FAILURE(rc))
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync {
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync Log(("VBoxNetAdpDarwinStop - failed, busy.\n"));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return KMOD_RETURN_FAILURE;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync }
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /*
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Undo the work done during start (in reverse order).
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync memset(&g_VBoxNetAdpGlobals, 0, sizeof(g_VBoxNetAdpGlobals));
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync vboxNetAdpOsDestroy(&g_vboxnet0);
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync RTR0Term();
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync return KMOD_RETURN_SUCCESS;
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync}
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync