예제 #1
0
/**
 * Looks up a IDC handle by session.
 *
 * @returns The IDC handle on success, NULL on failure.
 * @param   pSession    The session to lookup.
 *
 * @internal
 */
PSUPDRVIDCHANDLE supR0IdcGetHandleFromSession(PSUPDRVSESSION pSession)
{
    PSUPDRVIDCHANDLE pHandle = ASMAtomicUoReadPtrT(&g_pMainHandle, PSUPDRVIDCHANDLE);
    if (    VALID_PTR(pHandle)
        &&  pHandle->s.pSession == pSession)
        return pHandle;
    return NULL;
}
예제 #2
0
void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
{
    interface_filter_t pIfFilter;

    /*
     * Carefully obtain the interface filter reference and detach it.
     */
    RTSpinlockAcquire(pThis->hSpinlock);
    pIfFilter = ASMAtomicUoReadPtrT(&pThis->u.s.pIfFilter, interface_filter_t);
    if (pIfFilter)
        ASMAtomicUoWriteNullPtr(&pThis->u.s.pIfFilter);
    RTSpinlockReleaseNoInts(pThis->hSpinlock);

    if (pIfFilter)
        iflt_detach(pIfFilter);
}
예제 #3
0
/**
 * Reads and retains the host interface handle.
 *
 * @returns The handle, NULL if detached.
 * @param   pThis
 */
DECLINLINE(ifnet_t) vboxNetFltDarwinRetainIfNet(PVBOXNETFLTINS pThis)
{
    ifnet_t pIfNet = NULL;

    /*
     * Be careful here to avoid problems racing the detached callback.
     */
    RTSpinlockAcquire(pThis->hSpinlock);
    if (!ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost))
    {
        pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t);
        if (pIfNet)
            ifnet_reference(pIfNet);
    }
    RTSpinlockReleaseNoInts(pThis->hSpinlock);

    return pIfNet;
}
예제 #4
0
/**
 *
 * @see iff_detached_func in the darwin kpi.
 */
static void vboxNetFltDarwinIffDetached(void *pvThis, ifnet_t pIfNet)
{
    PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvThis;
    uint64_t NanoTS = RTTimeSystemNanoTS();
    LogFlow(("vboxNetFltDarwinIffDetached: pThis=%p NanoTS=%RU64 (%d)\n",
             pThis, NanoTS, VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) :  -1));

    Assert(!pThis->fDisconnectedFromHost);
    Assert(!pThis->fRediscoveryPending);

    /*
     * If we've put it into promiscuous mode, undo that now. If we don't
     * the if_pcount will go all wrong when it's replugged.
     */
    if (ASMAtomicXchgBool(&pThis->u.s.fSetPromiscuous, false))
        ifnet_set_promiscuous(pIfNet, 0);

    /*
     * We carefully take the spinlock and increase the interface reference
     * behind it in order to avoid problematic races with the detached callback.
     */
    RTSpinlockAcquire(pThis->hSpinlock);

    pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t);
    int cPromisc = VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : - 1;

    ASMAtomicUoWriteNullPtr(&pThis->u.s.pIfNet);
    ASMAtomicUoWriteNullPtr(&pThis->u.s.pIfFilter);
    ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false);
    pThis->u.s.fSetPromiscuous = false;
    ASMAtomicUoWriteU64(&pThis->NanoTSLastRediscovery, NanoTS);
    ASMAtomicUoWriteBool(&pThis->fRediscoveryPending, false);
    ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true);

    RTSpinlockReleaseNoInts(pThis->hSpinlock);

    if (pIfNet)
        ifnet_release(pIfNet);
    LogRel(("VBoxNetFlt: was detached from '%s' (%d)\n", pThis->szName, cPromisc));
}
예제 #5
0
void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
{
    struct ifnet *ifp;
    struct ifreq ifreq;
    int error;
    node_p node;
    struct ng_mesg *msg;
    struct ngm_connect *con;
    struct ngm_rmhook *rm;
    char path[NG_PATHSIZ];

    Log(("%s: fActive:%d\n", __func__, fActive));

    ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
    VBOXCURVNET_SET(ifp->if_vnet);
    node = ASMAtomicUoReadPtrT(&pThis->u.s.node, node_p);

    memset(&ifreq, 0, sizeof(struct ifreq));
    /* Activate interface */
    if (fActive)
    {
        pThis->u.s.flags = ifp->if_flags;
        ifpromisc(ifp, 1);

        /* ng_ether nodes are named after the interface name */
        snprintf(path, sizeof(path), "%s:", ifp->if_xname);

        /*
         * Send a netgraph connect message to the ng_ether node
         * assigned to the bridged interface. Connecting
         * the hooks 'lower' (ng_ether) to out 'input'.
         */
        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
                     sizeof(struct ngm_connect), M_NOWAIT);
        if (msg == NULL)
            return;
        con = (struct ngm_connect *)msg->data;
        snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:", ifp->if_xname);
        strlcpy(con->ourhook, "lower", NG_HOOKSIZ);
        strlcpy(con->peerhook, "input", NG_HOOKSIZ);
        NG_SEND_MSG_PATH(error, node, msg, path, 0);

        /*
         * Do the same for the hooks 'upper' (ng_ether) and our
         * 'output' hook.
         */
        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
                     sizeof(struct ngm_connect), M_NOWAIT);
        if (msg == NULL)
            return;
        con = (struct ngm_connect *)msg->data;
        snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:",
                 ifp->if_xname);
        strlcpy(con->ourhook, "upper", sizeof(con->ourhook));
        strlcpy(con->peerhook, "output", sizeof(con->peerhook));
        NG_SEND_MSG_PATH(error, node, msg, path, 0);
    }
    else
    {
        /* De-activate interface */
        pThis->u.s.flags = 0;
        ifpromisc(ifp, 0);

        /* Disconnect msgs are addressed to ourself */
        snprintf(path, sizeof(path), "vboxnetflt_%s:", ifp->if_xname);

        /*
         * Send a netgraph message to disconnect our 'input' hook
         */
        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
                     sizeof(struct ngm_rmhook), M_NOWAIT);
        if (msg == NULL)
            return;
        rm = (struct ngm_rmhook *)msg->data;
        strlcpy(rm->ourhook, "input", NG_HOOKSIZ);
        NG_SEND_MSG_PATH(error, node, msg, path, 0);

        /*
         * Send a netgraph message to disconnect our 'output' hook
         */
        NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
                     sizeof(struct ngm_rmhook), M_NOWAIT);
        if (msg == NULL)
            return;
        rm = (struct ngm_rmhook *)msg->data;
        strlcpy(rm->ourhook, "output", NG_HOOKSIZ);
        NG_SEND_MSG_PATH(error, node, msg, path, 0);
    }
    VBOXCURVNET_RESTORE();
}
예제 #6
0
/**
 * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered.
 *
 * @returns VBox status code.
 * @param   pThis           The instance.
 * @param   fRediscovery    If set we're doing a rediscovery attempt, so, don't
 *                          flood the release log.
 */
