VBoxNetAdp-darwin.cpp revision 36ebaddfec017eee7e82ee466c25de002cdc4231
f86f2dc613a22ee06add9b878197922466df641bvboxsync * VBoxNetAdp - Virtual Network Adapter Driver (Host), Darwin Specific Code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
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 * 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* Header Files *
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.
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncRT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*******************************************************************************
f86f2dc613a22ee06add9b878197922466df641bvboxsync* Defined Constants And Macros *
f86f2dc613a22ee06add9b878197922466df641bvboxsync*******************************************************************************/
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync/** The maximum number of SG segments.
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync * Used to prevent stack overflow and similar bad stuff. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync#define VBOXNETADP_FROM_IFACE(iface) ((PVBOXNETADP) ifnet_softc(iface))
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*******************************************************************************
f86f2dc613a22ee06add9b878197922466df641bvboxsync* Internal Functions *
f86f2dc613a22ee06add9b878197922466df641bvboxsync*******************************************************************************/
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic kern_return_t VBoxNetAdpDarwinStart(struct kmod_info *pKModInfo, void *pvData);
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic kern_return_t VBoxNetAdpDarwinStop(struct kmod_info *pKModInfo, void *pvData);
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);
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*******************************************************************************
f86f2dc613a22ee06add9b878197922466df641bvboxsync* Global Variables *
f86f2dc613a22ee06add9b878197922466df641bvboxsync*******************************************************************************/
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Declare the module stuff.
f86f2dc613a22ee06add9b878197922466df641bvboxsyncextern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData);
f86f2dc613a22ee06add9b878197922466df641bvboxsyncextern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData);
f86f2dc613a22ee06add9b878197922466df641bvboxsyncKMOD_EXPLICIT_DECL(VBoxNetAdp, VBOX_VERSION_STRING, _start, _stop)
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(kmod_start_func_t *) _realmain = VBoxNetAdpDarwinStart;
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(kmod_stop_func_t *) _antimain = VBoxNetAdpDarwinStop;
f86f2dc613a22ee06add9b878197922466df641bvboxsync * The (common) global data.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * The character device switch table for the driver.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /*.d_type = */0
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic void vboxNetAdpDarwinComposeUUID(PVBOXNETADP pThis, PRTUUID pUuid)
f86f2dc613a22ee06add9b878197922466df641bvboxsync /* Generate UUID from name and MAC address. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync pUuid->Gen.u8ClockSeqHiAndReserved = (pUuid->Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
f86f2dc613a22ee06add9b878197922466df641bvboxsync pUuid->Gen.u16TimeHiAndVersion = (pUuid->Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpComposeMACAddress(pThis, (PRTMAC)pUuid->Gen.au8Node);
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsyncstatic errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsyncstatic void vboxNetAdpDarwinAttachFamily(PVBOXNETADP pThis, protocol_family_t Family)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsyncstatic void vboxNetAdpDarwinDetachFamily(PVBOXNETADP pThis, protocol_family_t Family)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsyncstatic errno_t vboxNetAdpDarwinAddProto(ifnet_t pIface, protocol_family_t Family, const struct ifnet_demux_desc *pDemuxDesc, u_int32_t nDesc)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync LogFlow(("vboxNetAdpAddProto: Family=%d.\n", Family));
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync return ether_add_proto(pIface, Family, pDemuxDesc, nDesc);
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsyncstatic errno_t vboxNetAdpDarwinDelProto(ifnet_t pIface, protocol_family_t Family)
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync LogFlow(("vboxNetAdpDelProto: Family=%d.\n", Family));
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync Log2(("vboxNetAdpDarwinDetach: Signaling detach to vboxNetAdpUnregisterDevice.\n"));
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync /* Let vboxNetAdpDarwinUnregisterDevice know that the interface has been detached. */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncint vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync printf("vboxNetAdpOsCreate: failed to create semaphore (rc=%d).\n", rc);
f86f2dc613a22ee06add9b878197922466df641bvboxsync memcpy(LLADDR(&mac), pMACAddress->au8, mac.sdl_alen);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync RTStrPrintf(pThis->szName, VBOXNETADP_MAX_NAME_LEN, "%s%d", VBOXNETADP_NAME, pThis->uUnit);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Params.broadcast_addr = "\xFF\xFF\xFF\xFF\xFF\xFF";
f86f2dc613a22ee06add9b878197922466df641bvboxsync errno_t err = ifnet_allocate(&Params, &pThis->u.s.pIface);
f86f2dc613a22ee06add9b878197922466df641bvboxsync err = ifnet_set_flags(pThis->u.s.pIface, IFF_RUNNING | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST, 0xFFFF);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpDarwinRegisterDevice: Failed to set flags (err=%d).\n", err));
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpDarwinRegisterDevice: Failed to attach to interface (err=%d).\n", err));
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpDarwinRegisterDevice: Failed to allocate interface (err=%d).\n", err));
f86f2dc613a22ee06add9b878197922466df641bvboxsync /* Bring down the interface */
f86f2dc613a22ee06add9b878197922466df641bvboxsync err = ifnet_set_flags(pThis->u.s.pIface, 0, IFF_UP | IFF_RUNNING);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpDarwinUnregisterDevice: Failed to bring down interface "
f86f2dc613a22ee06add9b878197922466df641bvboxsync /* Detach all protocols. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
f86f2dc613a22ee06add9b878197922466df641bvboxsync ifnet_detach_protocol(pThis->u.s.pIface, pThis->u.s.aAttachedFamilies[i]);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpDarwinUnregisterDevice: Failed to detach interface "
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 LogRel(("VBoxAdpDrv: Failed to detach interface %s%d\n.",
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpUnregisterDevice: Failed to release interface (err=%d).\n", err));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Device open. Called on open /dev/vboxnetctl
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pInode Pointer to inode info structure.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pFilp Associated file pointer.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync proc_name(proc_pid(pProcess), szName, sizeof(szName));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync Log(("VBoxNetAdpDarwinOpen: pid=%d '%s'\n", proc_pid(pProcess), szName));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Close device.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync Log(("VBoxNetAdpDarwinClose: pid=%d\n", proc_pid(pProcess)));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Device I/O Control entry point.
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.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int VBoxNetAdpDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync Log(("VBoxNetAdpDarwinIOCtl: param len %#x; iCmd=%#lx\n", cbReq, iCmd));
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync Assert(strlen(pReq->szName) < sizeof(pReq->szName));
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync strncpy(pReq->szName, pNew->szName, sizeof(pReq->szName) - 1);
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync Log(("VBoxNetAdpDarwinIOCtl: Added '%s'\n", pReq->szName));
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync if (!memchr(pReq->szName, '\0', RT_MIN(cbReq, sizeof(pReq->szName))))
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync PVBOXNETADP pAdp = vboxNetAdpFindByName(pReq->szName);
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync Log(("VBoxNetAdpDarwinIOCtl: Removed %s\n", pReq->szName));
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync printf("VBoxNetAdpDarwinIOCtl: unknown command %lx.\n", IOCBASECMD(iCmd));
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Init the darwin specific members.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync memset(pThis->u.s.aAttachedFamilies, 0, sizeof(pThis->u.s.aAttachedFamilies));
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Start the kernel module.
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic kern_return_t VBoxNetAdpDarwinStart(struct kmod_info *pKModInfo, void *pvData)
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Initialize IPRT and find our module tag id.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * (IPRT is shared with VBoxDrv, it creates the loggers.)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogRel(("VBoxAdp: failed to register control device."));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync g_hCtlDev = devfs_make_node(makedev(g_nCtlDev, 0), DEVFS_CHAR,
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync UID_ROOT, GID_WHEEL, 0600, VBOXNETADP_CTL_DEV_NAME);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogRel(("VBoxAdp: failed to create FS node for control device."));
f86f2dc613a22ee06add9b878197922466df641bvboxsync LogRel(("VBoxAdpDrv: version " VBOX_VERSION_STRING " r%d\n", VBOX_SVN_REV));
f86f2dc613a22ee06add9b878197922466df641bvboxsync LogRel(("VBoxAdpDrv: failed to initialize device extension (rc=%d)\n", rc));
f86f2dc613a22ee06add9b878197922466df641bvboxsync printf("VBoxAdpDrv: failed to initialize IPRT (rc=%d)\n", rc);
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Stop the kernel module.
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic kern_return_t VBoxNetAdpDarwinStop(struct kmod_info *pKModInfo, void *pvData)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /* Remove control device */