de4157257515400c2c25373591135f110227b68cvboxsync/* $Id$ */
de4157257515400c2c25373591135f110227b68cvboxsync/** @file
de4157257515400c2c25373591135f110227b68cvboxsync * VBoxNetFlt - Network Filter Driver (Host), Common Code.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/*
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync * Copyright (C) 2008-2014 Oracle Corporation
de4157257515400c2c25373591135f110227b68cvboxsync *
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * available from http://www.virtualbox.org. This file is free software;
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * General Public License (GPL) as published by the Free Software
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/** @page pg_netflt VBoxNetFlt - Network Interface Filter
de4157257515400c2c25373591135f110227b68cvboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * This is a kernel module that attaches to a real interface on the host and
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * filters and injects packets.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * In the big picture we're one of the three trunk interface on the internal
de4157257515400c2c25373591135f110227b68cvboxsync * network, the one named "NIC Filter Driver": @image html Networking_Overview.gif
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @section sec_netflt_locking Locking and Potential Races
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * The main challenge here is to make sure the netfilter and internal network
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * instances won't be destroyed while someone is calling into them.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * The main calls into or out of of the filter driver are:
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * - Send.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * - Async send completion (not implemented yet)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * - Release by the internal network.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * - Receive.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * - Disappearance of the host networking interface.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * - Reappearance of the host networking interface.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * The latter two calls are can be caused by driver unloading/loading or the
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * device being physical unplugged (e.g. a USB network device). Actually, the
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * unload scenario must fervently be prevent as it will cause panics because the
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * internal network will assume the trunk is around until it releases it.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @todo Need to figure which host allow unloading and block/fix it.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Currently the netfilter instance lives until the internal network releases
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * it. So, it is the internal networks responsibility to make sure there are no
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * active calls when it releases the trunk and destroys the network. The
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * netfilter assists in this by providing INTNETTRUNKIFPORT::pfnSetState and
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * INTNETTRUNKIFPORT::pfnWaitForIdle. The trunk state is used to enable/disable
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * promiscuous mode on the hardware NIC (or similar activation) as well
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * indicating that disconnect is imminent and no further calls shall be made
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * into the internal network. After changing the state to disconnecting and
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * prior to invoking INTNETTRUNKIFPORT::pfnDisconnectAndRelease, the internal
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * network will use INTNETTRUNKIFPORT::pfnWaitForIdle to wait for any still
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * active calls to complete.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * The netfilter employs a busy counter and an internal state in addition to the
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * public trunk state. All these variables are protected using a spinlock.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @section sec_netflt_msc Locking / Sequence Diagrams - OBSOLETE
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * !OBSOLETE! - THIS WAS THE OLD APPROACH!
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * This secion contains a few sequence diagrams describing the problematic
de4157257515400c2c25373591135f110227b68cvboxsync * transitions of a host interface filter instance.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * The thing that makes it all a bit problematic is that multiple events may
de4157257515400c2c25373591135f110227b68cvboxsync * happen at the same time, and that we have to be very careful to avoid
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * deadlocks caused by mixing our locks with the ones in the host kernel. The
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * main events are receive, send, async send completion, disappearance of the
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * host networking interface and its reappearance. The latter two events are
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * can be caused by driver unloading/loading or the device being physical
de4157257515400c2c25373591135f110227b68cvboxsync * unplugged (e.g. a USB network device).
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * The strategy for dealing with these issues are:
de4157257515400c2c25373591135f110227b68cvboxsync * - Use a simple state machine.
de4157257515400c2c25373591135f110227b68cvboxsync * - Require the user (IntNet) to serialize all its calls to us,
de4157257515400c2c25373591135f110227b68cvboxsync * while at the same time not owning any lock used by any of the
de4157257515400c2c25373591135f110227b68cvboxsync * the callbacks we might call on receive and async send completion.
de4157257515400c2c25373591135f110227b68cvboxsync * - Make sure we're 100% idle before disconnecting, and have a
de4157257515400c2c25373591135f110227b68cvboxsync * disconnected status on both sides to fend off async calls.
de4157257515400c2c25373591135f110227b68cvboxsync * - Protect the host specific interface handle and the state variables
de4157257515400c2c25373591135f110227b68cvboxsync * using a spinlock.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release - OBSOLETE
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @msc
de4157257515400c2c25373591135f110227b68cvboxsync * VM, IntNet, NetFlt, Kernel, Wire;
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="pkt0 to wire", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * Kernel->Wire [label="pkt0 to wire", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * --- [label="Suspending the trunk interface"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * Wire->Kernel [label="pkt1 - racing us", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * Kernel=>>NetFlt [label="pkt1 - racing us", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>>IntNet [label="pkt1 recv - blocks", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Mark Trunk Suspended"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pfnSetActive(false)"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Mark inactive (atomic)"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt;
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pfnWaitForIdle(forever)"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>>NetFlt [label="pkt1 to host", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>>Kernel [label="pkt1 to host", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * Kernel<-Wire [label="pkt0 on wire", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="pkt0 on wire", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<=IntNet [label="Lock Net, free SG, Unlock Net", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<-NetFlt [label="idle", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt [label="idle (pfnWaitForIdle)"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * Wire->Kernel [label="pkt2", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * Kernel=>>NetFlt [label="pkt2", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>>Kernel [label="pkt2 to host", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * VM->IntNet [label="pkt3", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Route packet -> drop", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * --- [label="The trunk interface is idle now, disconnect it"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlink Trunk"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pfnDisconnectAndRelease"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="iflt_detach"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<=Kernel [label="iff_detached"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt>>Kernel [label="iff_detached"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="iflt_detach"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Release"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt [label="pfnDisconnectAndRelease"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @endmsc
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Removal - OBSOLETE
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * The ifnet_t (pIf) is a tricky customer as any reference to it can potentially
de4157257515400c2c25373591135f110227b68cvboxsync * race the filter detaching. The simple way of solving it on Darwin is to guard
de4157257515400c2c25373591135f110227b68cvboxsync * all access to the pIf member with a spinlock. The other host systems will
de4157257515400c2c25373591135f110227b68cvboxsync * probably have similar race conditions, so the spinlock is a generic thing.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @msc
de4157257515400c2c25373591135f110227b68cvboxsync * VM, IntNet, NetFlt, Kernel;
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * VM->IntNet [label="pkt0", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="ifnet_reference w/ spinlock", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="ifnet_reference", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="pkt0 to wire (blocks)", linecolor="green", textcolor="green" ];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * --- [label="The host interface is being disconnected"];
de4157257515400c2c25373591135f110227b68cvboxsync * Kernel->NetFlt [label="iff_detached"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="ifnet_release w/ spinlock"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="ifnet_release"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="fDisconnectedFromHost=true"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt>>Kernel [label="iff_detached"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="dropped", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Acquire spinlock", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="ifnet_release", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="pIf=NULL", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Release spinlock", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<=NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet>>NetFlt [label="pfnSGRelease", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt [label="pkt0 to wire", linecolor="green", textcolor="green"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @endmsc
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery - OBSOLETE
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * The rediscovery is performed when we receive a send request and a certain
de4157257515400c2c25373591135f110227b68cvboxsync * period have elapsed since the last attempt, i.e. we're polling it. We
de4157257515400c2c25373591135f110227b68cvboxsync * synchronize the rediscovery with disconnection from the internal network
de4157257515400c2c25373591135f110227b68cvboxsync * by means of the pfnWaitForIdle call, so no special handling is required.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @msc
de4157257515400c2c25373591135f110227b68cvboxsync * VM2, VM1, IntNet, NetFlt, Kernel, Wire;
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * --- [label="Rediscovery conditions are not met"];
de4157257515400c2c25373591135f110227b68cvboxsync * VM1->IntNet [label="pkt0"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pkt0 to wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt [label="pkt0 to wire (dropped)"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * --- [label="Rediscovery conditions"];
de4157257515400c2c25373591135f110227b68cvboxsync * VM1->IntNet [label="pkt1"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Route packet -> wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pkt1 to wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Read pIf(==NULL) w/ spinlock"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="fRediscoveryPending=true w/ spinlock"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="ifnet_find_by_name"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="ifnet_find_by_name (success)"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * VM2->IntNet [label="pkt2", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Lock Network", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Route packet -> wire", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>IntNet [label="Unlock Network", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet=>NetFlt [label="pkt2 to wire", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="!pIf || fRediscoveryPending (w/ spinlock)", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt [label="pkt2 to wire (dropped)", linecolor="red", textcolor="red"];
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="iflt_attach"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="iflt_attach (success)"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Acquire spinlock"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Set pIf and update flags"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>NetFlt [label="Release spinlock"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt=>Kernel [label="pkt1 to wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * Kernel->Wire [label="pkt1 to wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * NetFlt<<Kernel [label="pkt1 to wire"];
de4157257515400c2c25373591135f110227b68cvboxsync * IntNet<<NetFlt [label="pkt1 to wire"];
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @endmsc
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/*******************************************************************************
de4157257515400c2c25373591135f110227b68cvboxsync* Header Files *
de4157257515400c2c25373591135f110227b68cvboxsync*******************************************************************************/
de4157257515400c2c25373591135f110227b68cvboxsync#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
de4157257515400c2c25373591135f110227b68cvboxsync#include "VBoxNetFltInternal.h"
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync#include <VBox/sup.h>
de4157257515400c2c25373591135f110227b68cvboxsync#include <VBox/log.h>
de4157257515400c2c25373591135f110227b68cvboxsync#include <VBox/err.h>
de4157257515400c2c25373591135f110227b68cvboxsync#include <iprt/assert.h>
de4157257515400c2c25373591135f110227b68cvboxsync#include <iprt/string.h>
de4157257515400c2c25373591135f110227b68cvboxsync#include <iprt/spinlock.h>
de4157257515400c2c25373591135f110227b68cvboxsync#include <iprt/uuid.h>
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#include <iprt/mem.h>
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#include <iprt/time.h>
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#include <iprt/semaphore.h>
66d43d6192fb8fbb95c01515ba64f8a1e678a863vboxsync#include <iprt/thread.h>
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/*******************************************************************************
de4157257515400c2c25373591135f110227b68cvboxsync* Defined Constants And Macros *
de4157257515400c2c25373591135f110227b68cvboxsync*******************************************************************************/
de4157257515400c2c25373591135f110227b68cvboxsync#define IFPORT_2_VBOXNETFLTINS(pIfPort) \
de4157257515400c2c25373591135f110227b68cvboxsync ( (PVBOXNETFLTINS)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETFLTINS, MyPort)) )
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncAssertCompileMemberSize(VBOXNETFLTINS, enmState, sizeof(uint32_t));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Sets the enmState member atomically.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Used for all updates.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pThis The instance.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param enmNewState The new value.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLINLINE(void) vboxNetFltSetState(PVBOXNETFLTINS pThis, VBOXNETFTLINSSTATE enmNewState)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync{
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync}
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Gets the enmState member atomically.
de4157257515400c2c25373591135f110227b68cvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Used for all reads.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns The enmState value.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pThis The instance.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLINLINE(VBOXNETFTLINSSTATE) vboxNetFltGetState(PVBOXNETFLTINS pThis)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync{
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return (VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync}
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Finds a instance by its name, the caller does the locking.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pGlobals The globals.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszName The name of the instance.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic PVBOXNETFLTINS vboxNetFltFindInstanceLocked(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pCur;
de4157257515400c2c25373591135f110227b68cvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
de4157257515400c2c25373591135f110227b68cvboxsync if (!strcmp(pszName, pCur->szName))
de4157257515400c2c25373591135f110227b68cvboxsync return pCur;
de4157257515400c2c25373591135f110227b68cvboxsync return NULL;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Finds a instance by its name, will request the mutex.
de4157257515400c2c25373591135f110227b68cvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * No reference to the instance is retained, we're assuming the caller to
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * already have one but just for some reason doesn't have the pointer to it.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pGlobals The globals.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszName The name of the instance.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncDECLHIDDEN(PVBOXNETFLTINS) vboxNetFltFindInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pRet;
de4157257515400c2c25373591135f110227b68cvboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync AssertRCReturn(rc, NULL);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync pRet = vboxNetFltFindInstanceLocked(pGlobals, pszName);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync AssertRC(rc);
de4157257515400c2c25373591135f110227b68cvboxsync return pRet;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Unlinks an instance from the chain.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @param pGlobals The globals.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pToUnlink The instance to unlink.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic void vboxNetFltUnlinkLocked(PVBOXNETFLTGLOBALS pGlobals, PVBOXNETFLTINS pToUnlink)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync if (pGlobals->pInstanceHead == pToUnlink)
de4157257515400c2c25373591135f110227b68cvboxsync pGlobals->pInstanceHead = pToUnlink->pNext;
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pCur;
de4157257515400c2c25373591135f110227b68cvboxsync for (pCur = pGlobals->pInstanceHead; pCur; pCur = pCur->pNext)
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur->pNext == pToUnlink)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pCur->pNext = pToUnlink->pNext;
de4157257515400c2c25373591135f110227b68cvboxsync break;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pCur);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync pToUnlink->pNext = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Performs interface rediscovery if it was disconnected from the host.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns true if successfully rediscovered and connected, false if not.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pThis The instance.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis)
de4157257515400c2c25373591135f110227b68cvboxsync{
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync uint64_t Now;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync bool fRediscovered;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync bool fDoIt;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Don't do rediscovery if we're called with preemption disabled.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Note! This may cause trouble if we're always called with preemption
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * disabled and vboxNetFltOsMaybeRediscovered actually does some real
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * work. For the time being though, only Darwin and FreeBSD depends
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * on these call outs and neither supports sending with preemption
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * disabled.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if (!RTThreadPreemptIsEnabled(NIL_RTTHREAD))
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return false;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Rediscovered already? Time to try again?
de4157257515400c2c25373591135f110227b68cvboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Now = RTTimeNanoTS();
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync fRediscovered = !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
de4157257515400c2c25373591135f110227b68cvboxsync fDoIt = !fRediscovered
de4157257515400c2c25373591135f110227b68cvboxsync && !ASMAtomicUoReadBool(&pThis->fRediscoveryPending)
de4157257515400c2c25373591135f110227b68cvboxsync && Now - ASMAtomicUoReadU64(&pThis->NanoTSLastRediscovery) > UINT64_C(5000000000); /* 5 sec */
de4157257515400c2c25373591135f110227b68cvboxsync if (fDoIt)
de4157257515400c2c25373591135f110227b68cvboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, true);
de4157257515400c2c25373591135f110227b68cvboxsync
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Call the OS specific code to do the job.
de4157257515400c2c25373591135f110227b68cvboxsync * Update the state when the call returns, that is everything except for
de4157257515400c2c25373591135f110227b68cvboxsync * the fDisconnectedFromHost flag which the OS specific code shall set.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (fDoIt)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync fRediscovered = vboxNetFltOsMaybeRediscovered(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!fRediscovered || !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync ASMAtomicUoWriteU64(&pThis->NanoTSLastRediscovery, RTTimeNanoTS());
de4157257515400c2c25373591135f110227b68cvboxsync ASMAtomicWriteBool(&pThis->fRediscoveryPending, false);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync if (fRediscovered)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /** @todo this isn't 100% serialized. */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync vboxNetFltPortOsSetActive(pThis, pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return fRediscovered;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnXmit
de4157257515400c2c25373591135f110227b68cvboxsync */
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncstatic DECLCALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
c69091b522190cc83264ed458a05c6b2660a167cvboxsync int rc = VINF_SUCCESS;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pSG);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Do a busy retain and then make sure we're connected to the interface
de4157257515400c2c25373591135f110227b68cvboxsync * before invoking the OS specific code.
de4157257515400c2c25373591135f110227b68cvboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if (RT_LIKELY(vboxNetFltTryRetainBusyActive(pThis)))
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync {
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync || vboxNetFltMaybeRediscovered(pThis))
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync rc = vboxNetFltPortOsXmit(pThis, pvIfData, pSG, fDst);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync vboxNetFltRelease(pThis, true /* fBusy */);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
de4157257515400c2c25373591135f110227b68cvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync int rc;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertReturn(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING, VERR_INVALID_STATE);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Go to sleep on the semaphore after checking the busy count.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRetain(pThis, false /* fBusy */);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync rc = VINF_SUCCESS;
de4157257515400c2c25373591135f110227b68cvboxsync while (pThis->cBusy && RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemEventWait(pThis->hEventIdle, cMillies); /** @todo make interruptible? */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRelease(pThis, false /* fBusy */);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @copydoc INTNETTRUNKIFPORT::pfnSetState
de4157257515400c2c25373591135f110227b68cvboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncstatic DECLCALLBACK(INTNETTRUNKIFSTATE) vboxNetFltPortSetState(PINTNETTRUNKIFPORT pIfPort, INTNETTRUNKIFSTATE enmState)
de4157257515400c2c25373591135f110227b68cvboxsync{
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync INTNETTRUNKIFSTATE enmOldTrunkState;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis->pGlobals);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, INTNETTRUNKIFSTATE_INVALID);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertReturn(enmState > INTNETTRUNKIFSTATE_INVALID && enmState < INTNETTRUNKIFSTATE_END,
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync INTNETTRUNKIFSTATE_INVALID);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Take the lock and change the state.
de4157257515400c2c25373591135f110227b68cvboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync enmOldTrunkState = pThis->enmTrunkState;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if (enmOldTrunkState != enmState)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmTrunkState, enmState);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * If the state change indicates that the trunk has become active or
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * inactive, call the OS specific part so they can work the promiscuous
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * settings and such.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Note! The caller makes sure there are no concurrent pfnSetState calls.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if ((enmOldTrunkState == INTNETTRUNKIFSTATE_ACTIVE) != (enmState == INTNETTRUNKIFSTATE_ACTIVE))
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync vboxNetFltPortOsSetActive(pThis, (enmState == INTNETTRUNKIFSTATE_ACTIVE));
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return enmOldTrunkState;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync/**
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync * @copydoc INTNETTRUNKIFPORT::pfnNotifyMacAddress
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync */
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncstatic DECLCALLBACK(void) vboxNetFltPortNotifyMacAddress(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PCRTMAC pMac)
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync{
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync /*
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync * Input validation.
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync */
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync AssertPtr(pThis);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync vboxNetFltRetain(pThis, false /* fBusy */);
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync vboxNetFltPortOsNotifyMacAddress(pThis, pvIfData, pMac);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync vboxNetFltRelease(pThis, false /* fBusy */);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync/**
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync * @copydoc INTNETTRUNKIFPORT::pfnConnectInterface
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync */
f0626cddb8f2999ecf9a69b4778f163c767c1c66vboxsyncstatic DECLCALLBACK(int) vboxNetFltPortConnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIf, void **ppvIfData)
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync{
a91aecdafa378380347ffab1e48b428b7ec37747vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
a91aecdafa378380347ffab1e48b428b7ec37747vboxsync int rc;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync /*
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync * Input validation.
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync */
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync AssertPtr(pThis);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync vboxNetFltRetain(pThis, false /* fBusy */);
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync rc = vboxNetFltPortOsConnectInterface(pThis, pvIf, ppvIfData);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync vboxNetFltRelease(pThis, false /* fBusy */);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync return rc;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync/**
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectInterface
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync */
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncstatic DECLCALLBACK(void) vboxNetFltPortDisconnectInterface(PINTNETTRUNKIFPORT pIfPort, void *pvIfData)
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync{
a91aecdafa378380347ffab1e48b428b7ec37747vboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
a91aecdafa378380347ffab1e48b428b7ec37747vboxsync int rc;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync /*
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync * Input validation.
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync */
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync AssertPtr(pThis);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync vboxNetFltRetain(pThis, false /* fBusy */);
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync rc = vboxNetFltPortOsDisconnectInterface(pThis, pvIfData);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync vboxNetFltRelease(pThis, false /* fBusy */);
a91aecdafa378380347ffab1e48b428b7ec37747vboxsync AssertRC(rc); /** @todo fix vboxNetFltPortOsDisconnectInterface. */
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
de4157257515400c2c25373591135f110227b68cvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Serious paranoia.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis->pGlobals);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->szName[0]);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fRediscoveryPending);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->cBusy);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Disconnect and release it.
de4157257515400c2c25373591135f110227b68cvboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltOsDisconnectIt(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync pThis->pSwitchPort = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Unconnected);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync#endif
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRelease(pThis, false /* fBusy */);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Destroy a device that has been disconnected from the switch.
de4157257515400c2c25373591135f110227b68cvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns true if the instance is destroyed, false otherwise.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pThis The instance to be destroyed. This is
de4157257515400c2c25373591135f110227b68cvboxsync * no longer valid when this function returns.
de4157257515400c2c25373591135f110227b68cvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncstatic bool vboxNetFltDestroyInstance(PVBOXNETFLTINS pThis)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTGLOBALS pGlobals = pThis->pGlobals;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync uint32_t cRefs = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->cRefs);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync int rc;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync LogFlow(("vboxNetFltDestroyInstance: pThis=%p (%s)\n", pThis, pThis->szName));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Validate the state.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
de4157257515400c2c25373591135f110227b68cvboxsync Assert( vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting
de4157257515400c2c25373591135f110227b68cvboxsync || vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected);
de4157257515400c2c25373591135f110227b68cvboxsync#else
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting);
de4157257515400c2c25373591135f110227b68cvboxsync#endif
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fRediscoveryPending);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->cRefs);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->cBusy);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->pSwitchPort);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Make sure the state is 'disconnecting' / 'destroying' and let the OS
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * specific code do its part of the cleanup outside the mutex.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx); AssertRC(rc);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltOsDeleteInstance(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Unlink the instance and free up its resources.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx); AssertRC(rc);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Destroyed);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltUnlinkLocked(pGlobals, pThis);
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync RTSemEventDestroy(pThis->hEventIdle);
de4157257515400c2c25373591135f110227b68cvboxsync pThis->hEventIdle = NIL_RTSEMEVENT;
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockDestroy(pThis->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync pThis->hSpinlock = NIL_RTSPINLOCK;
de4157257515400c2c25373591135f110227b68cvboxsync RTMemFree(pThis);
eeb6c0c9cd7482b990f5b20f9b7c867e501dd392vboxsync
eeb6c0c9cd7482b990f5b20f9b7c867e501dd392vboxsync NOREF(cRefs);
eeb6c0c9cd7482b990f5b20f9b7c867e501dd392vboxsync
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync return true;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Releases a reference to the specified instance.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * This method will destroy the instance when the count reaches 0.
de4157257515400c2c25373591135f110227b68cvboxsync * It will also take care of decrementing the counter and idle wakeup.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @param pThis The instance.
de4157257515400c2c25373591135f110227b68cvboxsync * @param fBusy Whether the busy counter should be decremented too.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncDECLHIDDEN(void) vboxNetFltRelease(PVBOXNETFLTINS pThis, bool fBusy)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync uint32_t cRefs;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Paranoid Android.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
de4157257515400c2c25373591135f110227b68cvboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis->pGlobals);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->szName[0]);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Work the busy counter.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (fBusy)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync cRefs = ASMAtomicDecU32(&pThis->cBusy);
de4157257515400c2c25373591135f110227b68cvboxsync if (!cRefs)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync int rc = RTSemEventSignal(pThis->hEventIdle);
de4157257515400c2c25373591135f110227b68cvboxsync AssertRC(rc);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync Assert(cRefs < UINT32_MAX / 2);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * The object reference counting.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync cRefs = ASMAtomicDecU32(&pThis->cRefs);
de4157257515400c2c25373591135f110227b68cvboxsync if (!cRefs)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltDestroyInstance(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync Assert(cRefs < UINT32_MAX / 2);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync * @copydoc INTNETTRUNKIFPORT::pfnRelease
de4157257515400c2c25373591135f110227b68cvboxsync */
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsyncstatic DECLCALLBACK(void) vboxNetFltPortRelease(PINTNETTRUNKIFPORT pIfPort)
40295ab70cb24d4b45580b9e03766935cca282abvboxsync{
40295ab70cb24d4b45580b9e03766935cca282abvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync vboxNetFltRelease(pThis, false /* fBusy */);
40295ab70cb24d4b45580b9e03766935cca282abvboxsync}
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync/**
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync * @callback_method_impl{FNINTNETTRUNKIFPORTRELEASEBUSY}
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync */
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsyncDECLHIDDEN(DECLCALLBACK(void)) vboxNetFltPortReleaseBusy(PINTNETTRUNKIFPORT pIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
ae609731a9638dcf6d6fca8225bf7b1e46e997devboxsync vboxNetFltRelease(pThis, true /*fBusy*/);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Retains a reference to the specified instance and a busy reference too.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @param pThis The instance.
de4157257515400c2c25373591135f110227b68cvboxsync * @param fBusy Whether the busy counter should be incremented as well.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncDECLHIDDEN(void) vboxNetFltRetain(PVBOXNETFLTINS pThis, bool fBusy)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync uint32_t cRefs;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Paranoid Android.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
de4157257515400c2c25373591135f110227b68cvboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis->pGlobals);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->szName[0]);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Retain the object.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync cRefs = ASMAtomicIncU32(&pThis->cRefs);
479cb78f51993b710c1403ac9d21a30b53cd7693vboxsync Assert(cRefs > 1 && cRefs < UINT32_MAX / 2);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Work the busy counter.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (fBusy)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync cRefs = ASMAtomicIncU32(&pThis->cBusy);
ddf5c3bc368adfbecd8cc147963fe94d49e6e68dvboxsync Assert(cRefs > 0 && cRefs < UINT32_MAX / 2);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync NOREF(cRefs);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync/**
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Tries to retain the device as busy if the trunk is active.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * This is used before calling pfnRecv or pfnPreRecv.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @returns true if we succeeded in retaining a busy reference to the active
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * device. false if we failed.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param pThis The instance.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncDECLHIDDEN(bool) vboxNetFltTryRetainBusyActive(PVBOXNETFLTINS pThis)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync{
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync uint32_t cRefs;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync bool fRc;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Paranoid Android.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertPtr(pThis);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertPtr(pThis->pGlobals);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->szName[0]);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Do the retaining and checking behind the spinlock.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync fRc = pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if (fRc)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync {
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync cRefs = ASMAtomicIncU32(&pThis->cRefs);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertMsg(cRefs > 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync cRefs = ASMAtomicIncU32(&pThis->cBusy);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertMsg(cRefs >= 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return fRc;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync}
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync/**
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Tries to retain the device as busy if the trunk is not disconnecting.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * This is used before reporting stuff to the internal network.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @returns true if we succeeded in retaining a busy reference to the active
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * device. false if we failed.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param pThis The instance.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncDECLHIDDEN(bool) vboxNetFltTryRetainBusyNotDisconnected(PVBOXNETFLTINS pThis)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync{
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync uint32_t cRefs;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync bool fRc;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Paranoid Android.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertPtr(pThis);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertPtr(pThis->pGlobals);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->szName[0]);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Do the retaining and checking behind the spinlock.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync fRc = pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync || pThis->enmTrunkState == INTNETTRUNKIFSTATE_INACTIVE;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync if (fRc)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync {
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync cRefs = ASMAtomicIncU32(&pThis->cRefs);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertMsg(cRefs > 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync cRefs = ASMAtomicIncU32(&pThis->cBusy);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertMsg(cRefs >= 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return fRc;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync}
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
de4157257515400c2c25373591135f110227b68cvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(void) vboxNetFltPortRetain(PINTNETTRUNKIFPORT pIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRetain(pThis, false /* fBusy */);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Connects the instance to the specified switch port.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * Called while owning the lock. We're ASSUMING that the internal
de4157257515400c2c25373591135f110227b68cvboxsync * networking code is already owning an recursive mutex, so, there
de4157257515400c2c25373591135f110227b68cvboxsync * will be no deadlocks when vboxNetFltOsConnectIt calls back into
de4157257515400c2c25373591135f110227b68cvboxsync * it for setting preferences.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pThis The instance.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pSwitchPort The port on the internal network 'switch'.
de4157257515400c2c25373591135f110227b68cvboxsync * @param ppIfPort Where to return our port interface.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync int rc;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Validate state.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fRediscoveryPending);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->cBusy);
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected);
de4157257515400c2c25373591135f110227b68cvboxsync#else
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Initializing);
de4157257515400c2c25373591135f110227b68cvboxsync#endif
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_INACTIVE);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Do the job.
de4157257515400c2c25373591135f110227b68cvboxsync * Note that we're calling the os stuff while owning the semaphore here.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync pThis->pSwitchPort = pSwitchPort;
de4157257515400c2c25373591135f110227b68cvboxsync rc = vboxNetFltOsConnectIt(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Connected);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *ppIfPort = &pThis->MyPort;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync pThis->pSwitchPort = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_INACTIVE);
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Creates a new instance.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * The new instance will be in the suspended state in a dynamic config and in
de4157257515400c2c25373591135f110227b68cvboxsync * the inactive in a static one.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * Called without owning the lock, but will request is several times.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pGlobals The globals.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszName The instance name.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pSwitchPort The port on the switch that we're connected with (dynamic only).
c0fa9ee5c9cb7a79ac0f20d8009f75148bd9195fvboxsync * @param fNoPromisc Do not attempt going into promiscuous mode.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pvContext Context argument for vboxNetFltOsInitInstance.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param ppIfPort Where to store the pointer to our port interface (dynamic only).
de4157257515400c2c25373591135f110227b68cvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncstatic int vboxNetFltNewInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PINTNETTRUNKSWPORT pSwitchPort,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync bool fNoPromisc, void *pvContext, PINTNETTRUNKIFPORT *ppIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Allocate and initialize a new instance before requesting the mutex.
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync * Note! That in a static config we'll initialize the trunk state to
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync * disconnecting and flip it in vboxNetFltFactoryCreateAndConnect
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync * later on. This better reflext the state and it works better with
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync * assertions in the destruction path.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync int rc;
de4157257515400c2c25373591135f110227b68cvboxsync size_t const cchName = strlen(pszName);
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pNew = (PVBOXNETFLTINS)RTMemAllocZ(RT_OFFSETOF(VBOXNETFLTINS, szName[cchName + 1]));
de4157257515400c2c25373591135f110227b68cvboxsync if (!pNew)
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_INTNET_FLT_IF_FAILED;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->pNext = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->MyPort.u32Version = INTNETTRUNKIFPORT_VERSION;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnRetain = vboxNetFltPortRetain;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnRelease = vboxNetFltPortRelease;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnDisconnectAndRelease= vboxNetFltPortDisconnectAndRelease;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pNew->MyPort.pfnSetState = vboxNetFltPortSetState;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnWaitForIdle = vboxNetFltPortWaitForIdle;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnXmit = vboxNetFltPortXmit;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync pNew->MyPort.pfnNotifyMacAddress = vboxNetFltPortNotifyMacAddress;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync pNew->MyPort.pfnConnectInterface = vboxNetFltPortConnectInterface;
a91aecdafa378380347ffab1e48b428b7ec37747vboxsync pNew->MyPort.pfnDisconnectInterface = vboxNetFltPortDisconnectInterface;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION;
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync pNew->pSwitchPort = pSwitchPort;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->pGlobals = pGlobals;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->hSpinlock = NIL_RTSPINLOCK;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->enmState = kVBoxNetFltInsState_Initializing;
ed7bd9b2b73443bae6056c0d631f7914024697c1vboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
ed7bd9b2b73443bae6056c0d631f7914024697c1vboxsync pNew->enmTrunkState = INTNETTRUNKIFSTATE_DISCONNECTING;
ed7bd9b2b73443bae6056c0d631f7914024697c1vboxsync#else
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pNew->enmTrunkState = INTNETTRUNKIFSTATE_INACTIVE;
ed7bd9b2b73443bae6056c0d631f7914024697c1vboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync pNew->fDisconnectedFromHost = false;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->fRediscoveryPending = false;
c0fa9ee5c9cb7a79ac0f20d8009f75148bd9195fvboxsync pNew->fDisablePromiscuous = fNoPromisc;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->NanoTSLastRediscovery = INT64_MAX;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->cRefs = 1;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->cBusy = 0;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->hEventIdle = NIL_RTSEMEVENT;
de4157257515400c2c25373591135f110227b68cvboxsync memcpy(pNew->szName, pszName, cchName + 1);
de4157257515400c2c25373591135f110227b68cvboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rc = RTSpinlockCreate(&pNew->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxNetFltNewInstance");
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemEventCreate(&pNew->hEventIdle);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync rc = vboxNetFltOsPreInitInstance(pNew);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Insert the instance into the chain, checking for
de4157257515400c2c25373591135f110227b68cvboxsync * duplicates first of course (race).
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync if (!vboxNetFltFindInstanceLocked(pGlobals, pszName))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pNew->pNext = pGlobals->pInstanceHead;
de4157257515400c2c25373591135f110227b68cvboxsync pGlobals->pInstanceHead = pNew;
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Call the OS specific initialization code.
de4157257515400c2c25373591135f110227b68cvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = vboxNetFltOsInitInstance(pNew, pvContext);
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRequest(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Static instances are unconnected at birth.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync Assert(!pSwitchPort);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pNew->enmState = kVBoxNetFltInsState_Unconnected;
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *ppIfPort = &pNew->MyPort;
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#else /* !VBOXNETFLT_STATIC_CONFIG */
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Connect it as well, the OS specific bits has to be done outside
de4157257515400c2c25373591135f110227b68cvboxsync * the lock as they may call back to into intnet.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync rc = vboxNetFltConnectIt(pNew, pSwitchPort, ppIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync Assert(*ppIfPort == &pNew->MyPort);
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /* Bail out (failed). */
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltOsDeleteInstance(pNew);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#endif /* !VBOXNETFLT_STATIC_CONFIG */
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltUnlinkLocked(pGlobals, pNew);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync rc = VERR_INTNET_FLT_IF_BUSY;
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync RTSemEventDestroy(pNew->hEventIdle);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockDestroy(pNew->hSpinlock);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync RTMemFree(pNew);
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Searches for the NetFlt instance by its name and creates the new one if not found.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns VBox status code.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @retval VINF_SUCCESS and *ppInstance if a new instance was created.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @retval VINF_ALREADY_INITIALIZED and *ppInstance if an instance already exists.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pGlobal Pointer to the globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pszName The instance name.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param ppInstance Where to return the instance pointer on success.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pvContext Context which needs to be passed along to vboxNetFltOsInitInstance.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLHIDDEN(int) vboxNetFltSearchCreateInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName, PVBOXNETFLTINS *ppInstance, void *pvContext)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync{
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync PINTNETTRUNKIFPORT pIfPort;
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync PVBOXNETFLTINS pCur;
66d43d6192fb8fbb95c01515ba64f8a1e678a863vboxsync VBOXNETFTLINSSTATE enmState;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync int rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync *ppInstance = NULL;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync AssertRCReturn(rc, rc);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Look for an existing instance in the list.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * There might be an existing one in the list if the driver was unbound
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * while it was connected to an internal network. We're running into
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * a destruction race that is a bit similar to the one in
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * vboxNetFltFactoryCreateAndConnect, only the roles are reversed
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * and we're not in a position to back down. Instead of backing down
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * we'll delay a bit giving the other thread time to complete the
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * destructor.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync while (pCur)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync {
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync if (cRefs > 1)
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync {
66d43d6192fb8fbb95c01515ba64f8a1e678a863vboxsync enmState = vboxNetFltGetState(pCur);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync switch (enmState)
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync {
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync case kVBoxNetFltInsState_Unconnected:
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync case kVBoxNetFltInsState_Connected:
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync case kVBoxNetFltInsState_Disconnecting:
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync if (pCur->fDisconnectedFromHost)
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync {
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync /* Wait for it to exit the transitional disconnecting
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync state. It might otherwise be running the risk of
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync upsetting the OS specific code... */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync /** @todo This reconnect stuff should be serialized correctly for static
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * devices. Shouldn't it? In the dynamic case we're using the INTNET
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * outbound thunk lock, but that doesn't quite cut it here, or does
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync * it? We could either transition to initializing or make a callback
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * while owning the mutex here... */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync if (enmState == kVBoxNetFltInsState_Disconnecting)
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync {
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync do
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync {
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTThreadSleep(2); /* (2ms) */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTSemFastMutexRequest(pGlobals->hFastMtx);
afbe73d7167a3fec14b3762e4521ebdb51de8cafvboxsync enmState = vboxNetFltGetState(pCur);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync }
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync while (enmState == kVBoxNetFltInsState_Disconnecting);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync AssertMsg(enmState == kVBoxNetFltInsState_Unconnected, ("%d\n", enmState));
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync Assert(pCur->fDisconnectedFromHost);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync }
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync *ppInstance = pCur;
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync return VINF_ALREADY_INITIALIZED;
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync }
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync /* fall thru */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync default:
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync {
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync bool fDfH = pCur->fDisconnectedFromHost;
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync vboxNetFltRelease(pCur, false /* fBusy */);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync LogRel(("VBoxNetFlt: Huh? An instance of '%s' already exists! [pCur=%p cRefs=%d fDfH=%RTbool enmState=%d]\n",
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync pszName, pCur, cRefs - 1, fDfH, enmState));
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync *ppInstance = NULL;
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync return VERR_INTNET_FLT_IF_BUSY;
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync }
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync }
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync }
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync /* Zero references, it's being destroyed. Delay a bit so the destructor
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync can finish its work and try again. (vboxNetFltNewInstance will fail
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync with duplicate name if we don't.) */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync# ifdef RT_STRICT
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync Assert(cRefs == 1);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync enmState = vboxNetFltGetState(pCur);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync AssertMsg( enmState == kVBoxNetFltInsState_Unconnected
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync || enmState == kVBoxNetFltInsState_Disconnecting
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync || enmState == kVBoxNetFltInsState_Destroyed, ("%d\n", enmState));
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync# endif
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync ASMAtomicDecU32(&pCur->cRefs);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync RTThreadSleep(2); /* (2ms) */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync AssertRCReturn(rc, rc);
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /* try again */
4b4470be4f81cfa22b509a93e4381055e89f35b7vboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync }
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Try create a new instance.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * (fNoPromisc is overridden in the vboxNetFltFactoryCreateAndConnect path, so pass true here.)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = vboxNetFltNewInstance(pGlobals, pszName, NULL, true /* fNoPromisc */, pvContext, &pIfPort);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (RT_SUCCESS(rc))
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *ppInstance = IFPORT_2_VBOXNETFLTINS(pIfPort);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync else
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync *ppInstance = NULL;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync return rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync}
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#endif /* VBOXNETFLT_STATIC_CONFIG */
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic DECLCALLBACK(int) vboxNetFltFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync PINTNETTRUNKIFPORT *ppIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pCur;
de4157257515400c2c25373591135f110227b68cvboxsync int rc;
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pGlobals->cFactoryRefs > 0);
b696ef4184e5e590a2d74cc3b828d2ddb81aa2b2vboxsync AssertMsgReturn(!(fFlags & ~(INTNETTRUNKFACTORY_FLAG_NO_PROMISC)),
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Static: Find instance, check if busy, connect if not.
de4157257515400c2c25373591135f110227b68cvboxsync * Dynamic: Check for duplicate / busy interface instance.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync AssertRCReturn(rc, rc);
de4157257515400c2c25373591135f110227b68cvboxsync
fb080140fb48add63b366df7518d65b53c84c575vboxsync//#if defined(VBOXNETADP) && defined(RT_OS_WINDOWS)
f90275e092bca642e8b653493764af5ed2580d22vboxsync// /* temporary hack to pick up the first adapter */
f90275e092bca642e8b653493764af5ed2580d22vboxsync// pCur = pGlobals->pInstanceHead; /** @todo Don't for get to remove this temporary hack... :-) */
f90275e092bca642e8b653493764af5ed2580d22vboxsync//#else
de4157257515400c2c25373591135f110227b68cvboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
f90275e092bca642e8b653493764af5ed2580d22vboxsync//#endif
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /* Try grab a reference. If the count had already reached zero we're racing the
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync destructor code and must back down. */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (cRefs > 1)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (vboxNetFltGetState(pCur) == kVBoxNetFltInsState_Unconnected)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync pCur->enmTrunkState = INTNETTRUNKIFSTATE_INACTIVE; /** @todo protect me? */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pCur->fDisablePromiscuous = !!(fFlags & INTNETTRUNKFACTORY_FLAG_NO_PROMISC);
5b08599c7216b1a16011b2bbfe0b5a8acb58268evboxsync rc = vboxNetFltConnectIt(pCur, pSwitchPort, ppIfPort);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (RT_SUCCESS(rc))
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pCur = NULL; /* Don't release it, reference given to the caller. */
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync else
3dfa02954e51e2ae86a33cea78a146e45b5247b3vboxsync pCur->enmTrunkState = INTNETTRUNKIFSTATE_DISCONNECTING;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync else
5b08599c7216b1a16011b2bbfe0b5a8acb58268evboxsync rc = VERR_INTNET_FLT_IF_BUSY;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync else
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync Assert(cRefs == 1);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync ASMAtomicDecU32(&pCur->cRefs);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pCur = NULL; /* nothing to release */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = VERR_INTNET_FLT_IF_NOT_FOUND;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (pCur)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltRelease(pCur, false /* fBusy */);
5b08599c7216b1a16011b2bbfe0b5a8acb58268evboxsync#else
5b08599c7216b1a16011b2bbfe0b5a8acb58268evboxsync rc = VERR_INTNET_FLT_IF_BUSY;
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: returns %Rrc\n", rc));
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
de4157257515400c2c25373591135f110227b68cvboxsync rc = VERR_INTNET_FLT_IF_NOT_FOUND;
de4157257515400c2c25373591135f110227b68cvboxsync#else
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Dynamically create a new instance.
de4157257515400c2c25373591135f110227b68cvboxsync */
ba7ca7ddfe51f0587b631a73ca9dd27d5e63f830vboxsync rc = vboxNetFltNewInstance(pGlobals,
ba7ca7ddfe51f0587b631a73ca9dd27d5e63f830vboxsync pszName,
ba7ca7ddfe51f0587b631a73ca9dd27d5e63f830vboxsync pSwitchPort,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync !!(fFlags & INTNETTRUNKFACTORY_FLAG_NO_PROMISC),
ba7ca7ddfe51f0587b631a73ca9dd27d5e63f830vboxsync NULL,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync ppIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync LogFlow(("vboxNetFltFactoryCreateAndConnect: returns %Rrc\n", rc));
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync * @copydoc INTNETTRUNKFACTORY::pfnRelease
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic DECLCALLBACK(void) vboxNetFltFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, TrunkFactory));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(cRefs >= 0); NOREF(cRefs);
de4157257515400c2c25373591135f110227b68cvboxsync LogFlow(("vboxNetFltFactoryRelease: cRefs=%d (new)\n", cRefs));
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Implements the SUPDRV component factor interface query method.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns Pointer to an interface. NULL if not supported.
de4157257515400c2c25373591135f110227b68cvboxsync *
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @param pSupDrvFactory Pointer to the component factory registration structure.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pSession The session - unused.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszInterfaceUuid The factory interface id.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic DECLCALLBACK(void *) vboxNetFltQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTGLOBALS pGlobals = (PVBOXNETFLTGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETFLTGLOBALS, SupDrvFactory));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Convert the UUID strings and compare them.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync RTUUID UuidReq;
de4157257515400c2c25373591135f110227b68cvboxsync int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync ASMAtomicIncS32(&pGlobals->cFactoryRefs);
de4157257515400c2c25373591135f110227b68cvboxsync return &pGlobals->TrunkFactory;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef LOG_ENABLED
de4157257515400c2c25373591135f110227b68cvboxsync /* log legacy queries */
de4157257515400c2c25373591135f110227b68cvboxsync /* else if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_V1_UUID_STR))
de4157257515400c2c25373591135f110227b68cvboxsync Log(("VBoxNetFlt: V1 factory query\n"));
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync Log(("VBoxNetFlt: unknown factory interface query (%s)\n", pszInterfaceUuid));
de4157257515400c2c25373591135f110227b68cvboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync Log(("VBoxNetFlt: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return NULL;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Checks whether the VBoxNetFlt wossname can be unloaded.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * This will return false if someone is currently using the module.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns true if it's relatively safe to unload it, otherwise false.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pGlobals Pointer to the globals.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncDECLHIDDEN(bool) vboxNetFltCanUnload(PVBOXNETFLTGLOBALS pGlobals)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync bool fRc = !pGlobals->pInstanceHead
de4157257515400c2c25373591135f110227b68cvboxsync && pGlobals->cFactoryRefs <= 0;
de4157257515400c2c25373591135f110227b68cvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync AssertRC(rc);
de4157257515400c2c25373591135f110227b68cvboxsync return fRc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
fe1fcdb5f9f7e9d3217c17077f7dc284be86a87fvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Try to close the IDC connection to SUPDRV if established.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns VBox status code.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @retval VINF_SUCCESS on success.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @retval VERR_WRONG_ORDER if we're busy.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pGlobals Pointer to the globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @sa vboxNetFltTryDeleteIdcAndGlobals()
fe1fcdb5f9f7e9d3217c17077f7dc284be86a87fvboxsync */
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsyncDECLHIDDEN(int) vboxNetFltTryDeleteIdc(PVBOXNETFLTGLOBALS pGlobals)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync int rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Check before trying to deregister the factory.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (!vboxNetFltCanUnload(pGlobals))
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_WRONG_ORDER;
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (!pGlobals->fIDCOpen)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = VINF_SUCCESS;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Disconnect from SUPDRV and check that nobody raced us,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * reconnect if that should happen.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
de4157257515400c2c25373591135f110227b68cvboxsync AssertRC(rc);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (!vboxNetFltCanUnload(pGlobals))
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync AssertRC(rc);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return VERR_WRONG_ORDER;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync SUPR0IdcClose(&pGlobals->SupDrvIDC);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pGlobals->fIDCOpen = false;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync return rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync}
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
fe1fcdb5f9f7e9d3217c17077f7dc284be86a87fvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Establishes the IDC connection to SUPDRV and registers our component factory.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns VBox status code.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pGlobals Pointer to the globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @sa vboxNetFltInitGlobalsAndIdc().
fe1fcdb5f9f7e9d3217c17077f7dc284be86a87fvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLHIDDEN(int) vboxNetFltInitIdc(PVBOXNETFLTGLOBALS pGlobals)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync{
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync int rc;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync Assert(!pGlobals->fIDCOpen);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Establish a connection to SUPDRV and register our component factory.
de4157257515400c2c25373591135f110227b68cvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (RT_SUCCESS(rc))
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (RT_SUCCESS(rc))
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pGlobals->fIDCOpen = true;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync Log(("VBoxNetFlt: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return rc;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /* bail out. */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync LogRel(("VBoxNetFlt: Failed to register component factory, rc=%Rrc\n", rc));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync SUPR0IdcClose(&pGlobals->SupDrvIDC);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Deletes the globals.
de4157257515400c2c25373591135f110227b68cvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * This must be called after the IDC connection has been closed,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * see vboxNetFltTryDeleteIdc().
de4157257515400c2c25373591135f110227b68cvboxsync *
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * @param pGlobals Pointer to the globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @sa vboxNetFltTryDeleteIdcAndGlobals()
de4157257515400c2c25373591135f110227b68cvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLHIDDEN(void) vboxNetFltDeleteGlobals(PVBOXNETFLTGLOBALS pGlobals)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync{
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync Assert(!pGlobals->fIDCOpen);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Release resources.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync RTSemFastMutexDestroy(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync}
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Initializes the globals.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * @returns VBox status code.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pGlobals Pointer to the globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @sa vboxNetFltInitGlobalsAndIdc().
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLHIDDEN(int) vboxNetFltInitGlobals(PVBOXNETFLTGLOBALS pGlobals)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Initialize the common portions of the structure.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
de4157257515400c2c25373591135f110227b68cvboxsync if (RT_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
47a160d35dbc42c8c817c9b48be21dca11d329d6vboxsync pGlobals->pInstanceHead = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync
47a160d35dbc42c8c817c9b48be21dca11d329d6vboxsync pGlobals->TrunkFactory.pfnRelease = vboxNetFltFactoryRelease;
47a160d35dbc42c8c817c9b48be21dca11d329d6vboxsync pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetFltFactoryCreateAndConnect;
fb080140fb48add63b366df7518d65b53c84c575vboxsync#if defined(RT_OS_WINDOWS) && defined(VBOXNETADP)
097c8f9d75c4ccae68489be899a1865771be9009vboxsync memcpy(pGlobals->SupDrvFactory.szName, "VBoxNetAdp", sizeof("VBoxNetAdp"));
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#else
097c8f9d75c4ccae68489be899a1865771be9009vboxsync memcpy(pGlobals->SupDrvFactory.szName, "VBoxNetFlt", sizeof("VBoxNetFlt"));
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#endif
47a160d35dbc42c8c817c9b48be21dca11d329d6vboxsync pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetFltQueryFactoryInterface;
47a160d35dbc42c8c817c9b48be21dca11d329d6vboxsync pGlobals->fIDCOpen = false;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync
47a160d35dbc42c8c817c9b48be21dca11d329d6vboxsync return rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync }
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync return rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Called by the native part when the OS wants the driver to unload.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns VINF_SUCCESS on success, VERR_WRONG_ORDER if we're busy.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pGlobals Pointer to the globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLHIDDEN(int) vboxNetFltTryDeleteIdcAndGlobals(PVBOXNETFLTGLOBALS pGlobals)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync{
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync int rc = vboxNetFltTryDeleteIdc(pGlobals);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync if (RT_SUCCESS(rc))
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltDeleteGlobals(pGlobals);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync return rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync/**
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * Called by the native driver/kext module initialization routine.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * It will initialize the common parts of the globals, assuming the caller
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * has already taken care of the OS specific bits, and establish the IDC
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * connection to SUPDRV.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * @returns VBox status code.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * @param pGlobals Pointer to the globals.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncDECLHIDDEN(int) vboxNetFltInitGlobalsAndIdc(PVBOXNETFLTGLOBALS pGlobals)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync{
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync /*
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync * Initialize the common portions of the structure.
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync int rc = vboxNetFltInitGlobals(pGlobals);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync if (RT_SUCCESS(rc))
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync {
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync rc = vboxNetFltInitIdc(pGlobals);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync if (RT_SUCCESS(rc))
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync return rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync /* bail out. */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltDeleteGlobals(pGlobals);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync