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