f86f2dc613a22ee06add9b878197922466df641bvboxsync/* $Id$ */
f86f2dc613a22ee06add9b878197922466df641bvboxsync/** @file
f86f2dc613a22ee06add9b878197922466df641bvboxsync * VBoxNetAdp - Virtual Network Adapter Driver (Host), Darwin Specific Code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2012 Oracle Corporation
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
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
296a2ed12c9cf6041bb8006c2223605d2f56c6c9vboxsync#include "../../darwin/VBoxNetSend.h"
296a2ed12c9cf6041bb8006c2223605d2f56c6c9vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <sys/systm.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <sys/kpi_mbuf.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_END
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>
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync#include <sys/conf.h>
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync#include <miscfs/devfs/devfs.h>
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsyncextern "C" {
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync#include <net/bpf.h>
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync}
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*******************************************************************************/
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_BEGIN
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic kern_return_t VBoxNetAdpDarwinStart(struct kmod_info *pKModInfo, void *pvData);
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic kern_return_t VBoxNetAdpDarwinStop(struct kmod_info *pKModInfo, void *pvData);
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_END
f86f2dc613a22ee06add9b878197922466df641bvboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*******************************************************************************
f86f2dc613a22ee06add9b878197922466df641bvboxsync* Global Variables *
f86f2dc613a22ee06add9b878197922466df641bvboxsync*******************************************************************************/
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Declare the module stuff.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_BEGIN
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__;
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_END
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * The (common) global data.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int g_nCtlDev = -1; /* Major dev number */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic void *g_hCtlDev = 0; /* FS dev handle */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync/**
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * The character device switch table for the driver.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic struct cdevsw g_ChDev =
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync{
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_open = */VBoxNetAdpDarwinOpen,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_close = */VBoxNetAdpDarwinClose,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_read = */eno_rdwrt,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_write = */eno_rdwrt,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_ioctl = */VBoxNetAdpDarwinIOCtl,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_stop = */eno_stop,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_reset = */eno_reset,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_ttys = */NULL,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_select = */eno_select,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_mmap = */eno_mmap,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_strategy = */eno_strat,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_getc = */eno_getc,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_putc = */eno_putc,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_type = */0
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync};
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
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;
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pUuid->Gen.u8ClockSeqLow = pThis->iUnit;
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpComposeMACAddress(pThis, (PRTMAC)pUuid->Gen.au8Node);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsyncstatic errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync{
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Assert(pThis);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync if (pThis->u.s.nTapMode & BPF_MODE_OUTPUT)
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync {
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Log2(("vboxnetadp: out len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, mbuf_data(pMBuf)));
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync bpf_tap_out(pIface, DLT_EN10MB, pMBuf, NULL, 0);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync }
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
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsyncstatic errno_t vboxNetAdpDarwinDemux(ifnet_t pIface, mbuf_t pMBuf,
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync char *pFrameHeader,
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync protocol_family_t *pProtocolFamily)
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync{
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Assert(pThis);
2f2587731657bec95ef807348711bccbae4b9c61vboxsync Log2(("vboxNetAdpDarwinDemux: mode=%d\n", pThis->u.s.nTapMode));
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync if (pThis->u.s.nTapMode & BPF_MODE_INPUT)
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync {
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Log2(("vboxnetadp: in len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, pFrameHeader));
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync bpf_tap_in(pIface, DLT_EN10MB, pMBuf, pFrameHeader, ETHER_HDR_LEN);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync }
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync return ether_demux(pIface, pMBuf, pFrameHeader, pProtocolFamily);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync}
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsyncstatic errno_t vboxNetAdpDarwinBpfTap(ifnet_t pIface, u_int32_t uLinkType, bpf_tap_mode nMode)
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync{
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Assert(pThis);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Log2(("vboxNetAdpDarwinBpfTap: mode=%d\n", nMode));
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync pThis->u.s.nTapMode = nMode;
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync return 0;
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync}
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsyncstatic errno_t vboxNetAdpDarwinBpfSend(ifnet_t pIface, u_int32_t uLinkType, mbuf_t pMBuf)
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync{
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync LogRel(("vboxnetadp: BPF send function is not implemented (dlt=%d)\n", uLinkType));
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync mbuf_freem_list(pMBuf);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync return 0;
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync}
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync
c1623d2b6d464bb63ed49fa172e9e6d266f7b4cdvboxsync
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsyncint 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))
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync {
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync printf("vboxNetAdpOsCreate: failed to create semaphore (rc=%d).\n", rc);
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync pThis->u.s.nTapMode = BPF_MODE_DISABLED;
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync
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
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync RTStrPrintf(pThis->szName, VBOXNETADP_MAX_NAME_LEN, "%s%d", VBOXNETADP_NAME, pThis->iUnit);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpDarwinComposeUUID(pThis, &uuid);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.uniqueid = uuid.au8;
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.uniqueid_len = sizeof(uuid);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.name = VBOXNETADP_NAME;
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync Params.unit = pThis->iUnit;
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.family = IFNET_FAMILY_ETHERNET;
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.type = IFT_ETHER;
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.output = vboxNetAdpDarwinOutput;
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync Params.demux = vboxNetAdpDarwinDemux;
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 {
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync err = bpf_attach(pThis->u.s.pIface, DLT_EN10MB, ETHER_HDR_LEN,
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync vboxNetAdpDarwinBpfSend, vboxNetAdpDarwinBpfTap);
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync if (err)
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync {
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync LogRel(("vboxnetadp: bpf_attach failed with %d\n", err));
22f8a6ac3bcf3e3c8aa1f275097d6f7ce392195bvboxsync }
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);
3b17f75f3a22443ca2d6f44be26de8335ff4bcd3vboxsync VBoxNetSendDummy(pThis->u.s.pIface);
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
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync RTSemEventDestroy(pThis->u.s.hEvtDetached);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
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.",
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync VBOXNETADP_NAME, pThis->iUnit));
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
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync/**
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Device open. Called on open /dev/vboxnetctl
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync *
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pInode Pointer to inode info structure.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pFilp Associated file pointer.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync{
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync char szName[128];
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync szName[0] = '\0';
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync proc_name(proc_pid(pProcess), szName, sizeof(szName));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync Log(("VBoxNetAdpDarwinOpen: pid=%d '%s'\n", proc_pid(pProcess), szName));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync return 0;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync}
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync/**
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Close device.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync{
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync Log(("VBoxNetAdpDarwinClose: pid=%d\n", proc_pid(pProcess)));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync return 0;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync}
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync/**
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Device I/O Control entry point.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync *
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @returns Darwin for slow IOCtls and VBox status code for the fast ones.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param Dev The device number (major+minor).
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param iCmd The IOCtl command.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pData Pointer to the data (if any it's a SUPDRVIOCTLDATA (kernel copy)).
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param fFlags Flag saying we're a character device (like we didn't know already).
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pProcess The process issuing this request.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync{
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync uint32_t cbReq = IOCPARM_LEN(iCmd);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync PVBOXNETADPREQ pReq = (PVBOXNETADPREQ)pData;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync int rc;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync Log(("VBoxNetAdpDarwinIOCtl: param len %#x; iCmd=%#lx\n", cbReq, iCmd));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync switch (IOCBASECMD(iCmd))
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync {
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync case IOCBASECMD(VBOXNETADP_CTL_ADD):
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync {
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync if ( (IOC_DIRMASK & iCmd) != IOC_INOUT
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync || cbReq < sizeof(VBOXNETADPREQ))
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return EINVAL;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync PVBOXNETADP pNew;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync Log(("VBoxNetAdpDarwinIOCtl: szName=%s\n", pReq->szName));
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync rc = vboxNetAdpCreate(&pNew,
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync pReq->szName[0] && RTStrEnd(pReq->szName, RT_MIN(cbReq, sizeof(pReq->szName))) ?
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync pReq->szName : NULL);
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync if (RT_FAILURE(rc))
831893706fe8846e9d9288cf857ef789a845a017vboxsync return rc == VERR_OUT_OF_RESOURCES ? ENOMEM : EINVAL;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync Assert(strlen(pReq->szName) < sizeof(pReq->szName));
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync strncpy(pReq->szName, pNew->szName, sizeof(pReq->szName) - 1);
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync pReq->szName[sizeof(pReq->szName) - 1] = '\0';
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync Log(("VBoxNetAdpDarwinIOCtl: Added '%s'\n", pReq->szName));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync break;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync }
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync case IOCBASECMD(VBOXNETADP_CTL_REMOVE):
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync {
e86538a7bc028e823f16f8982e90f0c7ef5d4ecevboxsync if (!RTStrEnd(pReq->szName, RT_MIN(cbReq, sizeof(pReq->szName))))
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return EINVAL;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync PVBOXNETADP pAdp = vboxNetAdpFindByName(pReq->szName);
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync if (!pAdp)
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return EINVAL;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync rc = vboxNetAdpDestroy(pAdp);
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync if (RT_FAILURE(rc))
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return EINVAL;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync Log(("VBoxNetAdpDarwinIOCtl: Removed %s\n", pReq->szName));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync break;
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync }
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync default:
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync printf("VBoxNetAdpDarwinIOCtl: unknown command %lx.\n", IOCBASECMD(iCmd));
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return EINVAL;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync }
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return 0;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync}
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
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"));
1b10ee771c3d20fb5539532dddb732723e5ad0cfvboxsync rc = vboxNetAdpInit();
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync if (RT_SUCCESS(rc))
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync {
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync g_nCtlDev = cdevsw_add(-1, &g_ChDev);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync if (g_nCtlDev < 0)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync {
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogRel(("VBoxAdp: failed to register control device."));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync rc = VERR_CANT_CREATE;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync }
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync else
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync {
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync g_hCtlDev = devfs_make_node(makedev(g_nCtlDev, 0), DEVFS_CHAR,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync UID_ROOT, GID_WHEEL, 0600, VBOXNETADP_CTL_DEV_NAME);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync if (!g_hCtlDev)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync {
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogRel(("VBoxAdp: failed to create FS node for control device."));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync rc = VERR_CANT_CREATE;
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync }
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync }
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync }
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync
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 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
1b10ee771c3d20fb5539532dddb732723e5ad0cfvboxsync vboxNetAdpShutdown();
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /* Remove control device */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync devfs_remove(g_hCtlDev);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync cdevsw_remove(g_nCtlDev, &g_ChDev);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync RTR0Term();
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return KMOD_RETURN_SUCCESS;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}