VBoxNetFlt.c revision b3e8b4b6cae4ef871974b773bbdc114747e7db6e
236b2935f217749893b7034e59da3e3568928acevboxsync * VBoxNetFlt - Network Filter Driver (Host), Common Code.
236b2935f217749893b7034e59da3e3568928acevboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
236b2935f217749893b7034e59da3e3568928acevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
236b2935f217749893b7034e59da3e3568928acevboxsync * available from http://www.virtualbox.org. This file is free software;
236b2935f217749893b7034e59da3e3568928acevboxsync * you can redistribute it and/or modify it under the terms of the GNU
236b2935f217749893b7034e59da3e3568928acevboxsync * General Public License (GPL) as published by the Free Software
236b2935f217749893b7034e59da3e3568928acevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
236b2935f217749893b7034e59da3e3568928acevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
236b2935f217749893b7034e59da3e3568928acevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
236b2935f217749893b7034e59da3e3568928acevboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
236b2935f217749893b7034e59da3e3568928acevboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
236b2935f217749893b7034e59da3e3568928acevboxsync * additional information or have any questions.
236b2935f217749893b7034e59da3e3568928acevboxsync/** @page pg_netflt VBoxNetFlt - Network Interface Filter
236b2935f217749893b7034e59da3e3568928acevboxsync * This is a kernel module that attaches to a real interface on the host
236b2935f217749893b7034e59da3e3568928acevboxsync * and filters and injects packets.
236b2935f217749893b7034e59da3e3568928acevboxsync * In the big picture we're one of the three trunk interface on the internal
236b2935f217749893b7034e59da3e3568928acevboxsync * network, the one named "NIC Filter Driver": @image html Networking_Overview.gif
236b2935f217749893b7034e59da3e3568928acevboxsync * @section sec_netflt_msc Locking / Sequence Diagrams
157093a77f2752732368338110cb50fa6cd7717fvboxsync * This secion contains a few sequence diagrams describing the problematic
157093a77f2752732368338110cb50fa6cd7717fvboxsync * transitions of a host interface filter instance.
236b2935f217749893b7034e59da3e3568928acevboxsync * The thing that makes it all a bit problematic is that multiple events may
157093a77f2752732368338110cb50fa6cd7717fvboxsync * happen at the same time, and that we have to be very careful to avoid
157093a77f2752732368338110cb50fa6cd7717fvboxsync * deadlocks caused by mixing our locks with the ones in the host kernel.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * The main events are receive, send, async send completion, disappearance of
157093a77f2752732368338110cb50fa6cd7717fvboxsync * the host networking interface and it's reappearance. The latter two events
157093a77f2752732368338110cb50fa6cd7717fvboxsync * are can be caused by driver unloading/loading or the device being physical
157093a77f2752732368338110cb50fa6cd7717fvboxsync * unplugged (e.g. a USB network device).
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * The strategy for dealing with these issues are:
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * - Use a simple state machine.
236b2935f217749893b7034e59da3e3568928acevboxsync * - Require the user (IntNet) to serialize all its calls to us,
236b2935f217749893b7034e59da3e3568928acevboxsync * while at the same time not owning any lock used by any of the
236b2935f217749893b7034e59da3e3568928acevboxsync * the callbacks we might call on receive and async send completion.
236b2935f217749893b7034e59da3e3568928acevboxsync * - Make sure we're 100% idle before disconnecting, and have a
236b2935f217749893b7034e59da3e3568928acevboxsync * disconnected status on both sides to fend off async calls.
236b2935f217749893b7034e59da3e3568928acevboxsync * - Protect the host specific interface handle and the state variables
236b2935f217749893b7034e59da3e3568928acevboxsync * using a spinlock.
236b2935f217749893b7034e59da3e3568928acevboxsync * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release
236b2935f217749893b7034e59da3e3568928acevboxsync * VM, IntNet, NetFlt, Kernel, Wire;
236b2935f217749893b7034e59da3e3568928acevboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>Kernel [label="pkt0 to wire", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * Kernel->Wire [label="pkt0 to wire", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * --- [label="Suspending the trunk interface"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Lock Network"];
236b2935f217749893b7034e59da3e3568928acevboxsync * Wire->Kernel [label="pkt1 - racing us", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * Kernel=>>NetFlt [label="pkt1 - racing us", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>>IntNet [label="pkt1 recv - blocks", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Mark Trunk Suspended"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Unlock Network"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>NetFlt [label="pfnSetActive(false)"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>NetFlt [label="Mark inactive (atomic)"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet<<NetFlt;
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>NetFlt [label="pfnWaitForIdle(forever)"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>>NetFlt [label="pkt1 to host", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>>Kernel [label="pkt1 to host", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * Kernel<-Wire [label="pkt0 on wire", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="pkt0 on wire", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet<<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet<<=IntNet [label="Lock Net, free SG, Unlock Net", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<-NetFlt [label="idle", linecolor="green", textcolor="green"];
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * IntNet<<NetFlt [label="idle (pfnWaitForIdle)"];
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Wire->Kernel [label="pkt2", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * Kernel=>>NetFlt [label="pkt2", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>>Kernel [label="pkt2 to host", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * VM->IntNet [label="pkt3", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Route packet -> drop", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * --- [label="The trunk interface is idle now, disconnect it"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Lock Network"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Unlink Trunk"];
4ab1e1de561327173718600b82c542cbe1cc878cvboxsync * IntNet=>IntNet [label="Unlock Network"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>NetFlt [label="pfnDisconnectAndRelease"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>Kernel [label="iflt_detach"];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * NetFlt<<=Kernel [label="iff_detached"];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * NetFlt>>Kernel [label="iff_detached"];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * NetFlt<<Kernel [label="iflt_detach"];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * NetFlt=>NetFlt [label="Release"];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * IntNet<<NetFlt [label="pfnDisconnectAndRelease"];
bc5cd42756b3f98351040bbfccc08dd9bacd103avboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Removal
236b2935f217749893b7034e59da3e3568928acevboxsync * The ifnet_t (pIf) is a tricky customer as any reference to it can potentially
236b2935f217749893b7034e59da3e3568928acevboxsync * race the filter detaching. The simple way of solving it on Darwin is to guard
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * all access to the pIf member with a spinlock. The other host systems will
236b2935f217749893b7034e59da3e3568928acevboxsync * probably have similar race conditions, so the spinlock is a generic thing.
236b2935f217749893b7034e59da3e3568928acevboxsync * VM, IntNet, NetFlt, Kernel;
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * NetFlt=>Kernel [label="ifnet_reference w/ spinlock", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="ifnet_reference", linecolor="green", textcolor="green" ];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * NetFlt=>Kernel [label="pkt0 to wire (blocks)", linecolor="green", textcolor="green" ];
236b2935f217749893b7034e59da3e3568928acevboxsync * --- [label="The host interface is being disconnected"];
236b2935f217749893b7034e59da3e3568928acevboxsync * Kernel->NetFlt [label="iff_detached"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>Kernel [label="ifnet_release w/ spinlock"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="ifnet_release"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>NetFlt [label="fDisconnectedFromHost=true"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * NetFlt>>Kernel [label="iff_detached"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="dropped", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>NetFlt [label="Acquire spinlock", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * NetFlt=>NetFlt [label="pIf=NULL", linecolor="green", textcolor="green"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * NetFlt=>NetFlt [label="Release spinlock", linecolor="green", textcolor="green"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet<<NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery
157093a77f2752732368338110cb50fa6cd7717fvboxsync * The rediscovery is performed when we receive a send request and a certain
157093a77f2752732368338110cb50fa6cd7717fvboxsync * period have elapsed since the last attempt, i.e. we're polling it. We
157093a77f2752732368338110cb50fa6cd7717fvboxsync * synchronize the rediscovery with disconnection from the internal network
157093a77f2752732368338110cb50fa6cd7717fvboxsync * by means of the pfnWaitForIdle call, so no special handling is required.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * VM2, VM1, IntNet, NetFlt, Kernel, Wire;
157093a77f2752732368338110cb50fa6cd7717fvboxsync * --- [label="Rediscovery conditions are not met"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * VM1->IntNet [label="pkt0"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet=>IntNet [label="Lock Network"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet=>IntNet [label="Unlock Network"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet=>NetFlt [label="pkt0 to wire"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet<<NetFlt [label="pkt0 to wire (dropped)"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * --- [label="Rediscovery conditions"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * VM1->IntNet [label="pkt1"];
157093a77f2752732368338110cb50fa6cd7717fvboxsync * IntNet=>IntNet [label="Lock Network"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Route packet -> wire"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Unlock Network"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * IntNet=>NetFlt [label="pkt1 to wire"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * NetFlt=>NetFlt [label="fRediscoveryPending=true w/ spinlock"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>Kernel [label="ifnet_find_by_name"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="ifnet_find_by_name (success)"];
236b2935f217749893b7034e59da3e3568928acevboxsync * VM2->IntNet [label="pkt2", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Lock Network", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet=>NetFlt [label="pkt2 to wire", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>NetFlt [label="!pIf || fRediscoveryPending (w/ spinlock)", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * IntNet<<NetFlt [label="pkt2 to wire (dropped)", linecolor="red", textcolor="red"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>Kernel [label="iflt_attach"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt<<Kernel [label="iflt_attach (success)"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>NetFlt [label="Acquire spinlock"];
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * NetFlt=>NetFlt [label="Set pIf and update flags"];
236b2935f217749893b7034e59da3e3568928acevboxsync * NetFlt=>NetFlt [label="Release spinlock"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * NetFlt=>Kernel [label="pkt1 to wire"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * Kernel->Wire [label="pkt1 to wire"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * NetFlt<<Kernel [label="pkt1 to wire"];
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync * IntNet<<NetFlt [label="pkt1 to wire"];
236b2935f217749893b7034e59da3e3568928acevboxsync/*******************************************************************************
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync* Header Files *
236b2935f217749893b7034e59da3e3568928acevboxsync*******************************************************************************/
236b2935f217749893b7034e59da3e3568928acevboxsync/*******************************************************************************
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync* Defined Constants And Macros *
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync*******************************************************************************/
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync ( (PVBOXNETFLTINS)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETFLTINS, MyPort)) )
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncAssertCompileMemberSize(VBOXNETFLTINS, enmState, sizeof(uint32_t));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Sets the enmState member atomically.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Used for all updates.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pThis The instance.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param enmNewState The new value.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncDECLINLINE(void) vboxNetFltSetState(PVBOXNETFLTINS pThis, VBOXNETFTLINSSTATE enmNewState)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Gets the enmState member atomically.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Used for all reads.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns The enmState value.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pThis The instance.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncDECLINLINE(VBOXNETFTLINSSTATE) vboxNetFltGetState(PVBOXNETFLTINS pThis)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return (VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Finds a instance by its name, the caller does the locking.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pGlobals The globals.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pszName The name of the instance.
236b2935f217749893b7034e59da3e3568928acevboxsyncstatic PVBOXNETFLTINS vboxNetFltFindInstanceLocked(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
236b2935f217749893b7034e59da3e3568928acevboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Finds a instance by its name, will request the mutex.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * No reference to the instance is retained, we're assuming the caller to
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * already have one but just for some reason doesn't have the pointer to it.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pGlobals The globals.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pszName The name of the instance.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncDECLHIDDEN(PVBOXNETFLTINS) vboxNetFltFindInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync pRet = vboxNetFltFindInstanceLocked(pGlobals, pszName);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Unlinks an instance from the chain.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pGlobals The globals.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pToUnlink The instance to unlink.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncstatic void vboxNetFltUnlinkLocked(PVBOXNETFLTGLOBALS pGlobals, PVBOXNETFLTINS pToUnlink)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
236b2935f217749893b7034e59da3e3568928acevboxsync * Performs interface rediscovery if it was disconnected from the host.
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns true if successfully rediscovered and connected, false if not.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pThis The instance.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncstatic bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Rediscovered already? Time to try again?
236b2935f217749893b7034e59da3e3568928acevboxsync fRediscovered = !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
157093a77f2752732368338110cb50fa6cd7717fvboxsync && !ASMAtomicUoReadBool(&pThis->fRediscoveryPending)
157093a77f2752732368338110cb50fa6cd7717fvboxsync && Now - ASMAtomicUoReadU64(&pThis->NanoTSLastRediscovery) > UINT64_C(5000000000); /* 5 sec */
157093a77f2752732368338110cb50fa6cd7717fvboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, true);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Call the OS specific code to do the job.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Update the state when the call returns, that is everything except for
157093a77f2752732368338110cb50fa6cd7717fvboxsync * the fDisconnectedFromHost flag which the OS specific code shall set.
157093a77f2752732368338110cb50fa6cd7717fvboxsync fRediscovered = vboxNetFltOsMaybeRediscovered(pThis);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(!fRediscovered || !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost));
157093a77f2752732368338110cb50fa6cd7717fvboxsync ASMAtomicUoWriteU64(&pThis->NanoTSLastRediscovery, RTTimeNanoTS());
157093a77f2752732368338110cb50fa6cd7717fvboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, false);
157093a77f2752732368338110cb50fa6cd7717fvboxsync# if defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64)
157093a77f2752732368338110cb50fa6cd7717fvboxsync# define NETFLT_DECL_CALLBACK(type) DECLASM(DECLHIDDEN(type))
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortXmit)(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous)(PINTNETTRUNKIFPORT pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortGetMacAddress)(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsHostMac)(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortWaitForIdle)(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortSetActive)(PINTNETTRUNKIFPORT pIfPort, bool fActive);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease)(PINTNETTRUNKIFPORT pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRetain)(PINTNETTRUNKIFPORT pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRelease)(PINTNETTRUNKIFPORT pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsync# define NETFLT_DECL_CALLBACK(type) static DECLCALLBACK(type)
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnXmit
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)
157093a77f2752732368338110cb50fa6cd7717fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Input validation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Do a busy retain and then make sure we're connected to the interface
157093a77f2752732368338110cb50fa6cd7717fvboxsync * before invoking the OS specific code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsPromiscuous
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsPromiscuous(PINTNETTRUNKIFPORT pIfPort)
157093a77f2752732368338110cb50fa6cd7717fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Input validation.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Ask the OS specific code.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Input validation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Forward the question to the OS specific code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsHostMac
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsHostMac(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac)
157093a77f2752732368338110cb50fa6cd7717fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Input validation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Ask the OS specific code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
157093a77f2752732368338110cb50fa6cd7717fvboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
157093a77f2752732368338110cb50fa6cd7717fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Input validation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Go to sleep on the semaphore after checking the busy count.
157093a77f2752732368338110cb50fa6cd7717fvboxsync rc = RTSemEventWait(pThis->hEventIdle, cMillies); /** @todo make interruptible? */
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnSetActive
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
157093a77f2752732368338110cb50fa6cd7717fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Input validation.
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, false);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * We're assuming that the caller is serializing the calls, so we don't
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * have to be extremely careful here. Just update first and then call
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * the OS specific code, the update must be serialized for various reasons.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Serious paranoia.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
#ifdef VBOXNETFLT_STATIC_CONFIG
int rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
if (fBusy)
if (!cRefs)
if (!cRefs)
if (fBusy)
static int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
int rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
return rc;
static int vboxNetFltNewInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PINTNETTRUNKSWPORT pSwitchPort,
int rc;
if (!pNew)
return VERR_INTNET_FLT_IF_FAILED;
#ifdef VBOXNETFLT_STATIC_CONFIG
return rc;
return rc;
return rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
DECLHIDDEN(int) vboxNetFltSearchCreateInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PVBOXNETFLTINS *ppInstance, void *pvContext)
int rc;
while (pCur)
switch (enmState)
return VINF_ALREADY_INITIALIZED;
LogRel(("VBoxNetFlt: Huh? An instance of '%s' already exists! [pCur=%p cRefs=%d fDfH=%RTbool enmState=%d]\n",
return VERR_INTNET_FLT_IF_BUSY;
# ifdef RT_STRICT
return rc;
static DECLCALLBACK(int) vboxNetFltFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
int rc;
LogFlow(("vboxNetFltFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
if (pCur)
#ifdef VBOXNETFLT_STATIC_CONFIG
if (pCur)
return rc;
#ifdef VBOXNETFLT_STATIC_CONFIG
NULL,
ppIfPort);
return rc;
PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
static DECLCALLBACK(void *) vboxNetFltQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, SupDrvFactory));
#ifdef LOG_ENABLED
return NULL;
return fRc;
int rc;
return VERR_WRONG_ORDER;
return VERR_WRONG_ORDER;
return rc;
int rc;
rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;