VBoxNetFlt.c revision ccc948c886b751603889a67909fbd4a5fcaeac85
de4157257515400c2c25373591135f110227b68cvboxsync/* $Id$ */
de4157257515400c2c25373591135f110227b68cvboxsync/** @file
de4157257515400c2c25373591135f110227b68cvboxsync * VBoxNetFlt - Network Filter Driver (Host), Common Code.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/*
de4157257515400c2c25373591135f110227b68cvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
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.
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync *
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * additional information or have any questions.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/** @page pg_netflt VBoxNetFlt - Network Interface Filter
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * This is a kernel module that attaches to a real interface on the host
de4157257515400c2c25373591135f110227b68cvboxsync * and 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 *
de4157257515400c2c25373591135f110227b68cvboxsync * @section sec_netflt_msc Locking / Sequence Diagrams
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
de4157257515400c2c25373591135f110227b68cvboxsync * deadlocks caused by mixing our locks with the ones in the host kernel.
de4157257515400c2c25373591135f110227b68cvboxsync * The main events are receive, send, async send completion, disappearance of
de4157257515400c2c25373591135f110227b68cvboxsync * the host networking interface and it's reappearance. The latter two events
de4157257515400c2c25373591135f110227b68cvboxsync * are 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 *
de4157257515400c2c25373591135f110227b68cvboxsync * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release
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 *
de4157257515400c2c25373591135f110227b68cvboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Removal
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 *
de4157257515400c2c25373591135f110227b68cvboxsync * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery
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>
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{
de4157257515400c2c25373591135f110227b68cvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
de4157257515400c2c25373591135f110227b68cvboxsync uint64_t Now = RTTimeNanoTS();
de4157257515400c2c25373591135f110227b68cvboxsync bool fRediscovered;
de4157257515400c2c25373591135f110227b68cvboxsync bool fDoIt;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Rediscovered already? Time to try again?
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
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
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
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)
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltPortOsSetActive(pThis, pThis->fActive);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return fRediscovered;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
13ef4f36ce232d17f4738ffbc4ac21909898cc23vboxsync#ifdef RT_WITH_W64_UNWIND_HACK
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# if defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64)
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# define NETFLT_DECL_CALLBACK(type) DECLASM(DECLHIDDEN(type))
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# define NETFLT_CALLBACK(_n) netfltNtWrap##_n
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortXmit)(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous)(PINTNETTRUNKIFPORT pIfPort);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortGetMacAddress)(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsHostMac)(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortWaitForIdle)(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortSetActive)(PINTNETTRUNKIFPORT pIfPort, bool fActive);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease)(PINTNETTRUNKIFPORT pIfPort);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRetain)(PINTNETTRUNKIFPORT pIfPort);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRelease)(PINTNETTRUNKIFPORT pIfPort);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# else
13ef4f36ce232d17f4738ffbc4ac21909898cc23vboxsync# error "UNSUPPORTED (RT_WITH_W64_UNWIND_HACK)"
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# endif
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync#else
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# define NETFLT_DECL_CALLBACK(type) static DECLCALLBACK(type)
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync# define NETFLT_CALLBACK(_n) _n
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnXmit
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, 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 Assert(pThis->fActive);
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 */
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRetain(pThis, true /* fBusy */);
de4157257515400c2c25373591135f110227b68cvboxsync if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)
de4157257515400c2c25373591135f110227b68cvboxsync || vboxNetFltMaybeRediscovered(pThis))
de4157257515400c2c25373591135f110227b68cvboxsync rc = vboxNetFltPortOsXmit(pThis, pSG, fDst);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRelease(pThis, true /* fBusy */);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsPromiscuous
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsPromiscuous(PINTNETTRUNKIFPORT pIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->fActive);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Ask the OS specific code.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync return vboxNetFltPortOsIsPromiscuous(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->fActive);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Forward the question to the OS specific code.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltPortOsGetMacAddress(pThis, pMac);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnIsHostMac
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsHostMac(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->fActive);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Ask the OS specific code.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync return vboxNetFltPortOsIsHostMac(pThis, pMac);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(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);
de4157257515400c2c25373591135f110227b68cvboxsync AssertReturn(!pThis->fActive, 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/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnSetActive
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(bool) vboxNetFltPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Input validation.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync AssertPtr(pThis->pGlobals);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
de4157257515400c2c25373591135f110227b68cvboxsync AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, false);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * We're assuming that the caller is serializing the calls, so we don't
de4157257515400c2c25373591135f110227b68cvboxsync * have to be extremely careful here. Just update first and then call
de4157257515400c2c25373591135f110227b68cvboxsync * the OS specific code, the update must be serialized for various reasons.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (ASMAtomicReadBool(&pThis->fActive) != fActive)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
de4157257515400c2c25373591135f110227b68cvboxsync ASMAtomicWriteBool(&pThis->fActive, fActive);
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltPortOsSetActive(pThis, fActive);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync fActive = !fActive;
de4157257515400c2c25373591135f110227b68cvboxsync return !fActive;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
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);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fActive);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fRediscoveryPending);
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->cBusy);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Disconnect and release it.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
de4157257515400c2c25373591135f110227b68cvboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltOsDisconnectIt(pThis);
de4157257515400c2c25373591135f110227b68cvboxsync pThis->pSwitchPort = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Unconnected);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
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
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fActive);
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#ifdef VBOXNETFLT_STATIC_CONFIG
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync/** @todo r=bird: This looks kind of insane! I ASSUME this is specific to the
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * static config and to devices in the Unconnected state only. This *looks* like
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * a very unhealthy race between driver unloading and vboxNetFltFactoryCreateAndConnect.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * If I'm right, then vboxNetFltFactoryCreateAndConnect should be made to back down one
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * way or the other, it should not the other way around. (see suggestion further down)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * If I'm wrong, then please explain in full.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (cRefs != 0)
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync {
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync Assert(cRefs < UINT32_MAX / 2);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync return false;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync }
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Destroying);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#else
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#endif
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);
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/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(void) vboxNetFltPortRelease(PINTNETTRUNKIFPORT pIfPort)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort);
de4157257515400c2c25373591135f110227b68cvboxsync vboxNetFltRelease(pThis, false /* 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
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
de4157257515400c2c25373591135f110227b68cvboxsync */
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsyncNETFLT_DECL_CALLBACK(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->fActive);
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
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
de4157257515400c2c25373591135f110227b68cvboxsync Assert(!pThis->fActive);
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.
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;
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnRetain = NETFLT_CALLBACK(vboxNetFltPortRetain);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnRelease = NETFLT_CALLBACK(vboxNetFltPortRelease);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnDisconnectAndRelease= NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnSetActive = NETFLT_CALLBACK(vboxNetFltPortSetActive);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnWaitForIdle = NETFLT_CALLBACK(vboxNetFltPortWaitForIdle);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnGetMacAddress = NETFLT_CALLBACK(vboxNetFltPortGetMacAddress);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnIsHostMac = NETFLT_CALLBACK(vboxNetFltPortIsHostMac);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnIsPromiscuous = NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous);
3bddd917f8743d7e0773c2872c497ca4dae57c78vboxsync pNew->MyPort.pfnXmit = NETFLT_CALLBACK(vboxNetFltPortXmit);
de4157257515400c2c25373591135f110227b68cvboxsync pNew->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->pSwitchPort = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->pGlobals = pGlobals;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->hSpinlock = NIL_RTSPINLOCK;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->enmState = kVBoxNetFltInsState_Initializing;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->fActive = false;
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
de4157257515400c2c25373591135f110227b68cvboxsync rc = RTSpinlockCreate(&pNew->hSpinlock);
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;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync int rc;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync AssertRCReturn(rc, rc);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /*
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Look for an existing instance in the list.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * If found that it's being destroyed, wait for it to go away.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Return instances in other states ASSUMING that it has lost the
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * connection.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync *ppInstance = vboxNetFltFindInstanceLocked(pGlobals, pszName);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync while (*ppInstance)
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync {
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync VBOXNETFTLINSSTATE enmState = vboxNetFltGetState(*ppInstance);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if ( enmState != kVBoxNetFltInsState_Destroying
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync && enmState != kVBoxNetFltInsState_Destroyed)
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /** @todo r=bird: who is making sure this is a genuine reconnection case? */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltRetain(*ppInstance, false /* fBusy */);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync return VINF_ALREADY_INITIALIZED;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync }
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /* wait 2 ms */ /** @todo r=bird: Doesn't RTThreadSleep() work here? If it's bust, I'd like to know it so we can fix it... */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync RTSemEventWait(pGlobals->hBlockEvent, 2);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync AssertRCReturn(rc, rc);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync /* try again */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *ppInstance = 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);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync 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
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#if defined(VBOX_TAPMINIPORT) && defined(RT_OS_WINDOWS)
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync /* temporary hack to pick up the first adapter */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pCur = pGlobals->pInstanceHead; /** @todo Don't for get to remove this temporary hack... :-) */
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#else
de4157257515400c2c25373591135f110227b68cvboxsync pCur = vboxNetFltFindInstanceLocked(pGlobals, pszName);
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# if 0 /** @todo r=bird: We need to fix the race here. The race is against release+destructor, the
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * tell tale is a cRefs of and since cRefs is manipulated in an atomic fashion we can simply attempt
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * to grab a reference atomically, the worst thing that can happen is that we have to decrement it again..
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Here is my suggestion: */
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 {
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. */
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 */);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# else
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (vboxNetFltGetState(pCur) == kVBoxNetFltInsState_Unconnected)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync vboxNetFltRetain(pCur, false /* fBusy */); /** @todo r=bird: Who releases this on failure? */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pCur->fDisablePromiscuous = !!(fFlags & INTNETTRUNKFACTORY_FLAG_NO_PROMISC);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = vboxNetFltConnectIt(pCur, pSwitchPort, ppIfPort);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync else
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = VERR_INTNET_FLT_IF_BUSY;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync RTSemFastMutexRelease(pGlobals->hFastMtx);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# endif
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 */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = vboxNetFltNewInstance(pGlobals, pszName, pSwitchPort,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync !!(fFlags & INTNETTRUNKFACTORY_FLAG_NO_PROMISC),
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 *
de4157257515400c2c25373591135f110227b68cvboxsync * @param pSupDrvFactory Pointer to the componet 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;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync RTSemEventDestroy(pGlobals->hBlockEvent);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pGlobals->hBlockEvent = NIL_RTSEMEVENT;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#endif
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
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 {
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync rc = RTSemEventCreate(&pGlobals->hBlockEvent);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync if (RT_SUCCESS(rc))
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync {
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync#endif
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync pGlobals->pInstanceHead = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync pGlobals->TrunkFactory.pfnRelease = vboxNetFltFactoryRelease;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetFltFactoryCreateAndConnect;
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#if defined(RT_OS_WINDOWS) && defined(VBOX_TAPMINIPORT)
51b5a11e595811cfd0873a5ad86aa55d7584b5f3vboxsync strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetAdp");
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#else
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetFlt");
9ab5fb4455f72f3d979ff63e8789cb3241b80b52vboxsync#endif
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetFltQueryFactoryInterface;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pGlobals->fIDCOpen = false;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync return rc;
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync#ifdef VBOXNETFLT_STATIC_CONFIG
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync }
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync RTSemFastMutexDestroy(pGlobals->hFastMtx);
36856a8f35043a53995e4eb764d0e4e4bf1e5e8fvboxsync#endif
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