static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery)
{
    LogFlow(("vboxNetFltDarwinAttachToInterface: pThis=%p (%s)\n", pThis, pThis->szName));

    /*
     * Locate the interface first.
     *
     * The pIfNet member is updated before iflt_attach is called and used
     * to deal with the hypothetical case where someone rips out the
     * interface immediately after our iflt_attach call.
     */
    ifnet_t pIfNet = NULL;
    errno_t err = ifnet_find_by_name(pThis->szName, &pIfNet);
    if (err)
    {
        Assert(err == ENXIO);
        if (!fRediscovery)
            LogRel(("VBoxFltDrv: failed to find ifnet '%s' (err=%d)\n", pThis->szName, err));
        else
            Log(("VBoxFltDrv: failed to find ifnet '%s' (err=%d)\n", pThis->szName, err));
        return VERR_INTNET_FLT_IF_NOT_FOUND;
    }

    RTSpinlockAcquire(pThis->hSpinlock);
    ASMAtomicUoWritePtr(&pThis->u.s.pIfNet, pIfNet);
    RTSpinlockReleaseNoInts(pThis->hSpinlock);

    /*
     * Get the mac address while we still have a valid ifnet reference.
     */
    err = ifnet_lladdr_copy_bytes(pIfNet, &pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr));
    if (!err)
    {
        /*
         * Try attach the filter.
         */
        struct iff_filter RegRec;
        RegRec.iff_cookie   = pThis;
        RegRec.iff_name     = "VBoxNetFlt";
        RegRec.iff_protocol = 0;
        RegRec.iff_input    = vboxNetFltDarwinIffInput;
        RegRec.iff_output   = vboxNetFltDarwinIffOutput;
        RegRec.iff_event    = vboxNetFltDarwinIffEvent;
        RegRec.iff_ioctl    = vboxNetFltDarwinIffIoCtl;
        RegRec.iff_detached = vboxNetFltDarwinIffDetached;
        interface_filter_t pIfFilter = NULL;
        err = iflt_attach(pIfNet, &RegRec, &pIfFilter);
        Assert(err || pIfFilter);

        RTSpinlockAcquire(pThis->hSpinlock);
        pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t);
        if (pIfNet && !err)
        {
            ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
            ASMAtomicUoWritePtr(&pThis->u.s.pIfFilter, pIfFilter);
            pIfNet = NULL; /* don't dereference it */
        }
        RTSpinlockReleaseNoInts(pThis->hSpinlock);

        /* Report capabilities. */
        if (   !pIfNet
            && vboxNetFltTryRetainBusyNotDisconnected(pThis))
        {
            Assert(pThis->pSwitchPort);
            pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr);
            pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltDarwinIsPromiscuous(pThis));
            pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0,  INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
            pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
            vboxNetFltRelease(pThis, true /*fBusy*/);
        }
    }

    /* Release the interface on failure. */
    if (pIfNet)
        ifnet_release(pIfNet);

    int rc = RTErrConvertFromErrno(err);
    if (RT_SUCCESS(rc))
        LogRel(("VBoxFltDrv: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr));
    else
        LogRel(("VBoxFltDrv: failed to attach to ifnet '%s' (err=%d)\n", pThis->szName, err));
    return rc;
}