VBoxNetFlt.c revision eeb6c0c9cd7482b990f5b20f9b7c867e501dd392
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/* $Id$ */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/** @file
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VBoxNetFlt - Network Filter Driver (Host), Common Code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Copyright (C) 2008-2009 Sun Microsystems, Inc.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * available from http://www.virtualbox.org. This file is free software;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * General Public License (GPL) as published by the Free Software
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * additional information or have any questions.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/** @page pg_netflt VBoxNetFlt - Network Interface Filter
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This is a kernel module that attaches to a real interface on the host
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * and filters and injects packets.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * In the big picture we're one of the three trunk interface on the internal
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * network, the one named "NIC Filter Driver": @image html Networking_Overview.gif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @section sec_netflt_msc Locking / Sequence Diagrams
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This secion contains a few sequence diagrams describing the problematic
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * transitions of a host interface filter instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The thing that makes it all a bit problematic is that multiple events may
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * happen at the same time, and that we have to be very careful to avoid
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * deadlocks caused by mixing our locks with the ones in the host kernel.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The main events are receive, send, async send completion, disappearance of
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * the host networking interface and it's reappearance. The latter two events
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * are can be caused by driver unloading/loading or the device being physical
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * unplugged (e.g. a USB network device).
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The strategy for dealing with these issues are:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * - Use a simple state machine.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * - Require the user (IntNet) to serialize all its calls to us,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * while at the same time not owning any lock used by any of the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * the callbacks we might call on receive and async send completion.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * - Make sure we're 100% idle before disconnecting, and have a
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * disconnected status on both sides to fend off async calls.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * - Protect the host specific interface handle and the state variables
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * using a spinlock.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @msc
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM, IntNet, NetFlt, Kernel, Wire;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="pkt0 to wire", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Kernel->Wire [label="pkt0 to wire", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * --- [label="Suspending the trunk interface"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Lock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Wire->Kernel [label="pkt1 - racing us", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Kernel=>>NetFlt [label="pkt1 - racing us", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>>IntNet [label="pkt1 recv - blocks", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Mark Trunk Suspended"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>NetFlt [label="pfnSetActive(false)"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Mark inactive (atomic)"];
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * IntNet<<NetFlt;
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * IntNet=>NetFlt [label="pfnWaitForIdle(forever)"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * IntNet=>>NetFlt [label="pkt1 to host", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>>Kernel [label="pkt1 to host", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Kernel<-Wire [label="pkt0 on wire", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="pkt0 on wire", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<=IntNet [label="Lock Net, free SG, Unlock Net", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<-NetFlt [label="idle", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<NetFlt [label="idle (pfnWaitForIdle)"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Wire->Kernel [label="pkt2", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Kernel=>>NetFlt [label="pkt2", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>>Kernel [label="pkt2 to host", linecolor="red", textcolor="red"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * VM->IntNet [label="pkt3", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Route packet -> drop", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * --- [label="The trunk interface is idle now, disconnect it"];
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * IntNet=>IntNet [label="Lock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlink Trunk"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>NetFlt [label="pfnDisconnectAndRelease"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="iflt_detach"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<=Kernel [label="iff_detached"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt>>Kernel [label="iff_detached"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="iflt_detach"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Release"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<NetFlt [label="pfnDisconnectAndRelease"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @endmsc
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Removal
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The ifnet_t (pIf) is a tricky customer as any reference to it can potentially
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * race the filter detaching. The simple way of solving it on Darwin is to guard
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * all access to the pIf member with a spinlock. The other host systems will
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * probably have similar race conditions, so the spinlock is a generic thing.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @msc
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM, IntNet, NetFlt, Kernel;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="ifnet_reference w/ spinlock", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="ifnet_reference", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="pkt0 to wire (blocks)", linecolor="green", textcolor="green" ];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * --- [label="The host interface is being disconnected"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Kernel->NetFlt [label="iff_detached"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="ifnet_release w/ spinlock"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="ifnet_release"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="fDisconnectedFromHost=true"];
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * NetFlt>>Kernel [label="iff_detached"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="dropped", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Acquire spinlock", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="pIf=NULL", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Release spinlock", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @endmsc
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The rediscovery is performed when we receive a send request and a certain
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * period have elapsed since the last attempt, i.e. we're polling it. We
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * synchronize the rediscovery with disconnection from the internal network
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * by means of the pfnWaitForIdle call, so no special handling is required.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @msc
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM2, VM1, IntNet, NetFlt, Kernel, Wire;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * --- [label="Rediscovery conditions are not met"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM1->IntNet [label="pkt0"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Lock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Unlock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>NetFlt [label="pkt0 to wire"];
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<NetFlt [label="pkt0 to wire (dropped)"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * --- [label="Rediscovery conditions"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VM1->IntNet [label="pkt1"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Lock Network"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet=>IntNet [label="Unlock Network"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet=>NetFlt [label="pkt1 to wire"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * NetFlt=>NetFlt [label="fRediscoveryPending=true w/ spinlock"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * NetFlt=>Kernel [label="ifnet_find_by_name"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * NetFlt<<Kernel [label="ifnet_find_by_name (success)"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync *
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * VM2->IntNet [label="pkt2", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet=>NetFlt [label="pkt2 to wire", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * NetFlt=>NetFlt [label="!pIf || fRediscoveryPending (w/ spinlock)", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * IntNet<<NetFlt [label="pkt2 to wire (dropped)", linecolor="red", textcolor="red"];
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="iflt_attach"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="iflt_attach (success)"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Acquire spinlock"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Set pIf and update flags"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>NetFlt [label="Release spinlock"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt=>Kernel [label="pkt1 to wire"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Kernel->Wire [label="pkt1 to wire"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * NetFlt<<Kernel [label="pkt1 to wire"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IntNet<<NetFlt [label="pkt1 to wire"];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @endmsc
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync* Header Files *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "VBoxNetFltInternal.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <VBox/sup.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <VBox/log.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <VBox/err.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/assert.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/string.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/spinlock.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/uuid.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/mem.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/time.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/semaphore.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/thread.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Defined Constants And Macros *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define IFPORT_2_VBOXNETFLTINS(pIfPort) \
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ( (PVBOXNETFLTINS)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETFLTINS, MyPort)) )
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
83d61602c6968041692aa7203ee51c4085c7e460vboxsync
83d61602c6968041692aa7203ee51c4085c7e460vboxsyncAssertCompileMemberSize(VBOXNETFLTINS, enmState, sizeof(uint32_t));
83d61602c6968041692aa7203ee51c4085c7e460vboxsync
83d61602c6968041692aa7203ee51c4085c7e460vboxsync/**
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * Sets the enmState member atomically.
83d61602c6968041692aa7203ee51c4085c7e460vboxsync *
83d61602c6968041692aa7203ee51c4085c7e460vboxsync * Used for all updates.
83d61602c6968041692aa7203ee51c4085c7e460vboxsync *
83d61602c6968041692aa7203ee51c4085c7e460vboxsync * @param pThis The instance.
83d61602c6968041692aa7203ee51c4085c7e460vboxsync * @param enmNewState The new value.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync */
83d61602c6968041692aa7203ee51c4085c7e460vboxsyncDECLINLINE(void) vboxNetFltSetState(PVBOXNETFLTINS pThis, VBOXNETFTLINSSTATE enmNewState)
795d02542d53f15030f205374c4581d99ef581a4vboxsync{
795d02542d53f15030f205374c4581d99ef581a4vboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
795d02542d53f15030f205374c4581d99ef581a4vboxsync}
795d02542d53f15030f205374c4581d99ef581a4vboxsync
795d02542d53f15030f205374c4581d99ef581a4vboxsync
83d61602c6968041692aa7203ee51c4085c7e460vboxsync/**
83d61602c6968041692aa7203ee51c4085c7e460vboxsync * Gets the enmState member atomically.
83d61602c6968041692aa7203ee51c4085c7e460vboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Used for all reads.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns The enmState value.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pThis The instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLINLINE(VBOXNETFTLINSSTATE) vboxNetFltGetState(PVBOXNETFLTINS pThis)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return (VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Finds a instance by its name, the caller does the locking.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals The globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pszName The name of the instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic PVBOXNETFLTINS vboxNetFltFindInstanceLocked(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pCur;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!strcmp(pszName, pCur->szName))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return pCur;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Finds a instance by its name, will request the mutex.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * No reference to the instance is retained, we're assuming the caller to
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * already have one but just for some reason doesn't have the pointer to it.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals The globals.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * @param pszName The name of the instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(PVBOXNETFLTINS) vboxNetFltFindInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pRet;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRCReturn(rc, NULL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pRet = vboxNetFltFindInstanceLocked(pGlobals, pszName);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return pRet;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * Unlinks an instance from the chain.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals The globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pToUnlink The instance to unlink.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic void vboxNetFltUnlinkLocked(PVBOXNETFLTGLOBALS pGlobals, PVBOXNETFLTINS pToUnlink)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pGlobals->pInstanceHead == pToUnlink)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->pInstanceHead = pToUnlink->pNext;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pCur;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pCur->pNext == pToUnlink)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pCur->pNext = pToUnlink->pNext;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync break;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync Assert(pCur);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pToUnlink->pNext = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Performs interface rediscovery if it was disconnected from the host.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns true if successfully rediscovered and connected, false if not.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pThis The instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync uint64_t Now = RTTimeNanoTS();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync bool fRediscovered;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync bool fDoIt;
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Rediscovered already? Time to try again?
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync fRediscovered = !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync fDoIt = !fRediscovered
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync && !ASMAtomicUoReadBool(&pThis->fRediscoveryPending)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync && Now - ASMAtomicUoReadU64(&pThis->NanoTSLastRediscovery) > UINT64_C(5000000000); /* 5 sec */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (fDoIt)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, true);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Call the OS specific code to do the job.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Update the state when the call returns, that is everything except for
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * the fDisconnectedFromHost flag which the OS specific code shall set.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (fDoIt)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync fRediscovered = vboxNetFltOsMaybeRediscovered(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!fRediscovered || !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ASMAtomicUoWriteU64(&pThis->NanoTSLastRediscovery, RTTimeNanoTS());
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, false);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (fRediscovered)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltPortOsSetActive(pThis, pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return fRediscovered;
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef RT_WITH_W64_UNWIND_HACK
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# if defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# define NETFLT_DECL_CALLBACK(type) DECLASM(DECLHIDDEN(type))
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync# define NETFLT_CALLBACK(_n) netfltNtWrap##_n
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortXmit)(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous)(PINTNETTRUNKIFPORT pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortGetMacAddress)(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsHostMac)(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortWaitForIdle)(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortSetActive)(PINTNETTRUNKIFPORT pIfPort, bool fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease)(PINTNETTRUNKIFPORT pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRetain)(PINTNETTRUNKIFPORT pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRelease)(PINTNETTRUNKIFPORT pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# error "UNSUPPORTED (RT_WITH_W64_UNWIND_HACK)"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# define NETFLT_DECL_CALLBACK(type) static DECLCALLBACK(type)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# define NETFLT_CALLBACK(_n) _n
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnXmit
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Input validation.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pSG);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync Assert(pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Do a busy retain and then make sure we're connected to the interface
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * before invoking the OS specific code.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltRetain(pThis, true /* fBusy */);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync || vboxNetFltMaybeRediscovered(pThis))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltPortOsXmit(pThis, pSG, fDst);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltRelease(pThis, true /* fBusy */);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsPromiscuous
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsPromiscuous(PINTNETTRUNKIFPORT pIfPort)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Input validation.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Ask the OS specific code.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return vboxNetFltPortOsIsPromiscuous(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Input validation.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Forward the question to the OS specific code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltPortOsGetMacAddress(pThis, pMac);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsHostMac
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsHostMac(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Input validation.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Ask the OS specific code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return vboxNetFltPortOsIsHostMac(pThis, pMac);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Input validation.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertReturn(!pThis->fActive, VERR_INVALID_STATE);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Go to sleep on the semaphore after checking the busy count.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltRetain(pThis, false /* fBusy */);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync while (pThis->cBusy && RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemEventWait(pThis->hEventIdle, cMillies); /** @todo make interruptible? */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltRelease(pThis, false /* fBusy */);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnSetActive
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Input validation.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis->pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, false);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * We're assuming that the caller is serializing the calls, so we don't
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * have to be extremely careful here. Just update first and then call
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * the OS specific code, the update must be serialized for various reasons.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (ASMAtomicReadBool(&pThis->fActive) != fActive)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync ASMAtomicWriteBool(&pThis->fActive, fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltPortOsSetActive(pThis, fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync fActive = !fActive;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return !fActive;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Serious paranoia.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis->pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->szName[0]);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fRediscoveryPending);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->cBusy);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Disconnect and release it.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltOsDisconnectIt(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pSwitchPort = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Unconnected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync vboxNetFltRelease(pThis, false /* fBusy */);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Destroy a device that has been disconnected from the switch.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns true if the instance is destroyed, false otherwise.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pThis The instance to be destroyed. This is
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * no longer valid when this function returns.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic bool vboxNetFltDestroyInstance(PVBOXNETFLTINS pThis)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTGLOBALS pGlobals = pThis->pGlobals;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync uint32_t cRefs = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("vboxNetFltDestroyInstance: pThis=%p (%s)\n", pThis, pThis->szName));
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Validate the state.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert( vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync || vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fRediscoveryPending);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->cBusy);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->pSwitchPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * Make sure the state is 'disconnecting' / 'destroying' and let the OS
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * specific code do its part of the cleanup outside the mutex.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx); AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltOsDeleteInstance(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Unlink the instance and free up its resources.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx); AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Destroyed);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltUnlinkLocked(pGlobals, pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync RTSemEventDestroy(pThis->hEventIdle);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->hEventIdle = NIL_RTSEMEVENT;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockDestroy(pThis->hSpinlock);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->hSpinlock = NIL_RTSPINLOCK;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTMemFree(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NOREF(cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return true;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Releases a reference to the specified instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This method will destroy the instance when the count reaches 0.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * It will also take care of decrementing the counter and idle wakeup.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pThis The instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param fBusy Whether the busy counter should be decremented too.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(void) vboxNetFltRelease(PVBOXNETFLTINS pThis, bool fBusy)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync uint32_t cRefs;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Paranoid Android.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis->pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pThis->szName[0]);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Work the busy counter.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (fBusy)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync cRefs = ASMAtomicDecU32(&pThis->cBusy);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!cRefs)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = RTSemEventSignal(pThis->hEventIdle);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(cRefs < UINT32_MAX / 2);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The object reference counting.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync cRefs = ASMAtomicDecU32(&pThis->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!cRefs)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltDestroyInstance(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync Assert(cRefs < UINT32_MAX / 2);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortRelease(PINTNETTRUNKIFPORT pIfPort)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync vboxNetFltRelease(pThis, false /* fBusy */);
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync}
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync/**
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * Retains a reference to the specified instance and a busy reference too.
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync *
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * @param pThis The instance.
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync * @param fBusy Whether the busy counter should be incremented as well.
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync */
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsyncDECLHIDDEN(void) vboxNetFltRetain(PVBOXNETFLTINS pThis, bool fBusy)
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync{
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync uint32_t cRefs;
ecb98c0e709a5cebd8877fb39f61a821804024bcvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Paranoid Android.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertPtr(pThis);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
83d61602c6968041692aa7203ee51c4085c7e460vboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync AssertPtr(pThis->pGlobals);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync Assert(pThis->szName[0]);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Retain the object.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync cRefs = ASMAtomicIncU32(&pThis->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(cRefs > 1 && cRefs < UINT32_MAX / 2);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Work the busy counter.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync if (fBusy)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync cRefs = ASMAtomicIncU32(&pThis->cBusy);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(cRefs > 0 && cRefs < UINT32_MAX / 2);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NOREF(cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortRetain(PINTNETTRUNKIFPORT pIfPort)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltRetain(pThis, false /* fBusy */);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Connects the instance to the specified switch port.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Called while owning the lock. We're ASSUMING that the internal
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * networking code is already owning an recursive mutex, so, there
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * will be no deadlocks when vboxNetFltOsConnectIt calls back into
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * it for setting preferences.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pThis The instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pSwitchPort The port on the internal network 'switch'.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param ppIfPort Where to return our port interface.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Validate state.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fRediscoveryPending);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->cBusy);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Initializing);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Do the job.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * Note that we're calling the os stuff while owning the semaphore here.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pSwitchPort = pSwitchPort;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltOsConnectIt(pThis);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Connected);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppIfPort = &pThis->MyPort;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pSwitchPort = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pThis->fActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Creates a new instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The new instance will be in the suspended state in a dynamic config and in
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * the inactive in a static one.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Called without owning the lock, but will request is several times.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals The globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pszName The instance name.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pSwitchPort The port on the switch that we're connected with (dynamic only).
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param fNoPromisc Do not attempt going into promiscuous mode.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pvContext Context argument for vboxNetFltOsInitInstance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param ppIfPort Where to store the pointer to our port interface (dynamic only).
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic int vboxNetFltNewInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PINTNETTRUNKSWPORT pSwitchPort,
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync bool fNoPromisc, void *pvContext, PINTNETTRUNKIFPORT *ppIfPort)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Allocate and initialize a new instance before requesting the mutex.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync size_t const cchName = strlen(pszName);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pNew = (PVBOXNETFLTINS)RTMemAllocZ(RT_OFFSETOF(VBOXNETFLTINS, szName[cchName + 1]));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!pNew)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VERR_INTNET_FLT_IF_FAILED;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->pNext = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.u32Version = INTNETTRUNKIFPORT_VERSION;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnRetain = NETFLT_CALLBACK(vboxNetFltPortRetain);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnRelease = NETFLT_CALLBACK(vboxNetFltPortRelease);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnDisconnectAndRelease= NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnSetActive = NETFLT_CALLBACK(vboxNetFltPortSetActive);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnWaitForIdle = NETFLT_CALLBACK(vboxNetFltPortWaitForIdle);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync pNew->MyPort.pfnGetMacAddress = NETFLT_CALLBACK(vboxNetFltPortGetMacAddress);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnIsHostMac = NETFLT_CALLBACK(vboxNetFltPortIsHostMac);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnIsPromiscuous = NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.pfnXmit = NETFLT_CALLBACK(vboxNetFltPortXmit);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->pSwitchPort = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->pGlobals = pGlobals;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->hSpinlock = NIL_RTSPINLOCK;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->enmState = kVBoxNetFltInsState_Initializing;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->fActive = false;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->fDisconnectedFromHost = false;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->fRediscoveryPending = false;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->fDisablePromiscuous = fNoPromisc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->NanoTSLastRediscovery = INT64_MAX;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->cRefs = 1;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->cBusy = 0;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->hEventIdle = NIL_RTSEMEVENT;
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync memcpy(pNew->szName, pszName, cchName + 1);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSpinlockCreate(&pNew->hSpinlock);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemEventCreate(&pNew->hEventIdle);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltOsPreInitInstance(pNew);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Insert the instance into the chain, checking for
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * duplicates first of course (race).
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!vboxNetFltFindInstanceLocked(pGlobals, pszName))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->pNext = pGlobals->pInstanceHead;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->pInstanceHead = pNew;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Call the OS specific initialization code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltOsInitInstance(pNew, pvContext);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Static instances are unconnected at birth.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pSwitchPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pNew->enmState = kVBoxNetFltInsState_Unconnected;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppIfPort = &pNew->MyPort;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#else /* !VBOXNETFLT_STATIC_CONFIG */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Connect it as well, the OS specific bits has to be done outside
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * the lock as they may call back to into intnet.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltConnectIt(pNew, pSwitchPort, ppIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(*ppIfPort == &pNew->MyPort);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Bail out (failed). */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltOsDeleteInstance(pNew);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif /* !VBOXNETFLT_STATIC_CONFIG */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltUnlinkLocked(pGlobals, pNew);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_INTNET_FLT_IF_BUSY;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemEventDestroy(pNew->hEventIdle);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSpinlockDestroy(pNew->hSpinlock);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTMemFree(pNew);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Searches for the NetFlt instance by its name and creates the new one if not found.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @retval VINF_SUCCESS and *ppInstance if a new instance was created.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @retval VINF_ALREADY_INITIALIZED and *ppInstance if an instance already exists.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobal Pointer to the globals.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * @param pszName The instance name.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param ppInstance Where to return the instance pointer on success.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pvContext Context which needs to be passed along to vboxNetFltOsInitInstance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(int) vboxNetFltSearchCreateInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PVBOXNETFLTINS *ppInstance, void *pvContext)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PINTNETTRUNKIFPORT pIfPort;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pCur;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync VBOXNETFTLINSSTATE enmState;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppInstance = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRCReturn(rc, rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Look for an existing instance in the list.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * There might be an existing one in the list if the driver was unbound
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * while it was connected to an internal network. We're running into
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * a destruction race that is a bit similar to the one in
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * vboxNetFltFactoryCreateAndConnect, only the roles are reversed
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * and we're not in a position to back down. Instead of backing down
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * we'll delay a bit giving the other thread time to complete the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * destructor.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync while (pCur)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (cRefs > 1)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync enmState = vboxNetFltGetState(pCur);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync switch (enmState)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync case kVBoxNetFltInsState_Unconnected:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync case kVBoxNetFltInsState_Connected:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync case kVBoxNetFltInsState_Disconnecting:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pCur->fDisconnectedFromHost)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Wait for it to exit the transitional disconnecting
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync state. It might otherwise be running the risk of
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync upsetting the OS specific code... */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** @todo This reconnect stuff should be serialized correctly for static
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * devices. Shouldn't it? In the dynamic case we're using the INTNET
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * outbound thrunk lock, but that doesn't quite cut it here, or does
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * it? We could either transition to initializing or make a callback
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * while owning the mutext here... */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (enmState == kVBoxNetFltInsState_Disconnecting)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync do
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTThreadSleep(2); /* (2ms) */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync enmState = vboxNetFltGetState(pCur);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync while (enmState == kVBoxNetFltInsState_Disconnecting);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertMsg(enmState == kVBoxNetFltInsState_Unconnected, ("%d\n", enmState));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pCur->fDisconnectedFromHost);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppInstance = pCur;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VINF_ALREADY_INITIALIZED;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* fall thru */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync default:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync bool fDfH = pCur->fDisconnectedFromHost;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltRelease(pCur, false /* fBusy */);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogRel(("VBoxNetFlt: Huh? An instance of '%s' already exists! [pCur=%p cRefs=%d fDfH=%RTbool enmState=%d]\n",
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pszName, pCur, cRefs - 1, fDfH, enmState));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppInstance = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VERR_INTNET_FLT_IF_BUSY;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Zero references, it's being destroyed. Delay a bit so the destructor
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync can finish its work and try again. (vboxNetFltNewInstance will fail
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync with duplicate name if we don't.) */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# ifdef RT_STRICT
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(cRefs == 1);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync enmState = vboxNetFltGetState(pCur);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertMsg( enmState == kVBoxNetFltInsState_Unconnected
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync || enmState == kVBoxNetFltInsState_Disconnecting
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync || enmState == kVBoxNetFltInsState_Destroyed, ("%d\n", enmState));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync# endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ASMAtomicDecU32(&pCur->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTThreadSleep(2); /* (2ms) */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRCReturn(rc, rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* try again */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Try create a new instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * (fNoPromisc is overridden in the vboxNetFltFactoryCreateAndConnect path, so pass true here.)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltNewInstance(pGlobals, pszName, NULL, true /* fNoPromisc */, pvContext, &pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppInstance = IFPORT_2_VBOXNETFLTINS(pIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *ppInstance = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif /* VBOXNETFLT_STATIC_CONFIG */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) vboxNetFltFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PINTNETTRUNKIFPORT *ppIfPort)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTINS pCur;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pGlobals->cFactoryRefs > 0);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertMsgReturn(!(fFlags & ~(INTNETTRUNKFACTORY_FLAG_NO_PROMISC)),
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Static: Find instance, check if busy, connect if not.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Dynamic: Check for duplicate / busy interface instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRCReturn(rc, rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync//#if defined(VBOX_TAPMINIPORT) && defined(RT_OS_WINDOWS)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync// /* temporary hack to pick up the first adapter */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync// pCur = pGlobals->pInstanceHead; /** @todo Don't for get to remove this temporary hack... :-) */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync//#else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync//#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pCur)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Try grab a reference. If the count had already reached zero we're racing the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync destructor code and must back down. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (cRefs > 1)
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (vboxNetFltGetState(pCur) == kVBoxNetFltInsState_Unconnected)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pCur->fDisablePromiscuous = !!(fFlags & INTNETTRUNKFACTORY_FLAG_NO_PROMISC);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltConnectIt(pCur, pSwitchPort, ppIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pCur = NULL; /* Don't release it, reference given to the caller. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_INTNET_FLT_IF_BUSY;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync Assert(cRefs == 1);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ASMAtomicDecU32(&pCur->cRefs);
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync pCur = NULL; /* nothing to release */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_INTNET_FLT_IF_NOT_FOUND;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pCur)
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync vboxNetFltRelease(pCur, false /* fBusy */);
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync#else
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync rc = VERR_INTNET_FLT_IF_BUSY;
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync#endif
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: returns %Rrc\n", rc));
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync return rc;
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_INTNET_FLT_IF_NOT_FOUND;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Dynamically create a new instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltNewInstance(pGlobals,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pszName,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pSwitchPort,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync !!(fFlags & INTNETTRUNKFACTORY_FLAG_NO_PROMISC),
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ppIfPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: returns %Rrc\n", rc));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc INTNETTRUNKFACTORY::pfnRelease
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) vboxNetFltFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(cRefs >= 0); NOREF(cRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("vboxNetFltFactoryRelease: cRefs=%d (new)\n", cRefs));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Implements the SUPDRV component factor interface query method.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns Pointer to an interface. NULL if not supported.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pSupDrvFactory Pointer to the componet factory registration structure.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pSession The session - unused.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pszInterfaceUuid The factory interface id.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void *) vboxNetFltQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, SupDrvFactory));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Convert the UUID strings and compare them.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTUUID UuidReq;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ASMAtomicIncS32(&pGlobals->cFactoryRefs);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return &pGlobals->TrunkFactory;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#ifdef LOG_ENABLED
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* log legacy queries */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* else if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_V1_UUID_STR))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Log(("VBoxNetFlt: V1 factory query\n"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Log(("VBoxNetFlt: unknown factory interface query (%s)\n", pszInterfaceUuid));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Log(("VBoxNetFlt: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Checks whether the VBoxNetFlt wossname can be unloaded.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This will return false if someone is currently using the module.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns true if it's relatively safe to unload it, otherwise false.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(bool) vboxNetFltCanUnload(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync bool fRc = !pGlobals->pInstanceHead
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync && pGlobals->cFactoryRefs <= 0;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return fRc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Try to close the IDC connection to SUPDRV if established.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @retval VINF_SUCCESS on success.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @retval VERR_WRONG_ORDER if we're busy.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @sa vboxNetFltTryDeleteIdcAndGlobals()
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(int) vboxNetFltTryDeleteIdc(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Check before trying to deregister the factory.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!vboxNetFltCanUnload(pGlobals))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VERR_WRONG_ORDER;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!pGlobals->fIDCOpen)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Disconnect from SUPDRV and check that nobody raced us,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * reconnect if that should happen.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!vboxNetFltCanUnload(pGlobals))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertRC(rc);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VERR_WRONG_ORDER;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SUPR0IdcClose(&pGlobals->SupDrvIDC);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->fIDCOpen = false;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Establishes the IDC connection to SUPDRV and registers our component factory.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @sa vboxNetFltInitGlobalsAndIdc().
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(int) vboxNetFltInitIdc(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pGlobals->fIDCOpen);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Establish a connection to SUPDRV and register our component factory.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->fIDCOpen = true;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Log(("VBoxNetFlt: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* bail out. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogRel(("VBoxNetFlt: Failed to register component factory, rc=%Rrc\n", rc));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SUPR0IdcClose(&pGlobals->SupDrvIDC);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Deletes the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This must be called after the IDC connection has been closed,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * see vboxNetFltTryDeleteIdc().
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @sa vboxNetFltTryDeleteIdcAndGlobals()
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(void) vboxNetFltDeleteGlobals(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(!pGlobals->fIDCOpen);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Release resources.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTSemFastMutexDestroy(pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Initializes the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @sa vboxNetFltInitGlobalsAndIdc().
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(int) vboxNetFltInitGlobals(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Initialize the common portions of the structure.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->pInstanceHead = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->TrunkFactory.pfnRelease = vboxNetFltFactoryRelease;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetFltFactoryCreateAndConnect;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#if defined(RT_OS_WINDOWS) && defined(VBOX_TAPMINIPORT)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetAdp");
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync#else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetFlt");
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetFltQueryFactoryInterface;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pGlobals->fIDCOpen = false;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Called by the native part when the OS wants the driver to unload.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * @returns VINF_SUCCESS on success, VERR_WRONG_ORDER if we're busy.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(int) vboxNetFltTryDeleteIdcAndGlobals(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = vboxNetFltTryDeleteIdc(pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltDeleteGlobals(pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Called by the native driver/kext module initialization routine.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * It will initialize the common parts of the globals, assuming the caller
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * has already taken care of the OS specific bits, and establish the IDC
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * connection to SUPDRV.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync * @param pGlobals Pointer to the globals.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncDECLHIDDEN(int) vboxNetFltInitGlobalsAndIdc(PVBOXNETFLTGLOBALS pGlobals)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Initialize the common portions of the structure.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = vboxNetFltInitGlobals(pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = vboxNetFltInitIdc(pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_SUCCESS(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* bail out. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync vboxNetFltDeleteGlobals(pGlobals);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync