/** * 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; }
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); }
/** * 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; }
/** * * @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)); }
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(); }
/** * 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; }