VBoxNetFlt.c revision c0fa9ee5c9cb7a79ac0f20d8009f75148bd9195f
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VBoxNetFlt - Network Filter Driver (Host), Common Code.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * available from http://www.virtualbox.org. This file is free software;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * General Public License (GPL) as published by the Free Software
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * additional information or have any questions.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/** @page pg_netflt VBoxNetFlt - Network Interface Filter
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This is a kernel module that attaches to a real interface on the host
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * and filters and injects packets.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * In the big picture we're one of the three trunk interface on the internal
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * network, the one named "NIC Filter Driver": @image html Networking_Overview.gif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @section sec_netflt_msc Locking / Sequence Diagrams
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This secion contains a few sequence diagrams describing the problematic
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * transitions of a host interface filter instance.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * The thing that makes it all a bit problematic is that multiple events may
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * happen at the same time, and that we have to be very careful to avoid
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * deadlocks caused by mixing our locks with the ones in the host kernel.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * The main events are receive, send, async send completion, disappearance of
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * the host networking interface and it's reappearance. The latter two events
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * are can be caused by driver unloading/loading or the device being physical
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * unplugged (e.g. a USB network device).
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * The strategy for dealing with these issues are:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * - Use a simple state machine.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * - Require the user (IntNet) to serialize all its calls to us,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * while at the same time not owning any lock used by any of the
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * the callbacks we might call on receive and async send completion.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * - Make sure we're 100% idle before disconnecting, and have a
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * disconnected status on both sides to fend off async calls.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * - Protect the host specific interface handle and the state variables
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * using a spinlock.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM, IntNet, NetFlt, Kernel, Wire;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>Kernel [label="pkt0 to wire", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Kernel->Wire [label="pkt0 to wire", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * --- [label="Suspending the trunk interface"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Lock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Wire->Kernel [label="pkt1 - racing us", linecolor="red", textcolor="red"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Kernel=>>NetFlt [label="pkt1 - racing us", linecolor="red", textcolor="red"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>>IntNet [label="pkt1 recv - blocks", linecolor="red", textcolor="red"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Mark Trunk Suspended"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Unlock Network"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>NetFlt [label="pfnSetActive(false)"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Mark inactive (atomic)"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet<<NetFlt;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>NetFlt [label="pfnWaitForIdle(forever)"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>>NetFlt [label="pkt1 to host", linecolor="red", textcolor="red"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>>Kernel [label="pkt1 to host", linecolor="red", textcolor="red"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Kernel<-Wire [label="pkt0 on wire", linecolor="green", textcolor="green"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt<<Kernel [label="pkt0 on wire", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet<<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet<<=IntNet [label="Lock Net, free SG, Unlock Net", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<-NetFlt [label="idle", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet<<NetFlt [label="idle (pfnWaitForIdle)"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Wire->Kernel [label="pkt2", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Kernel=>>NetFlt [label="pkt2", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>>Kernel [label="pkt2 to host", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM->IntNet [label="pkt3", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Route packet -> drop", linecolor="green", textcolor="green" ];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * --- [label="The trunk interface is idle now, disconnect it"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Lock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Unlink Trunk"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Unlock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>NetFlt [label="pfnDisconnectAndRelease"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>Kernel [label="iflt_detach"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt<<=Kernel [label="iff_detached"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt>>Kernel [label="iff_detached"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<<Kernel [label="iflt_detach"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Release"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet<<NetFlt [label="pfnDisconnectAndRelease"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Removal
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * The ifnet_t (pIf) is a tricky customer as any reference to it can potentially
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * race the filter detaching. The simple way of solving it on Darwin is to guard
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * all access to the pIf member with a spinlock. The other host systems will
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * probably have similar race conditions, so the spinlock is a generic thing.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * VM, IntNet, NetFlt, Kernel;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>Kernel [label="ifnet_reference w/ spinlock", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<<Kernel [label="ifnet_reference", linecolor="green", textcolor="green" ];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>Kernel [label="pkt0 to wire (blocks)", linecolor="green", textcolor="green" ];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * --- [label="The host interface is being disconnected"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Kernel->NetFlt [label="iff_detached"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>Kernel [label="ifnet_release w/ spinlock"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<<Kernel [label="ifnet_release"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>NetFlt [label="fDisconnectedFromHost=true"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt>>Kernel [label="iff_detached"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt<<Kernel [label="dropped", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Acquire spinlock", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt<<Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="pIf=NULL", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Release spinlock", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet<<NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * The rediscovery is performed when we receive a send request and a certain
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * period have elapsed since the last attempt, i.e. we're polling it. We
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * synchronize the rediscovery with disconnection from the internal network
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * by means of the pfnWaitForIdle call, so no special handling is required.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM2, VM1, IntNet, NetFlt, Kernel, Wire;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * --- [label="Rediscovery conditions are not met"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * VM1->IntNet [label="pkt0"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Lock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Route packet -> wire"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Unlock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>NetFlt [label="pkt0 to wire"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet<<NetFlt [label="pkt0 to wire (dropped)"];
91fdb167bd5c9417d9507c1317ae121864fdc9cbvboxsync * --- [label="Rediscovery conditions"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM1->IntNet [label="pkt1"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Lock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Route packet -> wire"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>IntNet [label="Unlock Network"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * IntNet=>NetFlt [label="pkt1 to wire"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="fRediscoveryPending=true w/ spinlock"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>Kernel [label="ifnet_find_by_name"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<<Kernel [label="ifnet_find_by_name (success)"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VM2->IntNet [label="pkt2", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Lock Network", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet=>NetFlt [label="pkt2 to wire", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="!pIf || fRediscoveryPending (w/ spinlock)", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet<<NetFlt [label="pkt2 to wire (dropped)", linecolor="red", textcolor="red"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>Kernel [label="iflt_attach"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<<Kernel [label="iflt_attach (success)"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Acquire spinlock"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>NetFlt [label="Set pIf and update flags"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt=>NetFlt [label="Release spinlock"];
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * NetFlt=>Kernel [label="pkt1 to wire"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Kernel->Wire [label="pkt1 to wire"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * NetFlt<<Kernel [label="pkt1 to wire"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IntNet<<NetFlt [label="pkt1 to wire"];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Header Files *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync/*******************************************************************************
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync* Defined Constants And Macros *
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync*******************************************************************************/
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync ( (PVBOXNETFLTINS)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETFLTINS, MyPort)) )
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * Finds a instance by its name, the caller does the locking.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * @returns Pointer to the instance by the given name. NULL if not found.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * @param pGlobals The globals.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * @param pszName The name of the instance.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsyncstatic PVBOXNETFLTINS vboxNetFltFindInstanceLocked(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * Finds a instance by its name, will request the mutex.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns Pointer to the instance by the given name. NULL if not found.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @param pGlobals The globals.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pszName The name of the instance.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsyncDECLHIDDEN(PVBOXNETFLTINS) vboxNetFltFindInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync pRet = vboxNetFltFindInstanceLocked(pGlobals, pszName);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Unlinks an instance from the chain.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pGlobals The globals.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pToUnlink The instance to unlink.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncstatic void vboxNetFltUnlinkLocked(PVBOXNETFLTGLOBALS pGlobals, PVBOXNETFLTINS pToUnlink)
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncAssertCompileMemberSize(VBOXNETFLTINS, enmState, sizeof(uint32_t));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Sets the enmState member atomically.
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync * Used for all updates.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pThis The instance.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param enmNewState The new value.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncDECLINLINE(void) vboxNetFltSetState(PVBOXNETFLTINS pThis, VBOXNETFTLINSSTATE enmNewState)
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Gets the enmState member atomically.
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync * Used for all reads.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @returns The enmState value.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pThis The instance.
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsyncDECLINLINE(VBOXNETFTLINSSTATE) vboxNetFltGetState(PVBOXNETFLTINS pThis)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync return (VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Performs interface rediscovery if it was disconnected from the host.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @returns true if successfully rediscovered and connected, false if not.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pThis The instance.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncstatic bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Rediscovered already? Time to try again?
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync fRediscovered = !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync && !ASMAtomicUoReadBool(&pThis->fRediscoveryPending)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync && Now - ASMAtomicUoReadU64(&pThis->NanoTSLastRediscovery) > UINT64_C(5000000000); /* 5 sec */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, true);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Call the OS specific code to do the job.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Update the state when the call returns, that is everything except for
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * the fDisconnectedFromHost flag which the OS specific code shall set.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync fRediscovered = vboxNetFltOsMaybeRediscovered(pThis);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Assert(!fRediscovered || !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync ASMAtomicUoWriteU64(&pThis->NanoTSLastRediscovery, RTTimeNanoTS());
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, false);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync# if defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync# define NETFLT_DECL_CALLBACK(type) DECLASM(DECLHIDDEN(type))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortXmit)(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous)(PINTNETTRUNKIFPORT pIfPort);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortGetMacAddress)(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsHostMac)(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortWaitForIdle)(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortSetActive)(PINTNETTRUNKIFPORT pIfPort, bool fActive);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease)(PINTNETTRUNKIFPORT pIfPort);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRetain)(PINTNETTRUNKIFPORT pIfPort);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRelease)(PINTNETTRUNKIFPORT pIfPort);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# define NETFLT_DECL_CALLBACK(type) static DECLCALLBACK(type)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @copydoc INTNETTRUNKIFPORT::pfnXmit
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Input validation.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Do a busy retain and then make sure we're connected to the interface
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * before invoking the OS specific code.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsPromiscuous
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsPromiscuous(PINTNETTRUNKIFPORT pIfPort)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * Input validation.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * Ask the OS specific code.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * Input validation.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync * Forward the question to the OS specific code.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsHostMac
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsHostMac(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Input validation.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Ask the OS specific code.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * Input validation.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * Go to sleep on the semaphore after checking the busy count.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = RTSemEventWait(pThis->hEventIdle, cMillies); /** @todo make interruptible? */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * @copydoc INTNETTRUNKIFPORT::pfnSetActive
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
92de700c41f3803fd020736400a84b4105590eb6vboxsync * Input validation.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, false);
92de700c41f3803fd020736400a84b4105590eb6vboxsync * We're assuming that the caller is serializing the calls, so we don't
92de700c41f3803fd020736400a84b4105590eb6vboxsync * have to be extremely careful here. Just update first and then call
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * the OS specific code, the update must be serialized for various reasons.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Serious paranoia.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Disconnect and release it.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Unconnected);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * Destroy a device that has been disconnected from the switch.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @return true iff the instance is destroyed, false otherwise
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @param pThis The instance to be destroyed. This is
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * no longer valid when this function returns.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncstatic bool vboxNetFltCheckDestroyInstance(PVBOXNETFLTINS pThis)
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync uint32_t cRefs = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cRefs);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync LogFlow(("vboxNetFltCheckDestroyInstance: pThis=%p (%s)\n", pThis, pThis->szName));
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Validate the state.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync Assert( vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync || vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Make sure the state is 'disconnecting' and let the OS specific code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * do its part of the cleanup outside the mutex.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx); AssertRC(rc);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return false;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Destroying);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Unlink the instance and free up its resources.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx); AssertRC(rc);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Destroyed);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return true;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Releases a reference to the specified instance.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This method will destroy the instance when the count reaches 0.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * It will also take care of decrementing the counter and idle wakeup.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @param pThis The instance.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @param fBusy Whether the busy counter should be decremented too.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncDECLHIDDEN(void) vboxNetFltRelease(PVBOXNETFLTINS pThis, bool fBusy)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Paranoid Android.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
b2640405e06105d868b5fc8f7b676bb680884380vboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Work the busy counter.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * The object reference counting.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortRelease(PINTNETTRUNKIFPORT pIfPort)
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Retains a reference to the specified instance and a busy reference too.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pThis The instance.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param fBusy Whether the busy counter should be incremented as well.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncDECLHIDDEN(void) vboxNetFltRetain(PVBOXNETFLTINS pThis, bool fBusy)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Paranoid Android.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
b2640405e06105d868b5fc8f7b676bb680884380vboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Retain the object.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Work the busy counter.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortRetain(PINTNETTRUNKIFPORT pIfPort)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Connects the instance to the specified switch port.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Called while owning the lock. We're ASSUMING that the internal
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * networking code is already owning an recursive mutex, so, there
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * will be no deadlocks when vboxNetFltOsConnectIt calls back into
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * it for setting preferences.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns VBox status code.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pThis The instance.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pSwitchPort The port on the internal network 'switch'.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @param ppIfPort Where to return our port interface.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Validate state.
4f01a090c00f35e11528b7fa7bcdf629399af9e9vboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected);
e1d63281b1a65b419caf27e7b0712b2594b0c938vboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Initializing);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Do the job.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Note that we're calling the os stuff while owning the semaphore here.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Connected);
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * Creates a new instance.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * The new instance will be in the suspended state in a dynamic config and in
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * the inactive in a static one.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * Called without owning the lock, but will request is several times.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @returns VBox status code.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pGlobals The globals.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pszName The instance name.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pSwitchPort The port on the switch that we're connected with (dynamic only).
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * @param ppIfPort Where to store the pointer to our port interface (dynamic only).
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * @param fNoPromisc Do not attempt going into promiscuous mode.
147b6ddff14ec450da8593696cf60c4258d61613vboxsyncstatic int vboxNetFltNewInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort, bool fNoPromisc
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * Allocate and initialize a new instance before requesting the mutex.
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync PVBOXNETFLTINS pNew = (PVBOXNETFLTINS)RTMemAllocZ(RT_OFFSETOF(VBOXNETFLTINS, szName[cchName + 1]));
c676658a234a45bfe783320e8a13f6fd4f0425dbvboxsync pNew->MyPort.u32Version = INTNETTRUNKIFPORT_VERSION;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pNew->MyPort.pfnRetain = NETFLT_CALLBACK(vboxNetFltPortRetain);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pNew->MyPort.pfnRelease = NETFLT_CALLBACK(vboxNetFltPortRelease);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pNew->MyPort.pfnDisconnectAndRelease= NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.pfnSetActive = NETFLT_CALLBACK(vboxNetFltPortSetActive);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.pfnWaitForIdle = NETFLT_CALLBACK(vboxNetFltPortWaitForIdle);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.pfnGetMacAddress = NETFLT_CALLBACK(vboxNetFltPortGetMacAddress);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.pfnIsHostMac = NETFLT_CALLBACK(vboxNetFltPortIsHostMac);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.pfnIsPromiscuous = NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.pfnXmit = NETFLT_CALLBACK(vboxNetFltPortXmit);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pNew->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Insert the instance into the chain, checking for
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * duplicates first of course (race).
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (!vboxNetFltFindInstanceLocked(pGlobals, pszName))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Call the OS specific initialization code.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Connect it as well, the OS specific bits has to be done outside
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * the lock as they may call back to into intnet.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = vboxNetFltConnectIt(pNew, pSwitchPort, ppIfPort);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Bail out (failed). */
ce95f18112057771f68abe58df709edd7c467db1vboxsync * searches for the NetFlt instance by its name and creates the new one if not found
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @return VINF_SUCCESS if new instance was created, VINF_ALREADY_INITIALIZED if an instanmce already exists,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * VERR_xxx in case of a failure
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncDECLHIDDEN(int) vboxNetFltSearchCreateInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PVBOXNETFLTINS *ppInstance, void * pContext)
6724f34fdfee01d77d13f23d907d7b79d80e435dvboxsync *ppInstance = vboxNetFltFindInstanceLocked(pGlobals, pszName);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync VBOXNETFTLINSSTATE enmState = vboxNetFltGetState(*ppInstance);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if(enmState != kVBoxNetFltInsState_Destroying && enmState != kVBoxNetFltInsState_Destroyed)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync /*wait for the instance to be removed from the list */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync } while(vboxNetFltFindInstanceLocked(pGlobals, pszName));
8ad79874169cc981a694a15e8a806b9a39133673vboxsync rc = vboxNetFltNewInstance(pGlobals, pszName, NULL, &pIfPort, false, pContext);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic DECLCALLBACK(int) vboxNetFltFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort, bool fNoPromisc)
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: pszName=%p:{%s}\n", pszName, pszName));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Static: Find instance, check if busy, connect if not.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Dynamic: Check for duplicate / busy interface instance.
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync /* instance can be destroyed when it is neither used by the IntNet nor by the ndis filter driver mechanism
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * (i.e. the driver is not bound to the specified adapter)*/
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync /* Prevent setting promiscuous mode for WiFi adapters. */
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync LogAleksey(("fNoPromisc=%d\n", pCur->fDisablePromiscuous));
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync vboxNetFltRetain(pCur, false /* fBusy */); /** @todo who releases this on failure? */
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync rc = vboxNetFltConnectIt(pCur, pSwitchPort, ppIfPort);
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync /** @todo what? */
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: returns %Rrc\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Dynamically create a new instance.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = vboxNetFltNewInstance(pGlobals, pszName, pSwitchPort, ppIfPort, fNoPromisc);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: returns %Rrc\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @copydoc INTNETTRUNKFACTORY::pfnRelease
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic DECLCALLBACK(void) vboxNetFltFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync LogFlow(("vboxNetFltFactoryRelease: cRefs=%d (new)\n", cRefs));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Implements the SUPDRV component factor interface query method.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns Pointer to an interface. NULL if not supported.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param pSupDrvFactory Pointer to the componet factory registration structure.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param pSession The session - unused.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param pszInterfaceUuid The factory interface id.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic DECLCALLBACK(void *) vboxNetFltQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, SupDrvFactory));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Convert the UUID strings and compare them.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* log legacy queries */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* else if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_V1_UUID_STR))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxNetFlt: V1 factory query\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxNetFlt: unknown factory interface query (%s)\n", pszInterfaceUuid));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxNetFlt: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Checks whether the VBoxNetFlt wossname can be unloaded.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This will return false if someone is currently using the module.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns true if it's relatively safe to unload it, otherwise false.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @param pGlobals Pointer to the globals.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncDECLHIDDEN(bool) vboxNetFltCanUnload(PVBOXNETFLTGLOBALS pGlobals)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * tries to deinitialize Idc
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * we separate the globals settings "base" which is actually
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * "general" globals settings except for Idc, and idc.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * thus it's not possible to make idc initialization from the driver startup routine for it,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * though the "base is still needed for the driver to functions".
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pGlobals
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @return VINF_SUCCESS on succes, VERR_WRONG_ORDER if we're busy.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncDECLHIDDEN(int) vboxNetFltTryDeleteIdc(PVBOXNETFLTGLOBALS pGlobals)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Check before trying to deregister the factory.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Disconnect from SUPDRV and check that nobody raced us,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * reconnect if that should happen.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * performs "base" globals deinitialization
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * we separate the globals settings "base" which is actually
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * "general" globals settings except for Idc, and idc.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * thus it's not possible to make idc initialization from the driver startup routine for it,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * though the "base is still needed for the driver to functions".
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pGlobals
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @return none
ce95f18112057771f68abe58df709edd7c467db1vboxsyncDECLHIDDEN(void) vboxNetFltDeleteGlobalsBase(PVBOXNETFLTGLOBALS pGlobals)
ce95f18112057771f68abe58df709edd7c467db1vboxsync * Release resources.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Called by the native part when the OS wants the driver to unload.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns VINF_SUCCESS on succes, VERR_WRONG_ORDER if we're busy.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @param pGlobals Pointer to the globals.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncDECLHIDDEN(int) vboxNetFltTryDeleteGlobals(PVBOXNETFLTGLOBALS pGlobals)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * performs the "base" globals initialization
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * we separate the globals initialization to globals "base" initialization which is actually
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * "general" globals initialization except for Idc not being initialized, and idc initialization.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * thus it's not possible to make idc initialization from the driver startup routine for it.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @returns VBox status code.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param pGlobals Pointer to the globals. */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsyncDECLHIDDEN(int) vboxNetFltInitGlobalsBase(PVBOXNETFLTGLOBALS pGlobals)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Initialize the common portions of the structure.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
ce95f18112057771f68abe58df709edd7c467db1vboxsync pGlobals->TrunkFactory.pfnRelease = vboxNetFltFactoryRelease;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetFltFactoryCreateAndConnect;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetFlt");
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetFltQueryFactoryInterface;
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync * performs the Idc initialization
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * we separate the globals initialization to globals "base" initialization which is actually
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * "general" globals initialization except for Idc not being initialized, and idc initialization.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync * thus it's not possible to make idc initialization from the driver startup routine for it.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns VBox status code.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @param pGlobals Pointer to the globals. */
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsyncDECLHIDDEN(int) vboxNetFltInitIdc(PVBOXNETFLTGLOBALS pGlobals)
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync * Establish a connection to SUPDRV and register our component factory.
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync Log(("VBoxNetFlt: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync /* bail out. */
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync LogRel(("VBoxNetFlt: Failed to register component factory, rc=%Rrc\n", rc));
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync * Called by the native driver/kext module initialization routine.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * It will initialize the common parts of the globals, assuming the caller
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync * has already taken care of the OS specific bits.
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync * @returns VBox status code.
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync * @param pGlobals Pointer to the globals.
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsyncDECLHIDDEN(int) vboxNetFltInitGlobals(PVBOXNETFLTGLOBALS pGlobals)
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync * Initialize the common portions of the structure.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* bail out. */