diff options
Diffstat (limited to 'src/VBox/HostDrivers/VBoxNetFlt')
38 files changed, 4122 insertions, 1272 deletions
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk b/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk index 0d1dfdd70..b1d4b028d 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk +++ b/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk @@ -1,10 +1,10 @@ -# $Id: Makefile.kmk $ +# $Id: Makefile.kmk 29108 2010-05-05 20:17:42Z vboxsync $ ## @file # Sub-Makefile for the Network Filter Driver (VBoxNetFlt). # # -# Copyright (C) 2008 Sun Microsystems, Inc. +# Copyright (C) 2008 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -14,10 +14,6 @@ # VirtualBox OSE distribution. VirtualBox OSE is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# SUB_DEPTH = ../../../.. include $(KBUILD_PATH)/subheader.kmk @@ -48,6 +44,9 @@ ifdef VBOX_NETFLT_ONDEMAND_BIND VBoxNetFlt_DEFS.win += VBOX_NETFLT_ONDEMAND_BIND else VBoxNetFlt_DEFS.win += VBOXNETFLT_STATIC_CONFIG + VBoxNetFlt_DEFS.win += VBOXNETFLT_NO_PACKET_QUEUE + VBoxNetFlt_DEFS.win += NDIS_MINIPORT_DRIVER NDIS_WDM=1 BINARY_COMPATIBLE=0 + VBoxNetFlt_DEFS.win += NDIS50_MINIPORT=1 NDIS50=1 VBoxNetFlt_SOURCES.win += win/VBoxNetFltMp-win.c endif ifdef VBOX_LOOPBACK_USEFLAGS @@ -57,8 +56,6 @@ VBoxNetFlt_SOURCES = VBoxNetFlt.c #VBoxNetFlt_LDFLAGS.darwin = -v -Wl,-whyload -Wl,-v -Wl,-whatsloaded VBoxNetFlt_LDFLAGS.win.x86 = -Entry:DriverEntry@8 VBoxNetFlt_LDFLAGS.win.amd64 = -Entry:DriverEntry -VBoxNetFlt_SOURCES.win.amd64 += win/VBoxNetFltA-win.asm -VBoxNetFlt_DEFS.win.amd64 += RT_WITH_W64_UNWIND_HACK VBoxNetFlt_LIBS.win = \ $(PATH_SDK_W2K3DDK_LIB)/ntoskrnl.lib \ $(PATH_SDK_W2K3DDK_LIB)/hal.lib \ @@ -201,6 +198,9 @@ NetAdpUninstall_LIBS = $(TARGET_WinNetConfig) \ # VBoxNetFltNotify # DLLS.win += VBoxNetFltNotify +if defined(VBOX_SIGNING_MODE) +VBoxNetFltNotify_NOINST = true +endif VBoxNetFltNotify_TEMPLATE = VBOXR3STATIC VBoxNetFltNotify_SDKS = WINPSDK W2K3DDK VBOX_NTDLL VBoxNetFltNotify_DEFS = _WIN32_WINNT=0x0500 WIN32 _ATL_STATIC_REGISTRY @@ -258,10 +258,11 @@ VBoxNetAdp_SOURCES = \ win/VBoxNetFltMp-win.c \ win/VBoxNetFlt-win.rc VBoxNetAdp_DEFS += VBOXNETFLT_STATIC_CONFIG VBOXNETADP +VBoxNetAdp_DEFS.win += VBOXNETFLT_NO_PACKET_QUEUE +VBoxNetAdp_DEFS += NDIS_MINIPORT_DRIVER NDIS_WDM=1 BINARY_COMPATIBLE=0 +VBoxNetAdp_DEFS += NDIS50_MINIPORT=1 NDIS50=1 VBoxNetAdp_LDFLAGS.win.x86 = -Entry:DriverEntry@8 VBoxNetAdp_LDFLAGS.win.amd64 = -Entry:DriverEntry -VBoxNetAdp_SOURCES.win.amd64 += win/VBoxNetFltA-win.asm -VBoxNetAdp_DEFS.win.amd64 += RT_WITH_W64_UNWIND_HACK VBoxNetAdp_LIBS.win = \ $(PATH_SDK_W2K3DDK_LIB)/ntoskrnl.lib \ $(PATH_SDK_W2K3DDK_LIB)/hal.lib \ @@ -332,9 +333,22 @@ vboxnetflt_SOURCES.linux = linux/VBoxNetFlt-linux.c vboxnetflt_SOURCES.solaris = solaris/VBoxNetFlt-solaris.c vboxnetflt_SOURCES.freebsd = freebsd/VBoxNetFlt-freebsd.c vboxnetflt_SOURCES = VBoxNetFlt.c - endif - solaris/VBoxNetFlt-solaris.c_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV) + ifdef VBOX_WITH_NETFLT_CROSSBOW +SYSMODS += vboxnetbow +vboxnetbow_TEMPLATE = VBOXR0DRV +vboxnetbow_NAME = vboxbow +vboxnetbow_DEFS = vboxnetflt_DEFS VBOX_WITH_NETFLT_CROSSBOW +vboxnetbow_DEPS += $(VBOX_SVN_REV_KMK) +vboxnetbow_INCS := $(PATH_SUB_CURRENT) +vboxnetbow_LDFLAGS += -N drv/vboxdrv -N drv/vnic -N misc/mac -N misc/dls +vboxnetbow_LIBS = \ + $(PATH_LIB)/SUPR0IdcClient$(VBOX_SUFF_LIB) +vboxnetbow_SOURCES.solaris = solaris/VBoxNetFltBow-solaris.c +vboxnetbow_SOURCES = VBoxNetFlt.c +solaris/VBoxNetFltBow-solaris.c_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV) + endif # VBOX_WITH_NETFLT_CROSSBOW + endif # VBOX_WITH_VBOXDRV endif # to be removed. @@ -384,7 +398,7 @@ ifeq ($(KBUILD_TARGET),linux) $(VBOX_VERSION_STAMP) \ | $$(dir $$@) $(call MSG_TOOL,Creating,,$@) - $(QUIET)$(SED) -e "s;_VERSION_;${VBOX_VERSION_STRING};g; s;_MODULE_;vboxnetflt;g" --output $@ $< + $(QUIET)$(SED) -e "s;_VERSION_;${VBOX_VERSION_STRING};g; s;_MODULE_;vboxnetflt;g; s;_BUILDTYPE_;${KBUILD_TYPE};g" --output $@ $< $(QUIET)chmod 0755 $@ # Script needed for building the kernel module @@ -431,4 +445,3 @@ endif # freebsd include $(KBUILD_PATH)/subfooter.kmk - diff --git a/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFlt.c b/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFlt.c index 2a2fc9c93..e49e64b47 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFlt.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFlt.c @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFlt.c $ */ +/* $Id: VBoxNetFlt.c 29150 2010-05-06 13:13:03Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Common Code. */ /* - * Copyright (C) 2008-2009 Sun Microsystems, Inc. + * Copyright (C) 2008-2009 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,32 +13,65 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /** @page pg_netflt VBoxNetFlt - Network Interface Filter * - * This is a kernel module that attaches to a real interface on the host - * and filters and injects packets. + * This is a kernel module that attaches to a real interface on the host and + * filters and injects packets. * * In the big picture we're one of the three trunk interface on the internal * network, the one named "NIC Filter Driver": @image html Networking_Overview.gif * * - * @section sec_netflt_msc Locking / Sequence Diagrams + * @section sec_netflt_locking Locking and Potential Races + * + * The main challenge here is to make sure the netfilter and internal network + * instances won't be destroyed while someone is calling into them. + * + * The main calls into or out of of the filter driver are: + * - Send. + * - Async send completion (not implemented yet) + * - Release by the internal network. + * - Receive. + * - Disappearance of the host networking interface. + * - Reappearance of the host networking interface. + * + * The latter two calls are can be caused by driver unloading/loading or the + * device being physical unplugged (e.g. a USB network device). Actually, the + * unload scenario must fervently be prevent as it will cause panics because the + * internal network will assume the trunk is around until it releases it. + * @todo Need to figure which host allow unloading and block/fix it. + * + * Currently the netfilter instance lives until the internal network releases + * it. So, it is the internal networks responsibility to make sure there are no + * active calls when it releases the trunk and destroys the network. The + * netfilter assists in this by providing INTNETTRUNKIFPORT::pfnSetState and + * INTNETTRUNKIFPORT::pfnWaitForIdle. The trunk state is used to enable/disable + * promiscuous mode on the hardware NIC (or similar activation) as well + * indicating that disconnect is imminent and no further calls shall be made + * into the internal network. After changing the state to disconnecting and + * prior to invoking INTNETTRUNKIFPORT::pfnDisconnectAndRelease, the internal + * network will use INTNETTRUNKIFPORT::pfnWaitForIdle to wait for any still + * active calls to complete. + * + * The netfilter employs a busy counter and an internal state in addition to the + * public trunk state. All these variables are protected using a spinlock. + * + * + * @section sec_netflt_msc Locking / Sequence Diagrams - OBSOLETE + * + * !OBSOLETE! - THIS WAS THE OLD APPROACH! * * This secion contains a few sequence diagrams describing the problematic * transitions of a host interface filter instance. * * The thing that makes it all a bit problematic is that multiple events may * happen at the same time, and that we have to be very careful to avoid - * deadlocks caused by mixing our locks with the ones in the host kernel. - * The main events are receive, send, async send completion, disappearance of - * the host networking interface and it's reappearance. The latter two events - * are can be caused by driver unloading/loading or the device being physical + * deadlocks caused by mixing our locks with the ones in the host kernel. The + * main events are receive, send, async send completion, disappearance of the + * host networking interface and its reappearance. The latter two events are + * can be caused by driver unloading/loading or the device being physical * unplugged (e.g. a USB network device). * * The strategy for dealing with these issues are: @@ -52,7 +85,7 @@ * using a spinlock. * * - * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release + * @subsection subsec_netflt_msc_dis_rel Disconnect from the network and release - OBSOLETE * * @msc * VM, IntNet, NetFlt, Kernel, Wire; @@ -117,7 +150,7 @@ * * * - * @subsection subsec_netflt_msc_hif_rm Host Interface Removal + * @subsection subsec_netflt_msc_hif_rm Host Interface Removal - OBSOLETE * * The ifnet_t (pIf) is a tricky customer as any reference to it can potentially * race the filter detaching. The simple way of solving it on Darwin is to guard @@ -157,7 +190,7 @@ * * * - * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery + * @subsection subsec_netflt_msc_hif_rm Host Interface Rediscovery - OBSOLETE * * The rediscovery is performed when we receive a send request and a certain * period have elapsed since the last attempt, i.e. we're polling it. We @@ -341,15 +374,28 @@ static void vboxNetFltUnlinkLocked(PVBOXNETFLTGLOBALS pGlobals, PVBOXNETFLTINS p */ static bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis) { - RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - uint64_t Now = RTTimeNanoTS(); - bool fRediscovered; - bool fDoIt; + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + uint64_t Now; + bool fRediscovered; + bool fDoIt; + + /* + * Don't do rediscovery if we're called with preemption disabled. + * + * Note! This may cause trouble if we're always called with preemptioni + * disabled and vboxNetFltOsMaybeRediscovered actually does some real + * work. For the time being though, only Darwin and FreeBSD depends + * on these call outs and neither supports sending with preemption + * disabled. + */ + if (!RTThreadPreemptIsEnabled(NIL_RTTHREAD)) + return false; /* * Rediscovered already? Time to try again? */ - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + Now = RTTimeNanoTS(); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); fRediscovered = !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost); fDoIt = !fRediscovered @@ -358,7 +404,7 @@ static bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis) if (fDoIt) ASMAtomicWriteBool(&pThis->fRediscoveryPending, true); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); /* * Call the OS specific code to do the job. @@ -375,39 +421,18 @@ static bool vboxNetFltMaybeRediscovered(PVBOXNETFLTINS pThis) ASMAtomicWriteBool(&pThis->fRediscoveryPending, false); if (fRediscovered) - vboxNetFltPortOsSetActive(pThis, pThis->fActive); + /** @todo this isn't 100% serialized. */ + vboxNetFltPortOsSetActive(pThis, pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE); } return fRediscovered; } -#ifdef RT_WITH_W64_UNWIND_HACK -# if defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64) -# define NETFLT_DECL_CALLBACK(type) DECLASM(DECLHIDDEN(type)) -# define NETFLT_CALLBACK(_n) netfltNtWrap##_n - -NETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortXmit)(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst); -NETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous)(PINTNETTRUNKIFPORT pIfPort); -NETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortGetMacAddress)(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac); -NETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortIsHostMac)(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac); -NETFLT_DECL_CALLBACK(int) NETFLT_CALLBACK(vboxNetFltPortWaitForIdle)(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies); -NETFLT_DECL_CALLBACK(bool) NETFLT_CALLBACK(vboxNetFltPortSetActive)(PINTNETTRUNKIFPORT pIfPort, bool fActive); -NETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease)(PINTNETTRUNKIFPORT pIfPort); -NETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRetain)(PINTNETTRUNKIFPORT pIfPort); -NETFLT_DECL_CALLBACK(void) NETFLT_CALLBACK(vboxNetFltPortRelease)(PINTNETTRUNKIFPORT pIfPort); - -# else -# error "UNSUPPORTED (RT_WITH_W64_UNWIND_HACK)" -# endif -#else -# define NETFLT_DECL_CALLBACK(type) static DECLCALLBACK(type) -# define NETFLT_CALLBACK(_n) _n -#endif /** * @copydoc INTNETTRUNKIFPORT::pfnXmit */ -NETFLT_DECL_CALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst) +static DECLCALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst) { PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); int rc = VINF_SUCCESS; @@ -419,92 +444,27 @@ NETFLT_DECL_CALLBACK(int) vboxNetFltPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNET AssertPtr(pSG); Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE); - Assert(pThis->fActive); /* * Do a busy retain and then make sure we're connected to the interface * before invoking the OS specific code. */ - vboxNetFltRetain(pThis, true /* fBusy */); - if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost) - || vboxNetFltMaybeRediscovered(pThis)) - rc = vboxNetFltPortOsXmit(pThis, pSG, fDst); - vboxNetFltRelease(pThis, true /* fBusy */); + if (RT_LIKELY(vboxNetFltTryRetainBusyActive(pThis))) + { + if ( !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost) + || vboxNetFltMaybeRediscovered(pThis)) + rc = vboxNetFltPortOsXmit(pThis, pSG, fDst); + vboxNetFltRelease(pThis, true /* fBusy */); + } return rc; } /** - * @copydoc INTNETTRUNKIFPORT::pfnIsPromiscuous - */ -NETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsPromiscuous(PINTNETTRUNKIFPORT pIfPort) -{ - PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); - - /* - * Input validation. - */ - AssertPtr(pThis); - Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); - Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected); - Assert(pThis->fActive); - - /* - * Ask the OS specific code. - */ - return vboxNetFltPortOsIsPromiscuous(pThis); -} - - -/** - * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress - */ -NETFLT_DECL_CALLBACK(void) vboxNetFltPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac) -{ - PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); - - /* - * Input validation. - */ - AssertPtr(pThis); - Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); - Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected); - Assert(pThis->fActive); - - /* - * Forward the question to the OS specific code. - */ - vboxNetFltPortOsGetMacAddress(pThis, pMac); -} - - -/** - * @copydoc INTNETTRUNKIFPORT::pfnIsHostMac - */ -NETFLT_DECL_CALLBACK(bool) vboxNetFltPortIsHostMac(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac) -{ - PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); - - /* - * Input validation. - */ - AssertPtr(pThis); - Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); - Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected); - Assert(pThis->fActive); - - /* - * Ask the OS specific code. - */ - return vboxNetFltPortOsIsHostMac(pThis, pMac); -} - - -/** * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle */ -NETFLT_DECL_CALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies) +static DECLCALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies) { PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); int rc; @@ -515,7 +475,7 @@ NETFLT_DECL_CALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, AssertPtr(pThis); Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, VERR_INVALID_STATE); - AssertReturn(!pThis->fActive, VERR_INVALID_STATE); + AssertReturn(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING, VERR_INVALID_STATE); /* * Go to sleep on the semaphore after checking the busy count. @@ -533,11 +493,13 @@ NETFLT_DECL_CALLBACK(int) vboxNetFltPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, /** - * @copydoc INTNETTRUNKIFPORT::pfnSetActive + * @copydoc INTNETTRUNKIFPORT::pfnSetState */ -NETFLT_DECL_CALLBACK(bool) vboxNetFltPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive) +static DECLCALLBACK(INTNETTRUNKIFSTATE) vboxNetFltPortSetState(PINTNETTRUNKIFPORT pIfPort, INTNETTRUNKIFSTATE enmState) { - PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); + PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + INTNETTRUNKIFSTATE enmOldTrunkState; /* * Input validation. @@ -545,35 +507,39 @@ NETFLT_DECL_CALLBACK(bool) vboxNetFltPortSetActive(PINTNETTRUNKIFPORT pIfPort, b AssertPtr(pThis); AssertPtr(pThis->pGlobals); Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); - AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, false); + AssertReturn(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected, INTNETTRUNKIFSTATE_INVALID); + AssertReturn(enmState > INTNETTRUNKIFSTATE_INVALID && enmState < INTNETTRUNKIFSTATE_END, + INTNETTRUNKIFSTATE_INVALID); /* - * We're assuming that the caller is serializing the calls, so we don't - * have to be extremely careful here. Just update first and then call - * the OS specific code, the update must be serialized for various reasons. + * Take the lock and change the state. */ - if (ASMAtomicReadBool(&pThis->fActive) != fActive) - { - RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); - ASMAtomicWriteBool(&pThis->fActive, fActive); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + enmOldTrunkState = pThis->enmTrunkState; + if (enmOldTrunkState != enmState) + ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmTrunkState, enmState); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); - vboxNetFltPortOsSetActive(pThis, fActive); - } - else - fActive = !fActive; - return !fActive; + /* + * If the state change indicates that the trunk has become active or + * inactive, call the OS specific part so they can work the promiscuous + * settings and such. + * Note! The caller makes sure there are no concurrent pfnSetState calls. + */ + if ((enmOldTrunkState == INTNETTRUNKIFSTATE_ACTIVE) != (enmState == INTNETTRUNKIFSTATE_ACTIVE)) + vboxNetFltPortOsSetActive(pThis, (enmState == INTNETTRUNKIFSTATE_ACTIVE)); + + return enmOldTrunkState; } /** * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease */ -NETFLT_DECL_CALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort) +static DECLCALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort) { PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); - RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; /* * Serious paranoia. @@ -587,24 +553,24 @@ NETFLT_DECL_CALLBACK(void) vboxNetFltPortDisconnectAndRelease(PINTNETTRUNKIFPORT Assert(pThis->szName[0]); Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Connected); - Assert(!pThis->fActive); + Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING); Assert(!pThis->fRediscoveryPending); Assert(!pThis->cBusy); /* * Disconnect and release it. */ - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); vboxNetFltSetState(pThis, kVBoxNetFltInsState_Disconnecting); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); vboxNetFltOsDisconnectIt(pThis); pThis->pSwitchPort = NULL; #ifdef VBOXNETFLT_STATIC_CONFIG - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); vboxNetFltSetState(pThis, kVBoxNetFltInsState_Unconnected); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); #endif vboxNetFltRelease(pThis, false /* fBusy */); @@ -634,7 +600,7 @@ static bool vboxNetFltDestroyInstance(PVBOXNETFLTINS pThis) #else Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Disconnecting); #endif - Assert(!pThis->fActive); + Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING); Assert(!pThis->fRediscoveryPending); Assert(!pThis->cRefs); Assert(!pThis->cBusy); @@ -725,7 +691,7 @@ DECLHIDDEN(void) vboxNetFltRelease(PVBOXNETFLTINS pThis, bool fBusy) /** * @copydoc INTNETTRUNKIFPORT::pfnRetain */ -NETFLT_DECL_CALLBACK(void) vboxNetFltPortRelease(PINTNETTRUNKIFPORT pIfPort) +static DECLCALLBACK(void) vboxNetFltPortRelease(PINTNETTRUNKIFPORT pIfPort) { PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); vboxNetFltRelease(pThis, false /* fBusy */); @@ -775,9 +741,104 @@ DECLHIDDEN(void) vboxNetFltRetain(PVBOXNETFLTINS pThis, bool fBusy) /** + * Tries to retain the device as busy if the trunk is active. + * + * This is used before calling pfnRecv or pfnPreRecv. + * + * @returns true if we succeeded in retaining a busy reference to the active + * device. false if we failed. + * @param pThis The instance. + */ +DECLHIDDEN(bool) vboxNetFltTryRetainBusyActive(PVBOXNETFLTINS pThis) +{ + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + uint32_t cRefs; + bool fRc; + + /* + * Paranoid Android. + */ + AssertPtr(pThis); + Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); + Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION); + Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid + && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed); + AssertPtr(pThis->pGlobals); + Assert(pThis->hEventIdle != NIL_RTSEMEVENT); + Assert(pThis->hSpinlock != NIL_RTSPINLOCK); + Assert(pThis->szName[0]); + + /* + * Do the retaining and checking behind the spinlock. + */ + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + fRc = pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE; + if (fRc) + { + cRefs = ASMAtomicIncU32(&pThis->cRefs); + AssertMsg(cRefs > 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs); + + cRefs = ASMAtomicIncU32(&pThis->cBusy); + AssertMsg(cRefs >= 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs); + } + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); + + return fRc; +} + + +/** + * Tries to retain the device as busy if the trunk is not disconnecting. + * + * This is used before reporting stuff to the internal network. + * + * @returns true if we succeeded in retaining a busy reference to the active + * device. false if we failed. + * @param pThis The instance. + */ +DECLHIDDEN(bool) vboxNetFltTryRetainBusyNotDisconnected(PVBOXNETFLTINS pThis) +{ + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + uint32_t cRefs; + bool fRc; + + /* + * Paranoid Android. + */ + AssertPtr(pThis); + Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); + Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION); + Assert( vboxNetFltGetState(pThis) > kVBoxNetFltInsState_Invalid + && vboxNetFltGetState(pThis) < kVBoxNetFltInsState_Destroyed); + AssertPtr(pThis->pGlobals); + Assert(pThis->hEventIdle != NIL_RTSEMEVENT); + Assert(pThis->hSpinlock != NIL_RTSPINLOCK); + Assert(pThis->szName[0]); + + /* + * Do the retaining and checking behind the spinlock. + */ + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + fRc = pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE + || pThis->enmTrunkState == INTNETTRUNKIFSTATE_INACTIVE; + if (fRc) + { + cRefs = ASMAtomicIncU32(&pThis->cRefs); + AssertMsg(cRefs > 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs); + + cRefs = ASMAtomicIncU32(&pThis->cBusy); + AssertMsg(cRefs >= 1 && cRefs < UINT32_MAX / 2, ("%d\n", cRefs)); NOREF(cRefs); + } + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); + + return fRc; +} + + +/** * @copydoc INTNETTRUNKIFPORT::pfnRetain */ -NETFLT_DECL_CALLBACK(void) vboxNetFltPortRetain(PINTNETTRUNKIFPORT pIfPort) +static DECLCALLBACK(void) vboxNetFltPortRetain(PINTNETTRUNKIFPORT pIfPort) { PVBOXNETFLTINS pThis = IFPORT_2_VBOXNETFLTINS(pIfPort); vboxNetFltRetain(pThis, false /* fBusy */); @@ -804,13 +865,19 @@ static int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchP /* * Validate state. */ - Assert(!pThis->fActive); Assert(!pThis->fRediscoveryPending); Assert(!pThis->cBusy); #ifdef VBOXNETFLT_STATIC_CONFIG Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Unconnected); + /* INTNETTRUNKIFSTATE_DISCONNECTING means "not connected" here + * we use the INTNETTRUNKIFSTATE_DISCONNECTING state for consistency of cases when trunk + * was never connected and was connected and disconnected. + * In the latter case we end up with INTNETTRUNKIFSTATE_DICONNECTING, + * so use the same state for the former */ + Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING); #else Assert(vboxNetFltGetState(pThis) == kVBoxNetFltInsState_Initializing); + Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_INACTIVE); #endif /* @@ -827,7 +894,16 @@ static int vboxNetFltConnectIt(PVBOXNETFLTINS pThis, PINTNETTRUNKSWPORT pSwitchP else pThis->pSwitchPort = NULL; - Assert(!pThis->fActive); +#ifdef VBOXNETFLT_STATIC_CONFIG + /* INTNETTRUNKIFSTATE_DISCONNECTING means "not connected" here + * we use the INTNETTRUNKIFSTATE_DISCONNECTING state for consistency of cases when trunk + * was never connected and was connected and disconnected. + * In the latter case we end up with INTNETTRUNKIFSTATE_DISCONNECTING, + * so use the same state for the former */ + Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_DISCONNECTING); +#else + Assert(pThis->enmTrunkState == INTNETTRUNKIFSTATE_INACTIVE); +#endif return rc; } @@ -861,21 +937,25 @@ static int vboxNetFltNewInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszNam return VERR_INTNET_FLT_IF_FAILED; pNew->pNext = NULL; pNew->MyPort.u32Version = INTNETTRUNKIFPORT_VERSION; - pNew->MyPort.pfnRetain = NETFLT_CALLBACK(vboxNetFltPortRetain); - pNew->MyPort.pfnRelease = NETFLT_CALLBACK(vboxNetFltPortRelease); - pNew->MyPort.pfnDisconnectAndRelease= NETFLT_CALLBACK(vboxNetFltPortDisconnectAndRelease); - pNew->MyPort.pfnSetActive = NETFLT_CALLBACK(vboxNetFltPortSetActive); - pNew->MyPort.pfnWaitForIdle = NETFLT_CALLBACK(vboxNetFltPortWaitForIdle); - pNew->MyPort.pfnGetMacAddress = NETFLT_CALLBACK(vboxNetFltPortGetMacAddress); - pNew->MyPort.pfnIsHostMac = NETFLT_CALLBACK(vboxNetFltPortIsHostMac); - pNew->MyPort.pfnIsPromiscuous = NETFLT_CALLBACK(vboxNetFltPortIsPromiscuous); - pNew->MyPort.pfnXmit = NETFLT_CALLBACK(vboxNetFltPortXmit); + pNew->MyPort.pfnRetain = vboxNetFltPortRetain; + pNew->MyPort.pfnRelease = vboxNetFltPortRelease; + pNew->MyPort.pfnDisconnectAndRelease= vboxNetFltPortDisconnectAndRelease; + pNew->MyPort.pfnSetState = vboxNetFltPortSetState; + pNew->MyPort.pfnWaitForIdle = vboxNetFltPortWaitForIdle; + pNew->MyPort.pfnXmit = vboxNetFltPortXmit; pNew->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION; - pNew->pSwitchPort = NULL; + pNew->pSwitchPort = pSwitchPort; pNew->pGlobals = pGlobals; pNew->hSpinlock = NIL_RTSPINLOCK; pNew->enmState = kVBoxNetFltInsState_Initializing; - pNew->fActive = false; +#ifdef VBOXNETFLT_STATIC_CONFIG + /* for consistency of cases when trunk was never connected and was connected and disconnected. + * In the latter case we end up with INTNETTRUNKIFSTATE_DISCONNECTING, + * so use the same state for the former */ + pNew->enmTrunkState = INTNETTRUNKIFSTATE_DISCONNECTING; +#else + pNew->enmTrunkState = INTNETTRUNKIFSTATE_INACTIVE; +#endif pNew->fDisconnectedFromHost = false; pNew->fRediscoveryPending = false; pNew->fDisablePromiscuous = fNoPromisc; diff --git a/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h b/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h index 68b86383c..2bb676377 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h +++ b/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFltInternal.h $ */ +/* $Id: VBoxNetFltInternal.h 29108 2010-05-05 20:17:42Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Internal Header. */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #ifndef ___VBoxNetFltInternal_h___ @@ -107,7 +103,8 @@ typedef struct VBOXNETFLTINS RTSPINLOCK hSpinlock; /** The current interface state. */ VBOXNETFTLINSSTATE volatile enmState; - /** Active / Suspended indicator. */ + /** The trunk state. */ + INTNETTRUNKIFSTATE volatile enmTrunkState; bool volatile fActive; /** Disconnected from the host network interface. */ bool volatile fDisconnectedFromHost; @@ -130,6 +127,7 @@ typedef struct VBOXNETFLTINS /** The event that is signaled when we go idle and that pfnWaitForIdle blocks on. */ RTSEMEVENT hEventIdle; + /** @todo move MacAddr out of this structure! */ union { #ifdef VBOXNETFLT_OS_SPECFIC @@ -152,7 +150,7 @@ typedef struct VBOXNETFLTINS * This is for dealing with the ENETDOWN case. */ bool volatile fSetPromiscuous; /** The MAC address of the interface. */ - RTMAC Mac; + RTMAC MacAddr; /** @} */ # elif defined(RT_OS_LINUX) /** @name Linux instance data @@ -165,15 +163,35 @@ typedef struct VBOXNETFLTINS /** Whether device exists and physically attached. */ bool volatile fRegistered; /** The MAC address of the interface. */ - RTMAC Mac; + RTMAC MacAddr; struct notifier_block Notifier; struct packet_type PacketType; +# ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE struct sk_buff_head XmitQueue; struct work_struct XmitTask; +# endif /** @} */ # elif defined(RT_OS_SOLARIS) /** @name Solaris instance data. * @{ */ +# ifdef VBOX_WITH_NETFLT_CROSSBOW + /** The link Id of the VNIC */ + datalink_id_t VNICLinkId; + /** Instance number of VNIC */ + uint16_t uInstance; + /** Whether we created the VNIC or not */ + bool fCreatedVNIC; + /** The lower MAC handle */ + mac_handle_t hInterface; + /** The client MAC handle */ + mac_client_handle_t hClient; + /** The unicast address handle */ + mac_unicast_handle_t hUnicast; + /** The promiscuous handle */ + mac_promisc_handle_t hPromiscuous; + /** The MAC address of the interface */ + RTMAC MacAddr; +# else /** Pointer to the bound IPv4 stream. */ void volatile *pvIp4Stream; /** Pointer to the bound IPv6 stream. */ @@ -189,11 +207,12 @@ typedef struct VBOXNETFLTINS /** Layered device handle to the interface. */ ldi_handle_t hIface; /** The MAC address of the interface. */ - RTMAC Mac; + RTMAC MacAddr; /** Mutex protection used for loopback. */ RTSEMFASTMUTEX hFastMtx; /** Mutex protection used for dynamic IPv6 attaches. */ RTSEMFASTMUTEX hPollMtx; +# endif /** @} */ # elif defined(RT_OS_FREEBSD) /** @name FreeBSD instance data. @@ -217,7 +236,7 @@ typedef struct VBOXNETFLTINS /** Output task */ struct task tskout; /** The MAC address of the interface. */ - RTMAC Mac; + RTMAC MacAddr; /** @} */ # elif defined(RT_OS_WINDOWS) /** @name Windows instance data. @@ -227,11 +246,12 @@ typedef struct VBOXNETFLTINS volatile uint32_t cModeNetFltRefs; volatile uint32_t cModePassThruRefs; - +#ifndef VBOXNETFLT_NO_PACKET_QUEUE /** Packet worker thread info */ PACKET_QUEUE_WORKER PacketQueueWorker; +#endif /** The MAC address of the interface. Caching MAC for performance reasons. */ - RTMAC Mac; + RTMAC MacAddr; /** mutex used to synchronize ADAPT init/deinit */ RTSEMMUTEX hAdaptMutex; /** @} */ @@ -308,6 +328,8 @@ DECLHIDDEN(bool) vboxNetFltCanUnload(PVBOXNETFLTGLOBALS pGlobals); DECLHIDDEN(PVBOXNETFLTINS) vboxNetFltFindInstance(PVBOXNETFLTGLOBALS pGlobals, const char *pszName); DECLHIDDEN(void) vboxNetFltRetain(PVBOXNETFLTINS pThis, bool fBusy); +DECLHIDDEN(bool) vboxNetFltTryRetainBusyActive(PVBOXNETFLTINS pThis); +DECLHIDDEN(bool) vboxNetFltTryRetainBusyNotDisconnected(PVBOXNETFLTINS pThis); DECLHIDDEN(void) vboxNetFltRelease(PVBOXNETFLTINS pThis, bool fBusy); #ifdef VBOXNETFLT_STATIC_CONFIG @@ -343,49 +365,6 @@ DECLHIDDEN(bool) vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis); DECLHIDDEN(int) vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst); /** - * Checks if the interface is in promiscuous mode from the host perspective. - * - * If it is, then the internal networking switch will send frames - * heading for the wire to the host as well. - * - * @see INTNETTRUNKIFPORT::pfnIsPromiscuous for more details. - * - * @returns true / false accordingly. - * @param pThis The instance. - * - * @remarks Owns the network lock and the out-bound trunk port semaphores. - */ -DECLHIDDEN(bool) vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis); - -/** - * Get the MAC address of the interface we're attached to. - * - * Used by the internal networking switch for implementing the - * shared-MAC-on-the-wire mode. - * - * @param pThis The instance. - * @param pMac Where to store the MAC address. - * If you don't know, set all the bits except the first (the multicast one). - * - * @remarks Owns the network lock and the out-bound trunk port semaphores. - */ -DECLHIDDEN(void) vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac); - -/** - * Checks if the specified MAC address is for any of the host interfaces. - * - * Used by the internal networking switch to decide the destination(s) - * of a frame. - * - * @returns true / false accordingly. - * @param pThis The instance. - * @param pMac The MAC address. - * - * @remarks Owns the network lock and the out-bound trunk port semaphores. - */ -DECLHIDDEN(bool) vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac); - -/** * This is called when activating or suspending the instance. * * Use this method to enable and disable promiscuous mode on @@ -433,6 +412,9 @@ DECLHIDDEN(void) vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis); * This is called to attach to the actual host interface * after linking the instance into the list. * + * The MAC address as well promiscuousness and GSO capabilities should be + * reported by this function. + * * @return IPRT status code. * @param pThis The new instance. * @param pvContext The user supplied context in the static config only. diff --git a/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp b/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp index fecb5d249..3e7d035ea 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFlt-darwin.cpp $ */ +/* $Id: VBoxNetFlt-darwin.cpp 28830 2010-04-27 14:05:25Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Darwin Specific Code. */ /* - * Copyright (C) 2006-2008 Sun Microsystems, Inc. + * Copyright (C) 2006-2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /******************************************************************************* @@ -36,6 +32,7 @@ #define LOG_GROUP LOG_GROUP_NET_FLT_DRV #include <VBox/log.h> #include <VBox/err.h> +#include <VBox/intnetinline.h> #include <VBox/version.h> #include <iprt/initterm.h> #include <iprt/assert.h> @@ -235,14 +232,14 @@ DECLINLINE(ifnet_t) vboxNetFltDarwinRetainIfNet(PVBOXNETFLTINS pThis) /* * Be careful here to avoid problems racing the detached callback. */ - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); if (!ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)) { pIfNet = (ifnet_t)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pIfNet); if (pIfNet) ifnet_reference(pIfNet); } - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); return pIfNet; } @@ -384,26 +381,27 @@ static mbuf_t vboxNetFltDarwinMBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG) && mbuf_maxlen(pCur) >= pSG->cbTotal) { mbuf_setlen(pCur, pSG->cbTotal); - memcpy(mbuf_data(pCur), pSG->aSegs[0].pv, pSG->cbTotal); + IntNetSgRead(pSG, mbuf_data(pCur)); } else { /* Multi buffer copying. */ - size_t cbSrc = pSG->cbTotal; - uint8_t const *pbSrc = (uint8_t const *)pSG->aSegs[0].pv; - while (cbSrc > 0 && pCur) + size_t cbLeft = pSG->cbTotal; + size_t offSrc = 0; + while (cbLeft > 0 && pCur) { size_t cb = mbuf_maxlen(pCur); - if (cbSrc < cb) - cb = cbSrc; + if (cb > cbLeft) + cb = cbLeft; mbuf_setlen(pCur, cb); - memcpy(mbuf_data(pCur), pbSrc, cb); + IntNetSgReadEx(pSG, offSrc, cb, mbuf_data(pCur)); /* advance */ - pbSrc += cb; - cbSrc -= cb; + offSrc += cb; + cbLeft -= cb; pCur = mbuf_next(pCur); } + Assert(cbLeft == 0); } if (!err) { @@ -492,18 +490,11 @@ DECLINLINE(void) vboxNetFltDarwinMBufToSG(PVBOXNETFLTINS pThis, mbuf_t pMBuf, vo { NOREF(pThis); - pSG->pvOwnerData = NULL; - pSG->pvUserData = NULL; - pSG->pvUserData2 = NULL; - pSG->cUsers = 1; - pSG->fFlags = INTNETSG_FLAGS_TEMP; - pSG->cSegsAlloc = cSegs; - /* - * Walk the chain and convert the buffers to segments. + * Walk the chain and convert the buffers to segments. Works INTNETSG::cbTotal. */ unsigned iSeg = 0; - pSG->cbTotal = 0; + IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/); for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur)) { size_t cbSeg = mbuf_len(pCur); @@ -622,6 +613,31 @@ DECLINLINE(void) vboxNetFltDarwinMBufToSG(PVBOXNETFLTINS pThis, mbuf_t pMBuf, vo /** + * Helper for determining whether the host wants the interface to be + * promiscuous. + */ +static bool vboxNetFltDarwinIsPromiscuous(PVBOXNETFLTINS pThis) +{ + bool fRc = false; + ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis); + if (pIfNet) + { + /* gather the data */ + uint16_t fIf = ifnet_flags(pIfNet); + unsigned cPromisc = VBOX_GET_PCOUNT(pIfNet); + bool fSetPromiscuous = ASMAtomicUoReadBool(&pThis->u.s.fSetPromiscuous); + vboxNetFltDarwinReleaseIfNet(pThis, pIfNet); + + /* calc the return. */ + fRc = (fIf & IFF_PROMISC) + && cPromisc > fSetPromiscuous; + } + return fRc; +} + + + +/** * * @see iff_detached_func in the darwin kpi. */ @@ -647,7 +663,7 @@ static void vboxNetFltDarwinIffDetached(void *pvThis, ifnet_t pIfNet) * We carefully take the spinlock and increase the interface reference * behind it in order to avoid problematic races with the detached callback. */ - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); pIfNet = (ifnet_t)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pIfNet); int cPromisc = VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : - 1; @@ -660,7 +676,7 @@ static void vboxNetFltDarwinIffDetached(void *pvThis, ifnet_t pIfNet) ASMAtomicUoWriteBool(&pThis->fRediscoveryPending, false); ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); if (pIfNet) ifnet_release(pIfNet); @@ -755,6 +771,8 @@ static void vboxNetFltDarwinIffEvent(void *pvThis, ifnet_t pIfNet, protocol_fami } else if (pEvMsg->event_code == KEV_DL_LINK_OFF) Log(("vboxNetFltDarwinIffEvent: %s goes down (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pIfNet))); +/** @todo KEV_DL_LINK_ADDRESS_CHANGED -> pfnReportMacAddress */ +/** @todo KEV_DL_SIFFLAGS -> pfnReportPromiscuousMode */ } else Log(("vboxNetFltDarwinIffEvent: pThis->u.s.pIfNet=%p pIfNet=%p (%d)\n", pThis->u.s.pIfNet, pIfNet, VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : -1)); @@ -798,13 +816,7 @@ static errno_t vboxNetFltDarwinIffInputOutputWorker(PVBOXNETFLTINS pThis, mbuf_t /* * Active? Retain the instance and increment the busy counter. */ - RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); - const bool fActive = ASMAtomicUoReadBool(&pThis->fActive); - if (fActive) - vboxNetFltRetain(pThis, true /* fBusy */); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); - if (!fActive) + if (!vboxNetFltTryRetainBusyActive(pThis)) return 0; /* @@ -900,14 +912,14 @@ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRedisco } RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pIfNet, pIfNet); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); /* * Get the mac address while we still have a valid ifnet reference. */ - err = ifnet_lladdr_copy_bytes(pIfNet, &pThis->u.s.Mac, sizeof(pThis->u.s.Mac)); + err = ifnet_lladdr_copy_bytes(pIfNet, &pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); if (!err) { /* @@ -926,7 +938,7 @@ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRedisco err = iflt_attach(pIfNet, &RegRec, &pIfFilter); Assert(err || pIfFilter); - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); pIfNet = (ifnet_t)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pIfNet); if (pIfNet && !err) { @@ -934,7 +946,19 @@ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRedisco ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pIfFilter, pIfFilter); pIfNet = NULL; /* don't dereference it */ } - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); + + /* Report capabilities. */ + if ( !pIfNet + && vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + Assert(pThis->pSwitchPort); + pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); + pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltDarwinIsPromiscuous(pThis)); + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); + pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); + vboxNetFltRelease(pThis, true /*fBusy*/); + } } /* Release the interface on failure. */ @@ -943,7 +967,7 @@ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRedisco int rc = RTErrConvertFromErrno(err); if (RT_SUCCESS(rc)) - LogRel(("VBoxFltDrv: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.Mac), &pThis->u.s.Mac)); + LogRel(("VBoxFltDrv: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); else LogRel(("VBoxFltDrv: failed to attach to ifnet '%s' (err=%d)\n", pThis->szName, err)); return rc; @@ -1009,41 +1033,6 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) } -bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis) -{ - bool fRc = false; - ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis); - if (pIfNet) - { - /* gather the data */ - uint16_t fIf = ifnet_flags(pIfNet); - unsigned cPromisc = VBOX_GET_PCOUNT(pIfNet); - bool fSetPromiscuous = ASMAtomicUoReadBool(&pThis->u.s.fSetPromiscuous); - vboxNetFltDarwinReleaseIfNet(pThis, pIfNet); - - /* calc the return. */ - fRc = (fIf & IFF_PROMISC) - && cPromisc > fSetPromiscuous; - } - return fRc; -} - - -void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac) -{ - *pMac = pThis->u.s.Mac; -} - - -bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) -{ - /* ASSUMES that the MAC address never changes. */ - return pThis->u.s.Mac.au16[0] == pMac->au16[0] - && pThis->u.s.Mac.au16[1] == pMac->au16[1] - && pThis->u.s.Mac.au16[2] == pMac->au16[2]; -} - - void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) { ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis); @@ -1169,11 +1158,11 @@ void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis) /* * Carefully obtain the interface filter reference and detach it. */ - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); pIfFilter = (interface_filter_t)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pIfFilter); if (pIfFilter) ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pIfFilter, NULL); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); if (pIfFilter) iflt_detach(pIfFilter); @@ -1196,7 +1185,7 @@ int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis) pThis->u.s.pIfFilter = NULL; pThis->u.s.fSetPromiscuous = false; pThis->u.s.fNeedSetPromiscuous = false; - //pThis->u.s.Mac = {0}; + //pThis->u.s.MacAddr = {0}; return VINF_SUCCESS; } diff --git a/src/VBox/HostDrivers/VBoxNetFlt/darwin/loadnetflt.sh b/src/VBox/HostDrivers/VBoxNetFlt/darwin/loadnetflt.sh index fde0f4265..81ca4be5b 100755 --- a/src/VBox/HostDrivers/VBoxNetFlt/darwin/loadnetflt.sh +++ b/src/VBox/HostDrivers/VBoxNetFlt/darwin/loadnetflt.sh @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2008 Sun Microsystems, Inc. +# Copyright (C) 2006-2008 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -14,10 +14,6 @@ # VirtualBox OSE distribution. VirtualBox OSE is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# SCRIPT_NAME="loadnetflt" XNU_VERSION=`LC_ALL=C uname -r | LC_ALL=C cut -d . -f 1` diff --git a/src/VBox/HostDrivers/VBoxNetFlt/freebsd/Makefile b/src/VBox/HostDrivers/VBoxNetFlt/freebsd/Makefile index e45df4d5f..c51a2d4d7 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/freebsd/Makefile +++ b/src/VBox/HostDrivers/VBoxNetFlt/freebsd/Makefile @@ -1,11 +1,11 @@ -# $Id: Makefile $ +# $Id: Makefile 28800 2010-04-27 08:22:32Z vboxsync $ ## @file # Makefile for the VirtualBox FreeBSD Host Driver. # # # -# Copyright (C) 2006-2007 Sun Microsystems, Inc. +# Copyright (C) 2006-2007 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -15,10 +15,6 @@ # VirtualBox OSE distribution. VirtualBox OSE is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# KMOD = vboxnetflt diff --git a/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c b/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c index e9edbd223..4d13c2350 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c @@ -1,4 +1,4 @@ -/* $Id: VBoxNetFlt-freebsd.c $ */ +/* $Id: VBoxNetFlt-freebsd.c 28830 2010-04-27 14:05:25Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), FreeBSD Specific Code. */ @@ -60,6 +60,7 @@ #include <VBox/version.h> #include <VBox/err.h> #include <VBox/log.h> +#include <VBox/intnetinline.h> #include <iprt/initterm.h> #include <iprt/string.h> #include <iprt/spinlock.h> @@ -187,13 +188,7 @@ static void vboxNetFltFreeBSDMBufToSG(PVBOXNETFLTINS pThis, struct mbuf *m, PINT unsigned int i; struct mbuf *m0; - pSG->cbTotal = m_length(m, NULL); - pSG->pvOwnerData = NULL; - pSG->pvUserData = NULL; - pSG->pvUserData2 = NULL; - pSG->cUsers = 1; - pSG->fFlags = INTNETSG_FLAGS_TEMP; - pSG->cSegsAlloc = cSegs; + IntNetSgInitTempSegs(pSG, m_length(m, NULL), cSegs, 0 /*cSegsUsed*/); for (m0 = m, i = segOffset; m0; m0 = m0->m_next) { @@ -216,6 +211,7 @@ static void vboxNetFltFreeBSDMBufToSG(PVBOXNETFLTINS pThis, struct mbuf *m, PINT i++; } #endif + pSG->cSegsUsed = i; } @@ -228,7 +224,7 @@ static struct mbuf * vboxNetFltFreeBSDSGMBufFromSG(PVBOXNETFLTINS pThis, PINTNET int error; unsigned int i; - if (pSG->cbTotal == 0 || pSG->aSegs[0].cb == 0) + if (pSG->cbTotal == 0) return (NULL); m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); @@ -319,7 +315,7 @@ static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item) struct m_tag *mtag; bool fActive; - fActive = ASMAtomicUoReadBool(&pThis->fActive); + fActive = vboxNetFltTryRetainBusyActive(pThis); NGI_GET_M(item, m); NG_FREE_ITEM(item); @@ -341,6 +337,8 @@ static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item) if (mtag != NULL || !fActive) { ether_demux(ifp, m); + if (fActive) + vboxNetFltRelease(pThis, true /*fBusy*/); return (0); } mtx_lock_spin(&pThis->u.s.inq.ifq_mtx); @@ -348,13 +346,18 @@ static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item) mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx); taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskin); } - /** + /* * Handle mbufs on the outgoing hook, frames going to the interface */ else if (pThis->u.s.output == hook) { if (mtag != NULL || !fActive) - return ether_output_frame(ifp, m); + { + int rc = ether_output_frame(ifp, m); + if (fActive) + vboxNetFltRelease(pThis, true /*fBusy*/); + return rc; + } mtx_lock_spin(&pThis->u.s.outq.ifq_mtx); _IF_ENQUEUE(&pThis->u.s.outq, m); mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx); @@ -364,6 +367,9 @@ static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item) { m_freem(m); } + + if (fActive) + vboxNetFltRelease(pThis, true /*fBusy*/); return (0); } @@ -373,8 +379,7 @@ static int ng_vboxnetflt_shutdown(node_p node) bool fActive; /* Prevent node shutdown if we're active */ - fActive = ASMAtomicUoReadBool(&pThis->fActive); - if (fActive) + if (pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE) return (EBUSY); NG_NODE_UNREF(node); return (0); @@ -418,7 +423,7 @@ static void vboxNetFltFreeBSDinput(void *arg, int pending) /* Create a copy and deliver to the virtual switch */ pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0); - fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST); + fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_WIRE); RTMemTmpFree(pSG); if (fDropIt) m_freem(m); @@ -528,6 +533,13 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) return VINF_SUCCESS; } +static bool vboxNetFltFreeBsdIsPromiscuous(PVBOXNETFLTINS pThis) +{ + /** @todo This isn't taking into account that we put the interface in + * promiscuous mode. */ + return (pThis->u.s.flags & IFF_PROMISC) ? true : false; +} + int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) { char nam[NG_NODESIZ]; @@ -544,11 +556,13 @@ int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0) return VERR_INTERNAL_ERROR; - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp); pThis->u.s.node = node; - bcopy(IF_LLADDR(ifp), &pThis->u.s.Mac, ETHER_ADDR_LEN); + bcopy(IF_LLADDR(ifp), &pThis->u.s.MacAddr, ETHER_ADDR_LEN); ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); + /* Initialize deferred input queue */ bzero(&pThis->u.s.inq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN); @@ -559,13 +573,27 @@ int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); NG_NODE_SET_PRIVATE(node, pThis); + /* Attempt to name it vboxnetflt_<ifname> */ snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName); ng_name_node(node, nam); + /* Report MAC address, promiscuous mode and GSO capabilities. */ + /** @todo keep these reports up to date, either by polling for changes or + * intercept some control flow if possible. */ + if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + Assert(pThis->pSwitchPort); + pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); + pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltFreeBsdIsPromiscuous(pThis)); + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); + pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); + vboxNetFltRelease(pThis, true /*fBusy*/); + } + return VINF_SUCCESS; } @@ -707,23 +735,6 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) } } -bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis) -{ - return (pThis->u.s.flags & IFF_PROMISC) ? true : false; -} - -void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac) -{ - *pMac = pThis->u.s.Mac; -} - -bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) -{ - return pThis->u.s.Mac.au16[0] == pMac->au16[0] - && pThis->u.s.Mac.au16[1] == pMac->au16[1] - && pThis->u.s.Mac.au16[2] == pMac->au16[2]; -} - int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis) { return VINF_SUCCESS; diff --git a/src/VBox/HostDrivers/VBoxNetFlt/freebsd/files_vboxnetflt b/src/VBox/HostDrivers/VBoxNetFlt/freebsd/files_vboxnetflt index cefcaa465..9290f0edf 100755..100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/freebsd/files_vboxnetflt +++ b/src/VBox/HostDrivers/VBoxNetFlt/freebsd/files_vboxnetflt @@ -1,11 +1,11 @@ #!/bin/sh -# $Id: files_vboxnetflt $ +# $Id: files_vboxnetflt 29250 2010-05-09 17:53:58Z vboxsync $ ## @file # Shared file between Makefile.kmk and export_modules # # -# Copyright (C) 2007 Sun Microsystems, Inc. +# Copyright (C) 2007-2010 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -24,15 +24,13 @@ # You may elect to license modified versions of this file under the # terms and conditions of either the GPL or the CDDL or both. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/include/iprt/alloc.h=>include/iprt/alloc.h \ ${PATH_ROOT}/include/iprt/alloca.h=>include/iprt/alloca.h \ ${PATH_ROOT}/include/iprt/asm.h=>include/iprt/asm.h \ + ${PATH_ROOT}/include/iprt/asm-amd64-x86.h=>include/iprt/asm-amd64-x86.h \ + ${PATH_ROOT}/include/iprt/asm-math.h=>include/iprt/asm-math.h \ ${PATH_ROOT}/include/iprt/assert.h=>include/iprt/assert.h \ ${PATH_ROOT}/include/iprt/avl.h=>include/iprt/avl.h \ ${PATH_ROOT}/include/iprt/cdefs.h=>include/iprt/cdefs.h \ @@ -63,6 +61,7 @@ VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/include/VBox/err.h=>include/VBox/err.h \ ${PATH_ROOT}/include/VBox/log.h=>include/VBox/log.h \ ${PATH_ROOT}/include/VBox/intnet.h=>include/VBox/intnet.h \ + ${PATH_ROOT}/include/VBox/intnetinline.h=>include/VBox/intnetinline.h \ ${PATH_ROOT}/include/VBox/stam.h=>include/VBox/stam.h \ ${PATH_ROOT}/include/VBox/sup.h=>include/VBox/sup.h \ ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ @@ -75,10 +74,8 @@ VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPR0IdcClientComponent.c=>SUPR0IdcClientComponent.c \ ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPR0IdcClientInternal.h=>SUPR0IdcClientInternal.h \ ${PATH_ROOT}/src/VBox/HostDrivers/Support/freebsd/SUPR0IdcClient-freebsd.c=>SUPR0IdcClient-freebsd.c \ - ${PATH_ROOT}/src/VBox/Runtime/include/internal/initterm.h=>include/internal/initterm.h \ - ${PATH_ROOT}/src/VBox/Runtime/include/internal/iprt.h=>include/internal/iprt.h \ - ${PATH_ROOT}/src/VBox/Runtime/include/internal/magics.h=>include/internal/magics.h \ ${PATH_ROOT}/src/VBox/Runtime/r0drv/freebsd/the-freebsd-kernel.h=>r0drv/freebsd/the-freebsd-kernel.h \ ${PATH_OUT}/version-generated.h=>version-generated.h \ + ${PATH_OUT}/product-generated.h=>product-generated.h \ " diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile b/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile index ceefc45f1..63bc82587 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile +++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile @@ -5,7 +5,7 @@ # # -# Copyright (C) 2006-2007 Sun Microsystems, Inc. +# Copyright (C) 2006-2007 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -15,10 +15,6 @@ # VirtualBox OSE distribution. VirtualBox OSE is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# # # First, figure out which architecture we're targeting and the build type. @@ -69,7 +65,7 @@ OBJS = \ VBoxNetFlt.o \ SUPR0IdcClient.o \ SUPR0IdcClientComponent.o \ - SUPR0IdcClient-linux.o \ + linux/SUPR0IdcClient-linux.o ifeq ($(BUILD_TARGET_ARCH),x86) OBJS += math/gcc/divdi3.o \ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c b/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c index f03c90c1b..3287ffe08 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFlt-linux.c $ */ +/* $Id: VBoxNetFlt-linux.c 28830 2010-04-27 14:05:25Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Linux Specific Code. */ /* - * Copyright (C) 2006-2008 Sun Microsystems, Inc. + * Copyright (C) 2006-2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,26 +13,27 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /******************************************************************************* * Header Files * *******************************************************************************/ +#define LOG_GROUP LOG_GROUP_NET_FLT_DRV +#define VBOXNETFLT_LINUX_NO_XMIT_QUEUE #include "the-linux-kernel.h" #include "version-generated.h" +#include "product-generated.h" #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> #include <linux/miscdevice.h> #include <linux/ip.h> -#define LOG_GROUP LOG_GROUP_NET_FLT_DRV #include <VBox/log.h> #include <VBox/err.h> +#include <VBox/intnetinline.h> +#include <VBox/pdmnetinline.h> +#include <VBox/param.h> #include <iprt/alloca.h> #include <iprt/assert.h> #include <iprt/spinlock.h> @@ -40,6 +41,7 @@ #include <iprt/initterm.h> #include <iprt/process.h> #include <iprt/mem.h> +#include <iprt/net.h> #include <iprt/log.h> #include <iprt/mp.h> #include <iprt/mem.h> @@ -48,74 +50,76 @@ #define VBOXNETFLT_OS_SPECFIC 1 #include "../VBoxNetFltInternal.h" -#define VBOX_FLT_NB_TO_INST(pNB) ((PVBOXNETFLTINS)((uint8_t *)pNB - \ - RT_OFFSETOF(VBOXNETFLTINS, u.s.Notifier))) -#define VBOX_FLT_PT_TO_INST(pPT) ((PVBOXNETFLTINS)((uint8_t *)pPT - \ - RT_OFFSETOF(VBOXNETFLTINS, u.s.PacketType))) -#define VBOX_FLT_XT_TO_INST(pXT) ((PVBOXNETFLTINS)((uint8_t *)pXT - \ - RT_OFFSETOF(VBOXNETFLTINS, u.s.XmitTask))) -#define VBOX_GET_PCOUNT(pDev) (pDev->promiscuity) +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +#define VBOX_FLT_NB_TO_INST(pNB) RT_FROM_MEMBER(pNB, VBOXNETFLTINS, u.s.Notifier) +#define VBOX_FLT_PT_TO_INST(pPT) RT_FROM_MEMBER(pPT, VBOXNETFLTINS, u.s.PacketType) +#ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE +# define VBOX_FLT_XT_TO_INST(pXT) RT_FROM_MEMBER(pXT, VBOXNETFLTINS, u.s.XmitTask) +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -# define VBOX_SKB_RESET_NETWORK_HDR(skb) skb_reset_network_header(skb) -# define VBOX_SKB_RESET_MAC_HDR(skb) skb_reset_mac_header(skb) -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */ -# define VBOX_SKB_RESET_NETWORK_HDR(skb) skb->nh.raw = skb->data -# define VBOX_SKB_RESET_MAC_HDR(skb) skb->mac.raw = skb->data -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */ +# define VBOX_SKB_RESET_NETWORK_HDR(skb) skb_reset_network_header(skb) +# define VBOX_SKB_RESET_MAC_HDR(skb) skb_reset_mac_header(skb) +#else +# define VBOX_SKB_RESET_NETWORK_HDR(skb) skb->nh.raw = skb->data +# define VBOX_SKB_RESET_MAC_HDR(skb) skb->mac.raw = skb->data +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -# define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(skb) -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) */ -# define CHECKSUM_PARTIAL CHECKSUM_HW +# define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(skb) +#else +# define CHECKSUM_PARTIAL CHECKSUM_HW # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) -# define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(skb, 0) -# else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) */ +# define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(skb, 0) +# else # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7) -# define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(&skb, 0) -# else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 7) */ -# define VBOX_SKB_CHECKSUM_HELP(skb) (!skb_checksum_help(skb)) -# endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 7) */ -# endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) */ -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -# define VBOX_SKB_IS_GSO(skb) skb_is_gso(skb) - /* No features, very dumb device */ -# define VBOX_SKB_GSO_SEGMENT(skb) skb_gso_segment(skb, 0) -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) */ -# define VBOX_SKB_IS_GSO(skb) false -# define VBOX_SKB_GSO_SEGMENT(skb) NULL -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) */ +# define VBOX_SKB_CHECKSUM_HELP(skb) skb_checksum_help(&skb, 0) +# else +# define VBOX_SKB_CHECKSUM_HELP(skb) (!skb_checksum_help(skb)) +# endif +# endif +#endif #ifndef NET_IP_ALIGN # define NET_IP_ALIGN 2 #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) -unsigned dev_get_flags(const struct net_device *dev) -{ - unsigned flags; +#if 0 +/** Create scatter / gather segments for fragments. When not used, we will + * linearize the socket buffer before creating the internal networking SG. */ +# define VBOXNETFLT_SG_SUPPORT 1 +#endif - flags = (dev->flags & ~(IFF_PROMISC | - IFF_ALLMULTI | - IFF_RUNNING)) | - (dev->gflags & (IFF_PROMISC | - IFF_ALLMULTI)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +/** Indicates that the linux kernel may send us GSO frames. */ +# define VBOXNETFLT_WITH_GSO 1 - if (netif_running(dev) && netif_carrier_ok(dev)) - flags |= IFF_RUNNING; +/** This enables or disables the transmitting of GSO frame from the internal + * network and to the host. */ +# define VBOXNETFLT_WITH_GSO_XMIT_HOST 1 + +# if 0 /** @todo This is currently disable because it causes performance loss of 5-10%. */ +/** This enables or disables the transmitting of GSO frame from the internal + * network and to the wire. */ +# define VBOXNETFLT_WITH_GSO_XMIT_WIRE 1 +# endif + +/** This enables or disables the forwarding/flooding of GSO frame from the host + * to the internal network. */ +# define VBOXNETFLT_WITH_GSO_RECV 1 + +#endif - return flags; -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) */ /******************************************************************************* * Internal Functions * *******************************************************************************/ static int VBoxNetFltLinuxInit(void); static void VBoxNetFltLinuxUnload(void); +static void vboxNetFltLinuxForwardToIntNet(PVBOXNETFLTINS pThis, struct sk_buff *pBuf); /******************************************************************************* @@ -129,14 +133,33 @@ static VBOXNETFLTGLOBALS g_VBoxNetFltGlobals; module_init(VBoxNetFltLinuxInit); module_exit(VBoxNetFltLinuxUnload); -MODULE_AUTHOR("Sun Microsystems, Inc."); -MODULE_DESCRIPTION("VirtualBox Network Filter Driver"); +MODULE_AUTHOR(VBOX_VENDOR); +MODULE_DESCRIPTION(VBOX_PRODUCT " Network Filter Driver"); MODULE_LICENSE("GPL"); #ifdef MODULE_VERSION MODULE_VERSION(VBOX_VERSION_STRING " (" RT_XSTR(INTNETTRUNKIFPORT_VERSION) ")"); #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) && defined(LOG_ENABLED) +unsigned dev_get_flags(const struct net_device *dev) +{ + unsigned flags; + + flags = (dev->flags & ~(IFF_PROMISC | + IFF_ALLMULTI | + IFF_RUNNING)) | + (dev->gflags & (IFF_PROMISC | + IFF_ALLMULTI)); + + if (netif_running(dev) && netif_carrier_ok(dev)) + flags |= IFF_RUNNING; + + return flags; +} +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) */ + + /** * Initialize module. * @@ -202,6 +225,178 @@ static void __exit VBoxNetFltLinuxUnload(void) Log(("VBoxNetFltLinuxUnload - done\n")); } +/** + * Experiment where we filter trafic from the host to the internal network + * before it reaches the NIC driver. + * + * The current code uses a very ugly hack and only works on kernels using the + * net_device_ops (>= 2.6.29). It has been shown to give us a + * performance boost of 60-100% though. So, we have to find some less hacky way + * of getting this job done eventually. + * + * #define VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT + */ +#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT + +/** + * The overridden net_device_ops of the device we're attached to. + * + * Requires Linux 2.6.29 or later. + * + * This is a very dirty hack that was create to explore how much we can improve + * the host to guest transfers by not CC'ing the NIC. + */ +typedef struct VBoxNetDeviceOpsOverride +{ + /** Our overridden ops. */ + struct net_device_ops Ops; + /** Magic word. */ + uint32_t u32Magic; + /** Pointer to the original ops. */ + struct net_device_ops const *pOrgOps; + /** Pointer to the net filter instance. */ + PVBOXNETFLTINS pVBoxNetFlt; + /** The number of filtered packages. */ + uint64_t cFiltered; + /** The total number of packets */ + uint64_t cTotal; +} VBOXNETDEVICEOPSOVERRIDE, *PVBOXNETDEVICEOPSOVERRIDE; +/** VBOXNETDEVICEOPSOVERRIDE::u32Magic value. */ +#define VBOXNETDEVICEOPSOVERRIDE_MAGIC UINT32_C(0x00c0ffee) + +/** + * ndo_start_xmit wrapper that drops packets that shouldn't go to the wire + * because they belong on the internal network. + * + * @returns NETDEV_TX_XXX. + * @param pSkb The socket buffer to transmit. + * @param pDev The net device. + */ +static int vboxNetFltLinuxStartXmitFilter(struct sk_buff *pSkb, struct net_device *pDev) +{ + PVBOXNETDEVICEOPSOVERRIDE pOverride = (PVBOXNETDEVICEOPSOVERRIDE)pDev->netdev_ops; + uint8_t abHdrBuf[sizeof(RTNETETHERHDR) + sizeof(uint32_t) + RTNETIPV4_MIN_LEN]; + PCRTNETETHERHDR pEtherHdr; + PINTNETTRUNKSWPORT pSwitchPort; + + + /* + * Validate the override structure. + * + * Note! We're racing vboxNetFltLinuxUnhookDev here. If this was supposed + * to be production quality code, we would have to be much more + * careful here and avoid the race. + */ + if ( !VALID_PTR(pOverride) + || pOverride->u32Magic != VBOXNETDEVICEOPSOVERRIDE_MAGIC + || !VALID_PTR(pOverride->pOrgOps)) + { + printk("vboxNetFltLinuxStartXmitFilter: bad override %p\n", pOverride); + dev_kfree_skb(pSkb); + return NETDEV_TX_OK; + } + pOverride->cTotal++; + + /* + * Do the filtering base on the defaul OUI of our virtual NICs + * + * Note! In a real solution, we would ask the switch whether the + * destination MAC is 100% to be on the internal network and then + * drop it. + */ + pEtherHdr = (PCRTNETETHERHDR)skb_header_pointer(pSkb, 0, sizeof(abHdrBuf), &abHdrBuf[0]); + if ( pEtherHdr + && VALID_PTR(pOverride->pVBoxNetFlt) + && (pSwitchPort = pOverride->pVBoxNetFlt->pSwitchPort) != NULL + && VALID_PTR(pSwitchPort) + ) + { + INTNETSWDECISION enmDecision; + uint32_t cbHdrs = skb_headlen(pSkb); + cbHdrs = RT_MAX(cbHdrs, sizeof(abHdrBuf)); + + /** @todo consider reference counting, etc. */ + enmDecision = pSwitchPort->pfnPreRecv(pSwitchPort, pEtherHdr, cbHdrs, INTNETTRUNKDIR_HOST); + if (enmDecision == INTNETSWDECISION_INTNET) + { + dev_kfree_skb(pSkb); + pOverride->cFiltered++; + return NETDEV_TX_OK; + } + } + + return pOverride->pOrgOps->ndo_start_xmit(pSkb, pDev); +} + +/** + * Hooks the device ndo_start_xmit operation of the device. + * + * @param pThis The net filter instance. + * @param pDev The net device. + */ +static void vboxNetFltLinuxHookDev(PVBOXNETFLTINS pThis, struct net_device *pDev) +{ + PVBOXNETDEVICEOPSOVERRIDE pOverride; + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + + pOverride = RTMemAlloc(sizeof(*pOverride)); + if (!pOverride) + return; + pOverride->pOrgOps = pDev->netdev_ops; + pOverride->Ops = *pDev->netdev_ops; + pOverride->Ops.ndo_start_xmit = vboxNetFltLinuxStartXmitFilter; + pOverride->u32Magic = VBOXNETDEVICEOPSOVERRIDE_MAGIC; + pOverride->cTotal = 0; + pOverride->cFiltered = 0; + pOverride->pVBoxNetFlt = pThis; + + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); /* (this isn't necessary, but so what) */ + ASMAtomicXchgPtr((void * volatile *)&pDev->netdev_ops, pOverride); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); +} + +/** + * Undos what vboxNetFltLinuxHookDev did. + * + * @param pThis The net filter instance. + * @param pDev The net device. Can be NULL, in which case + * we'll try retrieve it from @a pThis. + */ +static void vboxNetFltLinuxUnhookDev(PVBOXNETFLTINS pThis, struct net_device *pDev) +{ + PVBOXNETDEVICEOPSOVERRIDE pOverride; + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + if (!pDev) + pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); + if (VALID_PTR(pDev)) + { + pOverride = (PVBOXNETDEVICEOPSOVERRIDE)pDev->netdev_ops; + if ( VALID_PTR(pOverride) + && pOverride->u32Magic == VBOXNETDEVICEOPSOVERRIDE_MAGIC + && VALID_PTR(pOverride->pOrgOps) + ) + { + ASMAtomicXchgPtr((void * volatile *)&pDev->netdev_ops, pOverride->pOrgOps); + ASMAtomicWriteU32(&pOverride->u32Magic, 0); + } + else + pOverride = NULL; + } + else + pOverride = NULL; + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); + + if (pOverride) + { + printk("vboxnetflt: dropped %llu out of %llu packets\n", pOverride->cFiltered, pOverride->cTotal); + RTMemFree(pOverride); + } +} + +#endif /* VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT */ + /** * Reads and retains the host interface handle. @@ -284,58 +479,116 @@ DECLINLINE(bool) vboxNetFltLinuxSkBufIsOur(struct sk_buff *pBuf) * @returns Pointer to the sk_buff. * @param pThis The instance. * @param pSG The (scatter/)gather list. + * @param fDstWire Set if the destination is the wire. */ static struct sk_buff *vboxNetFltLinuxSkBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, bool fDstWire) { struct sk_buff *pPkt; struct net_device *pDev; - /* - * Because we're lazy, we will ASSUME that all SGs coming from INTNET - * will only contain one single segment. - */ - if (pSG->cSegsUsed != 1 || pSG->cbTotal != pSG->aSegs[0].cb) - { - LogRel(("VBoxNetFlt: Dropped multi-segment(%d) packet coming from internal network.\n", pSG->cSegsUsed)); - return NULL; - } + unsigned fGsoType = 0; + if (pSG->cbTotal == 0) { LogRel(("VBoxNetFlt: Dropped empty packet coming from internal network.\n")); return NULL; } + /** @todo We should use fragments mapping the SG buffers with large packets. + * 256 bytes seems to be the a threshold used a lot for this. It + * requires some nasty work on the intnet side though... */ /* * Allocate a packet and copy over the data. - * */ pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); pPkt = dev_alloc_skb(pSG->cbTotal + NET_IP_ALIGN); - if (pPkt) + if (RT_UNLIKELY(!pPkt)) + { + Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal)); + pSG->pvUserData = NULL; + return NULL; + } + pPkt->dev = pDev; + pPkt->ip_summed = CHECKSUM_NONE; + + /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */ + skb_reserve(pPkt, NET_IP_ALIGN); + + /* Copy the segments. */ + skb_put(pPkt, pSG->cbTotal); + IntNetSgRead(pSG, pPkt->data); + +#if defined(VBOXNETFLT_WITH_GSO_XMIT_WIRE) || defined(VBOXNETFLT_WITH_GSO_XMIT_HOST) + /* + * Setup GSO if used by this packet. + */ + switch ((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type) { - pPkt->dev = pDev; - /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */ - skb_reserve(pPkt, NET_IP_ALIGN); - skb_put(pPkt, pSG->cbTotal); - memcpy(pPkt->data, pSG->aSegs[0].pv, pSG->cbTotal); - /* Set protocol and packet_type fields. */ - pPkt->protocol = eth_type_trans(pPkt, pDev); - pPkt->ip_summed = CHECKSUM_NONE; + default: + AssertMsgFailed(("%u (%s)\n", pSG->GsoCtx.u8Type, PDMNetGsoTypeName((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type) )); + /* fall thru */ + case PDMNETWORKGSOTYPE_INVALID: + fGsoType = 0; + break; + case PDMNETWORKGSOTYPE_IPV4_TCP: + fGsoType = SKB_GSO_TCPV4; + break; + case PDMNETWORKGSOTYPE_IPV4_UDP: + fGsoType = SKB_GSO_UDP; + break; + case PDMNETWORKGSOTYPE_IPV6_TCP: + fGsoType = SKB_GSO_TCPV6; + break; + } + if (fGsoType) + { + struct skb_shared_info *pShInfo = skb_shinfo(pPkt); + + pShInfo->gso_type = fGsoType | SKB_GSO_DODGY; + pShInfo->gso_size = pSG->GsoCtx.cbMaxSeg; + pShInfo->gso_segs = PDMNetGsoCalcSegmentCount(&pSG->GsoCtx, pSG->cbTotal); + if (fDstWire) { - VBOX_SKB_RESET_NETWORK_HDR(pPkt); - /* Restore ethernet header back. */ - skb_push(pPkt, ETH_HLEN); - VBOX_SKB_RESET_MAC_HDR(pPkt); + Assert(skb_headlen(pPkt) >= pSG->GsoCtx.cbHdrs); + pPkt->ip_summed = CHECKSUM_PARTIAL; +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + pPkt->csum_start = skb_headroom(pPkt) + pSG->GsoCtx.offHdr2; + if (fGsoType & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) + pPkt->csum_offset = RT_OFFSETOF(RTNETTCP, th_sum); + else + pPkt->csum_offset = RT_OFFSETOF(RTNETUDP, uh_sum); +# else + pPkt->h.raw = pPkt->data + pSG->GsoCtx.offHdr2; + if (fGsoType & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) + pPkt->csum = RT_OFFSETOF(RTNETTCP, th_sum); + else + pPkt->csum = RT_OFFSETOF(RTNETUDP, uh_sum); +# endif + } + else + { + pPkt->ip_summed = CHECKSUM_UNNECESSARY; + pPkt->csum = 0; + PDMNetGsoPrepForDirectUse(&pSG->GsoCtx, pPkt->data, pSG->cbTotal, false /*fPayloadChecksum*/); } - VBOXNETFLT_SKB_TAG(pPkt) = VBOXNETFLT_CB_TAG(pPkt); + } +#endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE || VBOXNETFLT_WITH_GSO_XMIT_HOST */ + + /* + * Finish up the socket buffer. + */ + pPkt->protocol = eth_type_trans(pPkt, pDev); + if (fDstWire) + { + VBOX_SKB_RESET_NETWORK_HDR(pPkt); - return pPkt; + /* Restore ethernet header back. */ + skb_push(pPkt, ETH_HLEN); /** @todo VLAN: +4 if VLAN? */ + VBOX_SKB_RESET_MAC_HDR(pPkt); } - else - Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal)); - pSG->pvUserData = NULL; + VBOXNETFLT_SKB_TAG(pPkt) = VBOXNETFLT_CB_TAG(pPkt); - return NULL; + return pPkt; } @@ -350,21 +603,18 @@ static struct sk_buff *vboxNetFltLinuxSkBufFromSG(PVBOXNETFLTINS pThis, PINTNETS * @param cSegs The number of segments allocated for the SG. * This should match the number in the mbuf exactly! * @param fSrc The source of the frame. + * @param pGso Pointer to the GSO context if it's a GSO + * internal network frame. NULL if regular frame. */ -DECLINLINE(void) vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff *pBuf, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc) +DECLINLINE(void) vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff *pBuf, PINTNETSG pSG, + unsigned cSegs, uint32_t fSrc, PCPDMNETWORKGSO pGsoCtx) { int i; NOREF(pThis); Assert(!skb_shinfo(pBuf)->frag_list); - pSG->pvOwnerData = NULL; - pSG->pvUserData = NULL; - pSG->pvUserData2 = NULL; - pSG->cUsers = 1; - pSG->fFlags = INTNETSG_FLAGS_TEMP; - pSG->cSegsAlloc = cSegs; - - if (fSrc & INTNETTRUNKDIR_WIRE) + + if (fSrc & INTNETTRUNKDIR_WIRE) { /* * The packet came from wire, ethernet header was removed by device driver. @@ -372,7 +622,12 @@ DECLINLINE(void) vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff * */ skb_push(pBuf, ETH_HLEN); } - pSG->cbTotal = pBuf->len; + + if (!pGsoCtx) + IntNetSgInitTempSegs(pSG, pBuf->len, cSegs, 0 /*cSegsUsed*/); + else + IntNetSgInitTempSegsGso(pSG, pBuf->len, cSegs, 0 /*cSegsUsed*/, pGsoCtx); + #ifdef VBOXNETFLT_SG_SUPPORT pSG->aSegs[0].cb = skb_headlen(pBuf); pSG->aSegs[0].pv = pBuf->data; @@ -386,14 +641,16 @@ DECLINLINE(void) vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff * printk("%p = kmap()\n", pSG->aSegs[i+1].pv); pSG->aSegs[i+1].Phys = NIL_RTHCPHYS; } - pSG->cSegsUsed = ++i; + ++i; + #else pSG->aSegs[0].cb = pBuf->len; pSG->aSegs[0].pv = pBuf->data; pSG->aSegs[0].Phys = NIL_RTHCPHYS; - pSG->cSegsUsed = i = 1; + i = 1; #endif + pSG->cSegsUsed = i; #ifdef PADD_RUNT_FRAMES_FROM_HOST /* @@ -414,8 +671,10 @@ DECLINLINE(void) vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff * pSG->aSegs[i].cb = 60 - pSG->cbTotal; pSG->cbTotal = 60; pSG->cSegsUsed++; + Assert(i + 1 <= pSG->cSegsAlloc) } #endif + Log4(("vboxNetFltLinuxSkBufToSG: allocated=%d, segments=%d frags=%d next=%p frag_list=%p pkt_type=%x fSrc=%x\n", pSG->cSegsAlloc, pSG->cSegsUsed, skb_shinfo(pBuf)->nr_frags, pBuf->next, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type, fSrc)); for (i = 0; i < pSG->cSegsUsed; i++) @@ -490,26 +749,38 @@ static int vboxNetFltLinuxPacketHandler(struct sk_buff *pBuf, return 0; } pBuf = pCopy; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) Log3(("vboxNetFltLinuxPacketHandler: skb copy len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n", pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type)); -#else +# else Log3(("vboxNetFltLinuxPacketHandler: skb copy len=%u data_len=%u truesize=%u next=%p nr_frags=%u tso_size=%u tso_seqs=%u frag_list=%p pkt_type=%x\n", pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->tso_size, skb_shinfo(pBuf)->tso_segs, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type)); -#endif +# endif } #endif +#ifdef VBOXNETFLT_LINUX_NO_XMIT_QUEUE + /* Forward it to the internal network. */ + vboxNetFltLinuxForwardToIntNet(pThis, pBuf); +#else /* Add the packet to transmit queue and schedule the bottom half. */ skb_queue_tail(&pThis->u.s.XmitQueue, pBuf); schedule_work(&pThis->u.s.XmitTask); Log4(("vboxNetFltLinuxPacketHandler: scheduled work %p for sk_buff %p\n", &pThis->u.s.XmitTask, pBuf)); +#endif + /* It does not really matter what we return, it is ignored by the kernel. */ return 0; } -static unsigned vboxNetFltLinuxSGSegments(PVBOXNETFLTINS pThis, struct sk_buff *pBuf) +/** + * Calculate the number of INTNETSEG segments the socket buffer will need. + * + * @returns Segment count. + * @param pBuf The socket buffer. + */ +DECLINLINE(unsigned) vboxNetFltLinuxCalcSGSegments(struct sk_buff *pBuf) { #ifdef VBOXNETFLT_SG_SUPPORT unsigned cSegs = 1 + skb_shinfo(pBuf)->nr_frags; @@ -517,17 +788,18 @@ static unsigned vboxNetFltLinuxSGSegments(PVBOXNETFLTINS pThis, struct sk_buff * unsigned cSegs = 1; #endif #ifdef PADD_RUNT_FRAMES_FROM_HOST - /* - * Add a trailer if the frame is too small. - */ + /* vboxNetFltLinuxSkBufToSG adds a padding segment if it's a runt. */ if (pBuf->len < 60) cSegs++; #endif return cSegs; } -/* WARNING! This function should only be called after vboxNetFltLinuxSkBufToSG()! */ -static void vboxNetFltLinuxDestroySG(struct sk_buff *pBuf, PINTNETSG pSG) +/** + * Destroy the intnet scatter / gather buffer created by + * vboxNetFltLinuxSkBufToSG. + */ +static void vboxNetFltLinuxDestroySG(PINTNETSG pSG) { #ifdef VBOXNETFLT_SG_SUPPORT int i; @@ -541,9 +813,10 @@ static void vboxNetFltLinuxDestroySG(struct sk_buff *pBuf, PINTNETSG pSG) NOREF(pSG); } -#ifndef LOG_ENABLED -#define vboxNetFltDumpPacket(a, b, c, d) -#else +#ifdef LOG_ENABLED +/** + * Logging helper. + */ static void vboxNetFltDumpPacket(PINTNETSG pSG, bool fEgress, const char *pszWhere, int iIncrement) { uint8_t *pInt, *pExt; @@ -567,23 +840,275 @@ static void vboxNetFltDumpPacket(PINTNETSG pSG, bool fEgress, const char *pszWhe pSG->cbTotal, iPacketNo)); Log3(("%.*Rhxd\n", pSG->aSegs[0].cb, pSG->aSegs[0].pv)); } +#else +# define vboxNetFltDumpPacket(a, b, c, d) do {} while (0) #endif +#ifdef VBOXNETFLT_WITH_GSO_RECV + +/** + * Worker for vboxNetFltLinuxForwardToIntNet that checks if we can forwards a + * GSO socket buffer without having to segment it. + * + * @returns true on success, false if needs segmenting. + * @param pThis The net filter instance. + * @param pSkb The GSO socket buffer. + * @param fSrc The source. + * @param pGsoCtx Where to return the GSO context on success. + */ +static bool vboxNetFltLinuxCanForwardAsGso(PVBOXNETFLTINS pThis, struct sk_buff *pSkb, uint32_t fSrc, + PPDMNETWORKGSO pGsoCtx) +{ + PDMNETWORKGSOTYPE enmGsoType; + uint16_t uEtherType; + unsigned int cbTransport; + unsigned int offTransport; + unsigned int cbTransportHdr; + unsigned uProtocol; + union + { + RTNETIPV4 IPv4; + RTNETIPV6 IPv6; + RTNETTCP Tcp; + uint8_t ab[40]; + uint16_t au16[40/2]; + uint32_t au32[40/4]; + } Buf; + + /* + * Check the GSO properties of the socket buffer and make sure it fits. + */ + /** @todo Figure out how to handle SKB_GSO_TCP_ECN! */ + if (RT_UNLIKELY( skb_shinfo(pSkb)->gso_type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_TCPV6 | SKB_GSO_TCPV4) )) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: gso_type=%#x\n", skb_shinfo(pSkb)->gso_type)); + return false; + } + if (RT_UNLIKELY( skb_shinfo(pSkb)->gso_size < 1 + || pSkb->len > VBOX_MAX_GSO_SIZE )) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: gso_size=%#x skb_len=%#x (max=%#x)\n", skb_shinfo(pSkb)->gso_size, pSkb->len, VBOX_MAX_GSO_SIZE)); + return false; + } + if (RT_UNLIKELY(fSrc & INTNETTRUNKDIR_WIRE)) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: fSrc=wire\n")); + return false; + } + + /* + * skb_gso_segment does the following. Do we need to do it as well? + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + skb_reset_mac_header(pSkb); + pSkb->mac_len = pSkb->network_header - pSkb->mac_header; +#else + pSkb->mac.raw = pSkb->data; + pSkb->mac_len = pSkb->nh.raw - pSkb->data; +#endif + + /* + * Switch on the ethertype. + */ + uEtherType = pSkb->protocol; + if ( uEtherType == RT_H2N_U16_C(RTNET_ETHERTYPE_VLAN) + && pSkb->mac_len == sizeof(RTNETETHERHDR) + sizeof(uint32_t)) + { + uint16_t const *puEtherType = skb_header_pointer(pSkb, sizeof(RTNETETHERHDR) + sizeof(uint16_t), sizeof(uint16_t), &Buf); + if (puEtherType) + uEtherType = *puEtherType; + } + switch (uEtherType) + { + case RT_H2N_U16_C(RTNET_ETHERTYPE_IPV4): + { + unsigned int cbHdr; + PCRTNETIPV4 pIPv4 = (PCRTNETIPV4)skb_header_pointer(pSkb, pSkb->mac_len, sizeof(Buf.IPv4), &Buf); + if (RT_UNLIKELY(!pIPv4)) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: failed to access IPv4 hdr\n")); + return false; + } + + cbHdr = pIPv4->ip_hl * 4; + cbTransport = RT_N2H_U16(pIPv4->ip_len); + if (RT_UNLIKELY( cbHdr < RTNETIPV4_MIN_LEN + || cbHdr > cbTransport )) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: invalid IPv4 lengths: ip_hl=%u ip_len=%u\n", pIPv4->ip_hl, RT_N2H_U16(pIPv4->ip_len))); + return false; + } + cbTransport -= cbHdr; + offTransport = pSkb->mac_len + cbHdr; + uProtocol = pIPv4->ip_p; + if (uProtocol == RTNETIPV4_PROT_TCP) + enmGsoType = PDMNETWORKGSOTYPE_IPV4_TCP; + else if (uProtocol == RTNETIPV4_PROT_UDP) + enmGsoType = PDMNETWORKGSOTYPE_IPV4_UDP; + else /** @todo IPv6: 4to6 tunneling */ + enmGsoType = PDMNETWORKGSOTYPE_INVALID; + break; + } + + case RT_H2N_U16_C(RTNET_ETHERTYPE_IPV6): + { + PCRTNETIPV6 pIPv6 = (PCRTNETIPV6)skb_header_pointer(pSkb, pSkb->mac_len, sizeof(Buf.IPv6), &Buf); + if (RT_UNLIKELY(!pIPv6)) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: failed to access IPv6 hdr\n")); + return false; + } + + cbTransport = RT_N2H_U16(pIPv6->ip6_plen); + offTransport = pSkb->mac_len + sizeof(RTNETIPV6); + uProtocol = pIPv6->ip6_nxt; + /** @todo IPv6: Dig our way out of the other headers. */ + if (uProtocol == RTNETIPV4_PROT_TCP) + enmGsoType = PDMNETWORKGSOTYPE_IPV6_TCP; + else if (uProtocol == RTNETIPV4_PROT_UDP) + enmGsoType = PDMNETWORKGSOTYPE_IPV4_UDP; + else + enmGsoType = PDMNETWORKGSOTYPE_INVALID; + break; + } + + default: + Log5(("vboxNetFltLinuxCanForwardAsGso: uEtherType=%#x\n", RT_H2N_U16(uEtherType))); + return false; + } + + if (enmGsoType == PDMNETWORKGSOTYPE_INVALID) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: Unsupported protocol %d\n", uProtocol)); + return false; + } + + if (RT_UNLIKELY( offTransport + cbTransport <= offTransport + || offTransport + cbTransport > pSkb->len + || cbTransport < (uProtocol == RTNETIPV4_PROT_TCP ? RTNETTCP_MIN_LEN : RTNETUDP_MIN_LEN)) ) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: Bad transport length; off=%#x + cb=%#x => %#x; skb_len=%#x (%s)\n", + offTransport, cbTransport, offTransport + cbTransport, pSkb->len, PDMNetGsoTypeName(enmGsoType) )); + return false; + } + + /* + * Check the TCP/UDP bits. + */ + if (uProtocol == RTNETIPV4_PROT_TCP) + { + PCRTNETTCP pTcp = (PCRTNETTCP)skb_header_pointer(pSkb, offTransport, sizeof(Buf.Tcp), &Buf); + if (RT_UNLIKELY(!pTcp)) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: failed to access TCP hdr\n")); + return false; + } + + cbTransportHdr = pTcp->th_off * 4; + if (RT_UNLIKELY( cbTransportHdr < RTNETTCP_MIN_LEN + || cbTransportHdr > cbTransport + || offTransport + cbTransportHdr >= UINT8_MAX + || offTransport + cbTransportHdr >= pSkb->len )) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: No space for TCP header; off=%#x cb=%#x skb_len=%#x\n", offTransport, cbTransportHdr, pSkb->len)); + return false; + } + + } + else + { + Assert(uProtocol == RTNETIPV4_PROT_UDP); + cbTransportHdr = sizeof(RTNETUDP); + if (RT_UNLIKELY( offTransport + cbTransportHdr >= UINT8_MAX + || offTransport + cbTransportHdr >= pSkb->len )) + { + Log5(("vboxNetFltLinuxCanForwardAsGso: No space for UDP header; off=%#x skb_len=%#x\n", offTransport, pSkb->len)); + return false; + } + } + + /* + * We're good, init the GSO context. + */ + pGsoCtx->u8Type = enmGsoType; + pGsoCtx->cbHdrs = offTransport + cbTransportHdr; + pGsoCtx->cbMaxSeg = skb_shinfo(pSkb)->gso_size; + pGsoCtx->offHdr1 = pSkb->mac_len; + pGsoCtx->offHdr2 = offTransport; + pGsoCtx->au8Unused[0] = 0; + pGsoCtx->au8Unused[1] = 0; + + return true; +} + +/** + * Forward the socket buffer as a GSO internal network frame. + * + * @returns IPRT status code. + * @param pThis The net filter instance. + * @param pSkb The GSO socket buffer. + * @param fSrc The source. + * @param pGsoCtx Where to return the GSO context on success. + */ +static int vboxNetFltLinuxForwardAsGso(PVBOXNETFLTINS pThis, struct sk_buff *pSkb, uint32_t fSrc, PCPDMNETWORKGSO pGsoCtx) +{ + int rc; + unsigned cSegs = vboxNetFltLinuxCalcSGSegments(pSkb); + if (RT_LIKELY(cSegs <= MAX_SKB_FRAGS + 1)) + { + PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); + if (RT_LIKELY(pSG)) + { + vboxNetFltLinuxSkBufToSG(pThis, pSkb, pSG, cSegs, fSrc, pGsoCtx); + + vboxNetFltDumpPacket(pSG, false, (fSrc & INTNETTRUNKDIR_HOST) ? "host" : "wire", 1); + pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc); + + vboxNetFltLinuxDestroySG(pSG); + rc = VINF_SUCCESS; + } + else + { + Log(("VBoxNetFlt: Dropping the sk_buff (failure case).\n")); + rc = VERR_NO_MEMORY; + } + } + else + { + Log(("VBoxNetFlt: Bad sk_buff? cSegs=%#x.\n", cSegs)); + rc = VERR_INTERNAL_ERROR_3; + } + + Log4(("VBoxNetFlt: Dropping the sk_buff.\n")); + dev_kfree_skb(pSkb); + return rc; +} + +#endif /* VBOXNETFLT_WITH_GSO_RECV */ + +/** + * Worker for vboxNetFltLinuxForwardToIntNet. + * + * @returns VINF_SUCCESS or VERR_NO_MEMORY. + * @param pThis The net filter instance. + * @param pBuf The socket buffer. + * @param fSrc The source. + */ static int vboxNetFltLinuxForwardSegment(PVBOXNETFLTINS pThis, struct sk_buff *pBuf, uint32_t fSrc) { - int rc; - unsigned cSegs = vboxNetFltLinuxSGSegments(pThis, pBuf); - if (cSegs < MAX_SKB_FRAGS) + int rc; + unsigned cSegs = vboxNetFltLinuxCalcSGSegments(pBuf); + if (cSegs <= MAX_SKB_FRAGS + 1) { PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); if (RT_LIKELY(pSG)) { - vboxNetFltLinuxSkBufToSG(pThis, pBuf, pSG, cSegs, fSrc); + vboxNetFltLinuxSkBufToSG(pThis, pBuf, pSG, cSegs, fSrc, NULL /*pGsoCtx*/); vboxNetFltDumpPacket(pSG, false, (fSrc & INTNETTRUNKDIR_HOST) ? "host" : "wire", 1); pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc); - vboxNetFltLinuxDestroySG(pBuf, pSG); + vboxNetFltLinuxDestroySG(pSG); rc = VINF_SUCCESS; } else @@ -603,39 +1128,50 @@ static int vboxNetFltLinuxForwardSegment(PVBOXNETFLTINS pThis, struct sk_buff *p return rc; } +/** + * + * @param pBuf The socket buffer. This is consumed by this function. + */ static void vboxNetFltLinuxForwardToIntNet(PVBOXNETFLTINS pThis, struct sk_buff *pBuf) { uint32_t fSrc = pBuf->pkt_type == PACKET_OUTGOING ? INTNETTRUNKDIR_HOST : INTNETTRUNKDIR_WIRE; - if (VBOX_SKB_IS_GSO(pBuf)) +#ifdef VBOXNETFLT_WITH_GSO + if (skb_is_gso(pBuf)) { - /* Need to segment the packet */ - struct sk_buff *pNext, *pSegment; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - Log3(("vboxNetFltLinuxForwardToIntNet: skb len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x ip_summed=%d\n", - pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type, pBuf->ip_summed)); -#endif - - pSegment = VBOX_SKB_GSO_SEGMENT(pBuf); - if (IS_ERR(pSegment)) + PDMNETWORKGSO GsoCtx; + Log3(("vboxNetFltLinuxForwardToIntNet: skb len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x ip_summed=%d\n", + pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type, pBuf->ip_summed)); +# ifdef VBOXNETFLT_WITH_GSO_RECV + if ( (skb_shinfo(pBuf)->gso_type & (SKB_GSO_UDP | SKB_GSO_TCPV6 | SKB_GSO_TCPV4)) + && vboxNetFltLinuxCanForwardAsGso(pThis, pBuf, fSrc, &GsoCtx) ) + vboxNetFltLinuxForwardAsGso(pThis, pBuf, fSrc, &GsoCtx); + else +# endif { + /* Need to segment the packet */ + struct sk_buff *pNext; + struct sk_buff *pSegment = skb_gso_segment(pBuf, 0 /*supported features*/); + if (IS_ERR(pSegment)) + { + dev_kfree_skb(pBuf); + LogRel(("VBoxNetFlt: Failed to segment a packet (%d).\n", PTR_ERR(pSegment))); + return; + } + + for (; pSegment; pSegment = pNext) + { + Log3(("vboxNetFltLinuxForwardToIntNet: segment len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n", + pSegment->len, pSegment->data_len, pSegment->truesize, pSegment->next, skb_shinfo(pSegment)->nr_frags, skb_shinfo(pSegment)->gso_size, skb_shinfo(pSegment)->gso_segs, skb_shinfo(pSegment)->gso_type, skb_shinfo(pSegment)->frag_list, pSegment->pkt_type)); + pNext = pSegment->next; + pSegment->next = 0; + vboxNetFltLinuxForwardSegment(pThis, pSegment, fSrc); + } dev_kfree_skb(pBuf); - LogRel(("VBoxNetFlt: Failed to segment a packet (%d).\n", PTR_ERR(pBuf))); - return; - } - for (; pSegment; pSegment = pNext) - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - Log3(("vboxNetFltLinuxForwardToIntNet: segment len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n", - pSegment->len, pSegment->data_len, pSegment->truesize, pSegment->next, skb_shinfo(pSegment)->nr_frags, skb_shinfo(pSegment)->gso_size, skb_shinfo(pSegment)->gso_segs, skb_shinfo(pSegment)->gso_type, skb_shinfo(pSegment)->frag_list, pSegment->pkt_type)); -#endif - pNext = pSegment->next; - pSegment->next = 0; - vboxNetFltLinuxForwardSegment(pThis, pSegment, fSrc); } - dev_kfree_skb(pBuf); } else +#endif /* VBOXNETFLT_WITH_GSO */ { if (pBuf->ip_summed == CHECKSUM_PARTIAL && pBuf->pkt_type == PACKET_OUTGOING) { @@ -663,43 +1199,116 @@ static void vboxNetFltLinuxForwardToIntNet(PVBOXNETFLTINS pThis, struct sk_buff } vboxNetFltLinuxForwardSegment(pThis, pBuf, fSrc); } - /* - * Create a (scatter/)gather list for the sk_buff and feed it to the internal network. - */ } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +#ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE +/** + * Work queue handler that forwards the socket buffers queued by + * vboxNetFltLinuxPacketHandler to the internal network. + * + * @param pWork The work queue. + */ +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) static void vboxNetFltLinuxXmitTask(struct work_struct *pWork) -#else +# else static void vboxNetFltLinuxXmitTask(void *pWork) -#endif +# endif { + PVBOXNETFLTINS pThis = VBOX_FLT_XT_TO_INST(pWork); struct sk_buff *pBuf; - bool fActive; - PVBOXNETFLTINS pThis; - RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; Log4(("vboxNetFltLinuxXmitTask: Got work %p.\n", pWork)); - pThis = VBOX_FLT_XT_TO_INST(pWork); + /* * Active? Retain the instance and increment the busy counter. */ - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); - fActive = ASMAtomicUoReadBool(&pThis->fActive); - if (fActive) - vboxNetFltRetain(pThis, true /* fBusy */); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); - if (!fActive) - return; + if (vboxNetFltTryRetainBusyActive(pThis)) + { + while ((pBuf = skb_dequeue(&pThis->u.s.XmitQueue)) != NULL) + vboxNetFltLinuxForwardToIntNet(pThis, pBuf); - while ((pBuf = skb_dequeue(&pThis->u.s.XmitQueue)) != 0) - vboxNetFltLinuxForwardToIntNet(pThis, pBuf); + vboxNetFltRelease(pThis, true /* fBusy */); + } + else + { + /** @todo Shouldn't we just drop the packets here? There is little point in + * making them accumulate when the VM is paused and it'll only waste + * kernel memory anyway... Hmm. maybe wait a short while (2-5 secs) + * before start draining the packets (goes for the intnet ring buf + * too)? */ + } +} +#endif /* !VBOXNETFLT_LINUX_NO_XMIT_QUEUE */ + +/** + * Reports the GSO capabilites of the hardware NIC. + * + * @param pThis The net filter instance. The caller hold a + * reference to this. + */ +static void vboxNetFltLinuxReportNicGsoCapabilities(PVBOXNETFLTINS pThis) +{ +#ifdef VBOXNETFLT_WITH_GSO_XMIT_WIRE + if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + struct net_device *pDev; + PINTNETTRUNKSWPORT pSwitchPort; + unsigned int fFeatures; + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + + pSwitchPort = pThis->pSwitchPort; /* this doesn't need to be here, but it doesn't harm. */ + pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); + if (pDev) + fFeatures = pDev->features; + else + fFeatures = 0; + + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); + + if (pThis->pSwitchPort) + { + /* Set/update the GSO capabilities of the NIC. */ + uint32_t fGsoCapabilites = 0; + if (fFeatures & NETIF_F_TSO) + fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_TCP); + if (fFeatures & NETIF_F_TSO6) + fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_TCP); +# if 0 /** @todo GSO: Test UDP offloading (UFO) on linux. */ + if (fFeatures & NETIF_F_UFO) + fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_UDP); + if (fFeatures & NETIF_F_UFO) + fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_UDP); +# endif + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, fGsoCapabilites, INTNETTRUNKDIR_WIRE); + } + + vboxNetFltRelease(pThis, true /*fBusy*/); + } +#endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE */ +} - vboxNetFltRelease(pThis, true /* fBusy */); +/** + * Helper that determins whether the host (ignoreing us) is operating the + * interface in promiscuous mode or not. + */ +static bool vboxNetFltLinuxPromiscuous(PVBOXNETFLTINS pThis) +{ + bool fRc = false; + struct net_device * pDev = vboxNetFltLinuxRetainNetDev(pThis); + if (pDev) + { + fRc = !!(pDev->promiscuity - (ASMAtomicUoReadBool(&pThis->u.s.fPromiscuousSet) & 1)); + LogFlow(("vboxNetFltPortOsIsPromiscuous: returns %d, pDev->promiscuity=%d, fPromiscuousSet=%d\n", + fRc, pDev->promiscuity, pThis->u.s.fPromiscuousSet)); + vboxNetFltLinuxReleaseNetDev(pThis, pDev); + } + return fRc; } /** - * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered. + * Internal worker for vboxNetFltLinuxNotifierCallback. * * @returns VBox status code. * @param pThis The instance. @@ -708,35 +1317,41 @@ static void vboxNetFltLinuxXmitTask(void *pWork) */ static int vboxNetFltLinuxAttachToInterface(PVBOXNETFLTINS pThis, struct net_device *pDev) { - struct packet_type *pt; RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - LogFlow(("vboxNetFltLinuxAttachToInterface: pThis=%p (%s)\n", pThis, pThis->szName)); - if (!pDev) - { - Log(("VBoxNetFlt: failed to find device '%s'\n", pThis->szName)); - return VERR_INTNET_FLT_IF_NOT_FOUND; - } - + /* + * Retain and store the device. + */ dev_hold(pDev); - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, pDev); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); Log(("vboxNetFltLinuxAttachToInterface: Device %p(%s) retained. ref=%d\n", pDev, pDev->name, atomic_read(&pDev->refcnt))); Log(("vboxNetFltLinuxAttachToInterface: Got pDev=%p pThis=%p pThis->u.s.pDev=%p\n", pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev))); + + /* Get the mac address while we still have a valid net_device reference. */ + memcpy(&pThis->u.s.MacAddr, pDev->dev_addr, sizeof(pThis->u.s.MacAddr)); + /* - * Get the mac address while we still have a valid ifnet reference. + * Install a packet filter for this device with a protocol wildcard (ETH_P_ALL). */ - memcpy(&pThis->u.s.Mac, pDev->dev_addr, sizeof(pThis->u.s.Mac)); + pThis->u.s.PacketType.type = __constant_htons(ETH_P_ALL); + pThis->u.s.PacketType.dev = pDev; + pThis->u.s.PacketType.func = vboxNetFltLinuxPacketHandler; + dev_add_pack(&pThis->u.s.PacketType); - pt = &pThis->u.s.PacketType; - pt->type = __constant_htons(ETH_P_ALL); - pt->dev = pDev; - pt->func = vboxNetFltLinuxPacketHandler; - dev_add_pack(pt); - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); +#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT + vboxNetFltLinuxHookDev(pThis, pDev); +#endif + + /* + * Set indicators that require the spinlock. Be abit paranoid about racing + * the device notification handle. + */ + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); if (pDev) { @@ -744,20 +1359,38 @@ static int vboxNetFltLinuxAttachToInterface(PVBOXNETFLTINS pThis, struct net_dev ASMAtomicUoWriteBool(&pThis->u.s.fRegistered, true); pDev = NULL; /* don't dereference it */ } - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); Log(("vboxNetFltLinuxAttachToInterface: this=%p: Packet handler installed.\n", pThis)); - /* Release the interface on failure. */ - if (pDev) + /* + * If the above succeeded report GSO capabilites, if not undo and + * release the device. + */ + if (!pDev) + { + Assert(pThis->pSwitchPort); + if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + vboxNetFltLinuxReportNicGsoCapabilities(pThis); + pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); + pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltLinuxPromiscuous(pThis)); + pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); + vboxNetFltRelease(pThis, true /*fBusy*/); + } + } + else { - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); +#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT + vboxNetFltLinuxUnhookDev(pThis, pDev); +#endif + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, NULL); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); dev_put(pDev); Log(("vboxNetFltLinuxAttachToInterface: Device %p(%s) released. ref=%d\n", pDev, pDev->name, atomic_read(&pDev->refcnt))); } - LogRel(("VBoxNetFlt: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.Mac), &pThis->u.s.Mac)); + LogRel(("VBoxNetFlt: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); return VINF_SUCCESS; } @@ -767,14 +1400,21 @@ static int vboxNetFltLinuxUnregisterDevice(PVBOXNETFLTINS pThis, struct net_devi RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; Assert(!pThis->fDisconnectedFromHost); - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); + +#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT + vboxNetFltLinuxUnhookDev(pThis, pDev); +#endif + + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); ASMAtomicWriteBool(&pThis->u.s.fRegistered, false); ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true); ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, NULL); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); dev_remove_pack(&pThis->u.s.PacketType); +#ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE skb_queue_purge(&pThis->u.s.XmitQueue); +#endif Log(("vboxNetFltLinuxUnregisterDevice: this=%p: Packet handler removed, xmit queue purged.\n", pThis)); Log(("vboxNetFltLinuxUnregisterDevice: Device %p(%s) released. ref=%d\n", pDev, pDev->name, atomic_read(&pDev->refcnt))); dev_put(pDev); @@ -785,15 +1425,16 @@ static int vboxNetFltLinuxUnregisterDevice(PVBOXNETFLTINS pThis, struct net_devi static int vboxNetFltLinuxDeviceIsUp(PVBOXNETFLTINS pThis, struct net_device *pDev) { /* Check if we are not suspended and promiscuous mode has not been set. */ - if (ASMAtomicUoReadBool(&pThis->fActive) && !ASMAtomicUoReadBool(&pThis->u.s.fPromiscuousSet)) + if ( pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE + && !ASMAtomicUoReadBool(&pThis->u.s.fPromiscuousSet)) { /* Note that there is no need for locking as the kernel got hold of the lock already. */ dev_set_promiscuity(pDev, 1); ASMAtomicWriteBool(&pThis->u.s.fPromiscuousSet, true); - Log(("vboxNetFltLinuxDeviceIsUp: enabled promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pDev))); + Log(("vboxNetFltLinuxDeviceIsUp: enabled promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity)); } else - Log(("vboxNetFltLinuxDeviceIsUp: no need to enable promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pDev))); + Log(("vboxNetFltLinuxDeviceIsUp: no need to enable promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity)); return NOTIFY_OK; } @@ -805,24 +1446,18 @@ static int vboxNetFltLinuxDeviceGoingDown(PVBOXNETFLTINS pThis, struct net_devic /* Note that there is no need for locking as the kernel got hold of the lock already. */ dev_set_promiscuity(pDev, -1); ASMAtomicWriteBool(&pThis->u.s.fPromiscuousSet, false); - Log(("vboxNetFltLinuxDeviceGoingDown: disabled promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pDev))); + Log(("vboxNetFltLinuxDeviceGoingDown: disabled promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity)); } else - Log(("vboxNetFltLinuxDeviceGoingDown: no need to disable promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pDev))); + Log(("vboxNetFltLinuxDeviceGoingDown: no need to disable promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity)); return NOTIFY_OK; } -static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr) - +#ifdef LOG_ENABLED +/** Stringify the NETDEV_XXX constants. */ +static const char *vboxNetFltLinuxGetNetDevEventName(unsigned long ulEventType) { - int rc = NOTIFY_OK; -#ifdef DEBUG - char *pszEvent = "<unknown>"; -#endif - struct net_device *pDev = (struct net_device *)ptr; - PVBOXNETFLTINS pThis = VBOX_FLT_NB_TO_INST(self); - -#ifdef DEBUG + const char *pszEvent = "NETDRV_<unknown>"; switch (ulEventType) { case NETDEV_REGISTER: pszEvent = "NETDEV_REGISTER"; break; @@ -835,33 +1470,64 @@ static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned case NETDEV_CHANGEMTU: pszEvent = "NETDEV_CHANGEMTU"; break; case NETDEV_CHANGEADDR: pszEvent = "NETDEV_CHANGEADDR"; break; case NETDEV_GOING_DOWN: pszEvent = "NETDEV_GOING_DOWN"; break; +# ifdef NETDEV_FEAT_CHANGE + case NETDEV_FEAT_CHANGE: pszEvent = "NETDEV_FEAT_CHANGE"; break; +# endif } + return pszEvent; +} +#endif /* LOG_ENABLED */ + +/** + * Callback for listening to netdevice events. + * + * This works the rediscovery, clean up on unregistration, promiscuity on + * up/down, and GSO feature changes from ethtool. + * + * @returns NOTIFY_OK + * @param self Pointer to our notifier registration block. + * @param ulEventType The event. + * @param ptr Event specific, but it is usually the device it + * relates to. + */ +static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr) + +{ + PVBOXNETFLTINS pThis = VBOX_FLT_NB_TO_INST(self); + struct net_device *pDev = (struct net_device *)ptr; + int rc = NOTIFY_OK; + Log(("VBoxNetFlt: got event %s(0x%lx) on %s, pDev=%p pThis=%p pThis->u.s.pDev=%p\n", - pszEvent, ulEventType, pDev->name, pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev))); -#endif - if (ulEventType == NETDEV_REGISTER && !strcmp(pDev->name, pThis->szName)) + vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType, pDev->name, pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev))); + if ( ulEventType == NETDEV_REGISTER + && !strcmp(pDev->name, pThis->szName)) { vboxNetFltLinuxAttachToInterface(pThis, pDev); } else { pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); - if (pDev != ptr) - return NOTIFY_OK; - rc = NOTIFY_OK; - switch (ulEventType) + if (pDev == ptr) { - case NETDEV_UNREGISTER: - rc = vboxNetFltLinuxUnregisterDevice(pThis, pDev); - break; - case NETDEV_UP: - rc = vboxNetFltLinuxDeviceIsUp(pThis, pDev); - break; - case NETDEV_GOING_DOWN: - rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev); - break; - case NETDEV_CHANGENAME: - break; + switch (ulEventType) + { + case NETDEV_UNREGISTER: + rc = vboxNetFltLinuxUnregisterDevice(pThis, pDev); + break; + case NETDEV_UP: + rc = vboxNetFltLinuxDeviceIsUp(pThis, pDev); + break; + case NETDEV_GOING_DOWN: + rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev); + break; + case NETDEV_CHANGENAME: + break; +#ifdef NETDEV_FEAT_CHANGE + case NETDEV_FEAT_CHANGE: + vboxNetFltLinuxReportNicGsoCapabilities(pThis); + break; +#endif + } } } @@ -929,36 +1595,6 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) } -bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis) -{ - bool fRc = false; - struct net_device * pDev = vboxNetFltLinuxRetainNetDev(pThis); - if (pDev) - { - fRc = !!(pDev->promiscuity - (ASMAtomicUoReadBool(&pThis->u.s.fPromiscuousSet) & 1)); - LogFlow(("vboxNetFltPortOsIsPromiscuous: returns %d, pDev->promiscuity=%d, fPromiscuousSet=%d\n", - fRc, pDev->promiscuity, pThis->u.s.fPromiscuousSet)); - vboxNetFltLinuxReleaseNetDev(pThis, pDev); - } - return fRc; -} - - -void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac) -{ - *pMac = pThis->u.s.Mac; -} - - -bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) -{ - /* ASSUMES that the MAC address never changes. */ - return pThis->u.s.Mac.au16[0] == pMac->au16[0] - && pThis->u.s.Mac.au16[1] == pMac->au16[1] - && pThis->u.s.Mac.au16[2] == pMac->au16[2]; -} - - void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) { struct net_device * pDev; @@ -981,7 +1617,7 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) */ #ifdef LOG_ENABLED u_int16_t fIf; - unsigned const cPromiscBefore = VBOX_GET_PCOUNT(pDev); + unsigned const cPromiscBefore = pDev->promiscuity; #endif if (fActive) { @@ -991,7 +1627,7 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) dev_set_promiscuity(pDev, 1); rtnl_unlock(); pThis->u.s.fPromiscuousSet = true; - Log(("vboxNetFltPortOsSetActive: enabled promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pDev))); + Log(("vboxNetFltPortOsSetActive: enabled promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity)); } else { @@ -1000,13 +1636,13 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) rtnl_lock(); dev_set_promiscuity(pDev, -1); rtnl_unlock(); - Log(("vboxNetFltPortOsSetActive: disabled promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pDev))); + Log(("vboxNetFltPortOsSetActive: disabled promiscuous mode on %s (%d)\n", pThis->szName, pDev->promiscuity)); } pThis->u.s.fPromiscuousSet = false; #ifdef LOG_ENABLED fIf = dev_get_flags(pDev); - Log(("VBoxNetFlt: fIf=%#x; %d->%d\n", fIf, cPromiscBefore, VBOX_GET_PCOUNT(pDev))); + Log(("VBoxNetFlt: fIf=%#x; %d->%d\n", fIf, cPromiscBefore, pDev->promiscuity)); #endif } @@ -1024,25 +1660,55 @@ int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis) int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis) { - /* Nothing to do here. */ + /* + * Report the GSO capabilities of the host and device (if connected). + * Note! No need to mark ourselves busy here. + */ + /** @todo duplicate work here now? Attach */ +#if defined(VBOXNETFLT_WITH_GSO_XMIT_HOST) + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, + 0 + | RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_TCP) + | RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_TCP) +# if 0 /** @todo GSO: Test UDP offloading (UFO) on linux. */ + | RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_UDP) + | RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_UDP) +# endif + , INTNETTRUNKDIR_HOST); + +#endif + vboxNetFltLinuxReportNicGsoCapabilities(pThis); + return VINF_SUCCESS; } void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis) { - struct net_device *pDev; - bool fRegistered; - RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; + struct net_device *pDev; + bool fRegistered; + RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); +#ifdef VBOXNETFLT_WITH_FILTER_HOST2GUEST_SKBS_EXPERIMENT + vboxNetFltLinuxUnhookDev(pThis, NULL); +#endif + + /** @todo This code may race vboxNetFltLinuxUnregisterDevice (very very + * unlikely, but none the less). Since it doesn't actually update the + * state (just reads it), it is likely to panic in some interesting + * ways. */ + + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); fRegistered = ASMAtomicUoReadBool(&pThis->u.s.fRegistered); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); + if (fRegistered) { dev_remove_pack(&pThis->u.s.PacketType); +#ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE skb_queue_purge(&pThis->u.s.XmitQueue); +#endif Log(("vboxNetFltOsDeleteInstance: this=%p: Packet handler removed, xmit queue purged.\n", pThis)); Log(("vboxNetFltOsDeleteInstance: Device %p(%s) released. ref=%d\n", pDev, pDev->name, atomic_read(&pDev->refcnt))); dev_put(pDev); @@ -1086,11 +1752,13 @@ int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis) pThis->u.s.fRegistered = false; pThis->u.s.fPromiscuousSet = false; memset(&pThis->u.s.PacketType, 0, sizeof(pThis->u.s.PacketType)); +#ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE skb_queue_head_init(&pThis->u.s.XmitQueue); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) INIT_WORK(&pThis->u.s.XmitTask, vboxNetFltLinuxXmitTask); -#else +# else INIT_WORK(&pThis->u.s.XmitTask, vboxNetFltLinuxXmitTask, &pThis->u.s.XmitTask); +# endif #endif return VINF_SUCCESS; diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt index 7cf0de61a..cd2bef091 100755..100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt +++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt @@ -1,11 +1,11 @@ #!/bin/sh -# $Id: $ +# $Id: files_vboxnetflt 29250 2010-05-09 17:53:58Z vboxsync $ ## @file # Shared file between Makefile.kmk and export_modules # # -# Copyright (C) 2007 Sun Microsystems, Inc. +# Copyright (C) 2007-2010 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -15,15 +15,13 @@ # VirtualBox OSE distribution. VirtualBox OSE is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/include/iprt/alloc.h=>include/iprt/alloc.h \ ${PATH_ROOT}/include/iprt/alloca.h=>include/iprt/alloca.h \ ${PATH_ROOT}/include/iprt/asm.h=>include/iprt/asm.h \ + ${PATH_ROOT}/include/iprt/asm-amd64-x86.h=>include/iprt/asm-amd64-x86.h \ + ${PATH_ROOT}/include/iprt/asm-math.h=>include/iprt/asm-math.h \ ${PATH_ROOT}/include/iprt/assert.h=>include/iprt/assert.h \ ${PATH_ROOT}/include/iprt/avl.h=>include/iprt/avl.h \ ${PATH_ROOT}/include/iprt/cdefs.h=>include/iprt/cdefs.h \ @@ -36,6 +34,7 @@ VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/include/iprt/mem.h=>include/iprt/mem.h \ ${PATH_ROOT}/include/iprt/memobj.h=>include/iprt/memobj.h \ ${PATH_ROOT}/include/iprt/mp.h=>include/iprt/mp.h \ + ${PATH_ROOT}/include/iprt/net.h=>include/iprt/net.h \ ${PATH_ROOT}/include/iprt/param.h=>include/iprt/param.h \ ${PATH_ROOT}/include/iprt/power.h=>include/iprt/power.h \ ${PATH_ROOT}/include/iprt/process.h=>include/iprt/process.h \ @@ -54,6 +53,9 @@ VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/include/VBox/err.h=>include/VBox/err.h \ ${PATH_ROOT}/include/VBox/log.h=>include/VBox/log.h \ ${PATH_ROOT}/include/VBox/intnet.h=>include/VBox/intnet.h \ + ${PATH_ROOT}/include/VBox/intnetinline.h=>include/VBox/intnetinline.h \ + ${PATH_ROOT}/include/VBox/pdmnetinline.h=>include/VBox/pdmnetinline.h \ + ${PATH_ROOT}/include/VBox/param.h=>include/VBox/param.h \ ${PATH_ROOT}/include/VBox/stam.h=>include/VBox/stam.h \ ${PATH_ROOT}/include/VBox/sup.h=>include/VBox/sup.h \ ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ @@ -64,17 +66,15 @@ VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPR0IdcClient.c=>SUPR0IdcClient.c \ ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPR0IdcClientComponent.c=>SUPR0IdcClientComponent.c \ ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPR0IdcClientInternal.h=>SUPR0IdcClientInternal.h \ - ${PATH_ROOT}/src/VBox/HostDrivers/Support/linux/SUPR0IdcClient-linux.c=>SUPR0IdcClient-linux.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/linux/SUPR0IdcClient-linux.c=>linux/SUPR0IdcClient-linux.c \ ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/divdi3.c=>math/gcc/divdi3.c \ ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/moddi3.c=>math/gcc/moddi3.c \ ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>math/gcc/qdivrem.c \ ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>math/gcc/quad.h \ ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>math/gcc/udivdi3.c \ ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \ - ${PATH_ROOT}/src/VBox/Runtime/include/internal/initterm.h=>include/internal/initterm.h \ - ${PATH_ROOT}/src/VBox/Runtime/include/internal/iprt.h=>include/internal/iprt.h \ - ${PATH_ROOT}/src/VBox/Runtime/include/internal/magics.h=>include/internal/magics.h \ ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \ ${PATH_OUT}/version-generated.h=>version-generated.h \ + ${PATH_OUT}/product-generated.h=>product-generated.h \ " diff --git a/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c b/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c index ae86a5130..41a59ce57 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFlt-solaris.c $ */ +/* $Id: VBoxNetFlt-solaris.c 28961 2010-05-03 08:22:37Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Solaris Specific Code. */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /******************************************************************************* @@ -25,7 +21,7 @@ #define LOG_GROUP LOG_GROUP_NET_FLT_DRV #include <VBox/log.h> #include <VBox/err.h> -#include <VBox/cdefs.h> +#include <VBox/intnetinline.h> #include <VBox/version.h> #include <iprt/string.h> #include <iprt/initterm.h> @@ -97,10 +93,12 @@ #define DEVICE_DESC_MOD "VirtualBox NetMod" #if defined(DEBUG_ramshankar) +# undef LogFlowFunc +# define LogFlowFunc LogRel # undef Log -# define Log LogRel +# define Log LogRel # undef LogFlow -# define LogFlow LogRel +# define LogFlow LogRel #endif #ifdef VBOXNETFLT_SOLARIS_IPV6_POLLING @@ -274,10 +272,12 @@ static struct modlstrmod g_VBoxNetFltSolarisModule = */ static struct modlinkage g_VBoxNetFltSolarisModLinkage = { - MODREV_1, /* loadable module system revision */ - &g_VBoxNetFltSolarisDriver, /* streams driver framework */ - &g_VBoxNetFltSolarisModule, /* streams module framework */ - NULL /* terminate array of linkage structures */ + MODREV_1, /* loadable module system revision */ + { + &g_VBoxNetFltSolarisDriver, /* streams driver framework */ + &g_VBoxNetFltSolarisModule, /* streams module framework */ + NULL /* terminate array of linkage structures */ + } }; struct vboxnetflt_state_t; @@ -412,7 +412,7 @@ static int g_VBoxNetFltSolarisPollInterval = -1; */ int _init(void) { - LogFlow((DEVICE_NAME ":_init\n")); + LogFlowFunc((DEVICE_NAME ":_init\n")); /* * Prevent module autounloading. @@ -483,7 +483,7 @@ int _init(void) int _fini(void) { int rc; - LogFlow((DEVICE_NAME ":_fini\n")); + LogFlowFunc((DEVICE_NAME ":_fini\n")); /* * Undo the work done during start (in reverse order). @@ -519,7 +519,7 @@ int _fini(void) int _info(struct modinfo *pModInfo) { - LogFlow((DEVICE_NAME ":_info\n")); + LogFlowFunc((DEVICE_NAME ":_info\n")); int rc = mod_info(&g_VBoxNetFltSolarisModLinkage, pModInfo); @@ -538,7 +538,7 @@ int _info(struct modinfo *pModInfo) */ static int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) { - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd)); + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd)); switch (enmCmd) { @@ -578,8 +578,11 @@ static int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) /* Nothing to do here... */ return DDI_SUCCESS; } + + /* case DDI_PM_RESUME: */ + default: + return DDI_FAILURE; } - return DDI_FAILURE; } @@ -593,13 +596,12 @@ static int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) */ static int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) { - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd)); + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd)); switch (enmCmd) { case DDI_DETACH: { - int instance = ddi_get_instance(pDip); ddi_remove_minor_node(pDip, NULL); return DDI_SUCCESS; } @@ -609,8 +611,12 @@ static int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) /* Nothing to do here... */ return DDI_SUCCESS; } + + /* case DDI_PM_SUSPEND: */ + /* case DDI_HOT_PLUG_DETACH: */ + default: + return DDI_FAILURE; } - return DDI_FAILURE; } @@ -626,7 +632,7 @@ static int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) */ static int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppResult) { - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd, + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd, getminor((dev_t)pvArg))); switch (enmCmd) @@ -664,7 +670,7 @@ static int VBoxNetFltSolarisModOpen(queue_t *pQueue, dev_t *pDev, int fOpenMode, { Assert(pQueue); - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModOpen pQueue=%p pDev=%p fOpenMode=%d fStreamMode=%d\n", pQueue, pDev, + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisModOpen pQueue=%p pDev=%p fOpenMode=%d fStreamMode=%d\n", pQueue, pDev, fOpenMode, fStreamMode)); /* @@ -865,7 +871,7 @@ static int VBoxNetFltSolarisModClose(queue_t *pQueue, int fOpenMode, cred_t *pCr { Assert(pQueue); - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModClose pQueue=%p fOpenMode=%d\n", pQueue, fOpenMode)); + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisModClose pQueue=%p fOpenMode=%d\n", pQueue, fOpenMode)); vboxnetflt_stream_t *pStream = NULL; vboxnetflt_stream_t **ppPrevStream = NULL; @@ -978,7 +984,7 @@ static int VBoxNetFltSolarisModReadPut(queue_t *pQueue, mblk_t *pMsg) if (!pMsg) return 0; - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut pQueue=%p pMsg=%p\n", pQueue, pMsg)); + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisModReadPut pQueue=%p pMsg=%p\n", pQueue, pMsg)); bool fSendUpstream = true; vboxnetflt_stream_t *pStream = pQueue->q_ptr; @@ -1001,10 +1007,10 @@ static int VBoxNetFltSolarisModReadPut(queue_t *pQueue, mblk_t *pMsg) * the promiscuous OFF acknowledgement case). */ RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); - const bool fActive = ASMAtomicUoReadBool(&pThis->fActive); + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); + const bool fActive = pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE; vboxNetFltRetain(pThis, true /* fBusy */); - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pStream; @@ -1058,31 +1064,23 @@ static int VBoxNetFltSolarisModReadPut(queue_t *pQueue, mblk_t *pMsg) break; } - bcopy(pMsg->b_rptr + cOffset, &pThis->u.s.Mac, sizeof(pThis->u.s.Mac)); + bcopy(pMsg->b_rptr + cOffset, &pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_PHYS_ADDR. New Mac=%.*Rhxs\n", - sizeof(pThis->u.s.Mac), &pThis->u.s.Mac)); + sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); break; } case DL_NOTE_LINK_UP: { - const bool fDisconnected = ASMAtomicUoReadBool(&pThis->fActive); - if (fDisconnected) - { - ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, false); + if (ASMAtomicXchgBool(&pThis->fDisconnectedFromHost, false)) LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_LINK_UP.\n")); - } break; } case DL_NOTE_LINK_DOWN: { - const bool fDisconnected = ASMAtomicUoReadBool(&pThis->fActive); - if (!fDisconnected) - { - ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true); + if (!ASMAtomicXchgBool(&pThis->fDisconnectedFromHost, true)) LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_LINK_DOWN.\n")); - } break; } } @@ -1209,7 +1207,7 @@ static int VBoxNetFltSolarisModReadPut(queue_t *pQueue, mblk_t *pMsg) */ static int VBoxNetFltSolarisModWritePut(queue_t *pQueue, mblk_t *pMsg) { - LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut pQueue=%p pMsg=%p\n", pQueue, pMsg)); + LogFlowFunc((DEVICE_NAME ":VBoxNetFltSolarisModWritePut pQueue=%p pMsg=%p\n", pQueue, pMsg)); putnext(pQueue, pMsg); return 0; @@ -1224,7 +1222,7 @@ static int VBoxNetFltSolarisModWritePut(queue_t *pQueue, mblk_t *pMsg) */ static int vboxNetFltSolarisSetRawMode(vboxnetflt_promisc_stream_t *pPromiscStream) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisSetRawMode pPromiscStream=%p\n", pPromiscStream)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisSetRawMode pPromiscStream=%p\n", pPromiscStream)); mblk_t *pRawMsg = NULL; pRawMsg = mkiocb(DLIOCRAW); @@ -1253,7 +1251,7 @@ static int vboxNetFltSolarisSetRawMode(vboxnetflt_promisc_stream_t *pPromiscStre */ static int vboxNetFltSolarisSetFastMode(queue_t *pQueue) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisSetFastMode pQueue=%p\n", pQueue)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisSetFastMode pQueue=%p\n", pQueue)); mblk_t *pFastMsg = mkiocb(DL_IOC_HDR_INFO); if (RT_UNLIKELY(!pFastMsg)) @@ -1302,7 +1300,7 @@ static int vboxNetFltSolarisSetFastMode(queue_t *pQueue) */ static int vboxNetFltSolarisPromiscReq(queue_t *pQueue, bool fPromisc) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisPromiscReq pQueue=%p fPromisc=%d\n", pQueue, fPromisc)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisPromiscReq pQueue=%p fPromisc=%d\n", pQueue, fPromisc)); t_uscalar_t Cmd; size_t cbReq = 0; @@ -1354,7 +1352,7 @@ static int vboxNetFltSolarisPromiscReq(queue_t *pQueue, bool fPromisc) */ static int vboxNetFltSolarisPhysAddrReq(queue_t *pQueue) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisPhysAddrReq pQueue=%p\n", pQueue)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisPhysAddrReq pQueue=%p\n", pQueue)); t_uscalar_t Cmd = DL_PHYS_ADDR_REQ; size_t cbReq = DL_PHYS_ADDR_REQ_SIZE; @@ -1379,16 +1377,24 @@ static int vboxNetFltSolarisPhysAddrReq(queue_t *pQueue) */ static void vboxNetFltSolarisCachePhysAddr(PVBOXNETFLTINS pThis, mblk_t *pMsg) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr pThis=%p pMsg=%p\n", pThis, pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr pThis=%p pMsg=%p\n", pThis, pMsg)); AssertCompile(sizeof(RTMAC) == ETHERADDRL); dl_phys_addr_ack_t *pPhysAddrAck = (dl_phys_addr_ack_t *)pMsg->b_rptr; - if (pPhysAddrAck->dl_addr_length == sizeof(pThis->u.s.Mac)) + if (pPhysAddrAck->dl_addr_length == sizeof(pThis->u.s.MacAddr)) { - bcopy(pMsg->b_rptr + pPhysAddrAck->dl_addr_offset, &pThis->u.s.Mac, sizeof(pThis->u.s.Mac)); + bcopy(pMsg->b_rptr + pPhysAddrAck->dl_addr_offset, &pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); + + LogFlow((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr: DL_PHYS_ADDR_ACK: Mac=%.*Rhxs\n", + sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); - LogFlow((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr: DL_PHYS_ADDR_ACK: Mac=%.*Rhxs\n", sizeof(pThis->u.s.Mac), - &pThis->u.s.Mac)); + if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + Assert(pThis->pSwitchPort); + if (pThis->pSwitchPort) + pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); + vboxNetFltRelease(pThis, true /*fBusy*/); + } } else { @@ -1407,7 +1413,7 @@ static void vboxNetFltSolarisCachePhysAddr(PVBOXNETFLTINS pThis, mblk_t *pMsg) */ static int vboxNetFltSolarisBindReq(queue_t *pQueue, int SAP) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisBindReq SAP=%d\n", SAP)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisBindReq SAP=%d\n", SAP)); mblk_t *pBindMsg = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ); if (RT_UNLIKELY(!pBindMsg)) @@ -1433,7 +1439,7 @@ static int vboxNetFltSolarisBindReq(queue_t *pQueue, int SAP) */ static int vboxNetFltSolarisNotifyReq(queue_t *pQueue) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisNotifyReq\n")); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisNotifyReq\n")); mblk_t *pNotifyMsg = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO, DL_NOTIFY_REQ); if (RT_UNLIKELY(!pNotifyMsg)) @@ -1668,7 +1674,7 @@ static int vboxNetFltSolarisMuxIdToFd(vnode_t *pVNode, int MuxId, int *pFd) */ static int vboxNetFltSolarisRelinkIp4(vnode_t *pVNode, struct lifreq *pInterface, int IpMuxFd, int ArpMuxFd) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisRelinkIp4: pVNode=%p pInterface=%p IpMuxFd=%d ArpMuxFd=%d\n", pVNode, + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisRelinkIp4: pVNode=%p pInterface=%p IpMuxFd=%d ArpMuxFd=%d\n", pVNode, pInterface, IpMuxFd, ArpMuxFd)); int NewIpMuxId; @@ -1703,7 +1709,7 @@ static int vboxNetFltSolarisRelinkIp4(vnode_t *pVNode, struct lifreq *pInterface */ static int vboxNetFltSolarisRelinkIp6(vnode_t *pVNode, struct lifreq *pInterface, int Ip6MuxFd) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisRelinkIp6: pVNode=%p pInterface=%p Ip6MuxFd=%d\n", pVNode, pInterface, Ip6MuxFd)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisRelinkIp6: pVNode=%p pInterface=%p Ip6MuxFd=%d\n", pVNode, pInterface, Ip6MuxFd)); int NewIp6MuxId; int rc = strioctl(pVNode, I_PLINK, (intptr_t)Ip6MuxFd, 0, K_TO_K, kcred, &NewIp6MuxId); @@ -1732,7 +1738,7 @@ static int vboxNetFltSolarisRelinkIp6(vnode_t *pVNode, struct lifreq *pInterface */ static int vboxNetFltSolarisDetermineModPos(bool fAttach, vnode_t *pVNode, int *pModPos) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: fAttach=%d pVNode=%p pModPos=%p\n", fAttach, pVNode, pModPos)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: fAttach=%d pVNode=%p pModPos=%p\n", fAttach, pVNode, pModPos)); int cMod; int rc = strioctl(pVNode, I_LIST, (intptr_t)NULL, 0, K_TO_K, kcred, &cMod); @@ -1980,7 +1986,7 @@ static int vboxNetFltSolarisOpenStream(PVBOXNETFLTINS pThis) */ static void vboxNetFltSolarisCloseStream(PVBOXNETFLTINS pThis) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisCloseStream pThis=%p\n")); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisCloseStream pThis=%p\n")); if (pThis->u.s.hIface) { @@ -1999,7 +2005,7 @@ static void vboxNetFltSolarisCloseStream(PVBOXNETFLTINS pThis) */ static int vboxNetFltSolarisAttachIp4(PVBOXNETFLTINS pThis, bool fAttach) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp4 pThis=%p fAttach=%d\n", pThis, fAttach)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisAttachIp4 pThis=%p fAttach=%d\n", pThis, fAttach)); /* * Statuatory Warning: Hackish code ahead. @@ -2084,7 +2090,6 @@ static int vboxNetFltSolarisAttachIp4(PVBOXNETFLTINS pThis, bool fAttach) * We need to I_PUNLINK on these multiplexor IDs before we can start * operating on the lower stream as insertions are direct operations on the lower stream. */ - int ret; rc = strioctl(pUdp4VNode, I_PUNLINK, (intptr_t)Ip4Interface.lifr_ip_muxid, 0, K_TO_K, kcred, &ret); rc2 = strioctl(pUdp4VNode, I_PUNLINK, (intptr_t)Ip4Interface.lifr_arp_muxid, 0, K_TO_K, kcred, &ret); if ( !rc @@ -2267,7 +2272,7 @@ static int vboxNetFltSolarisAttachIp4(PVBOXNETFLTINS pThis, bool fAttach) */ static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp6 pThis=%p fAttach=%d\n", pThis, fAttach)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisAttachIp6 pThis=%p fAttach=%d\n", pThis, fAttach)); /* * Statuatory Warning: Hackish code ahead. @@ -2284,11 +2289,9 @@ static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach) StrMod.pos = -1; /* this is filled in later. */ int rc; - int rc2; int ret; ldi_ident_t DeviceIdent = ldi_ident_from_anon(); ldi_handle_t Ip6DevHandle; - ldi_handle_t Udp6DevHandle; /* * Open the IPv6 stream as a layered devices. @@ -2335,7 +2338,6 @@ static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach) * We need to I_PUNLINK on these multiplexor IDs before we can start * operating on the lower stream as insertions are direct operations on the lower stream. */ - int ret; rc = strioctl(pUdp6VNode, I_PUNLINK, (intptr_t)Ip6Interface.lifr_ip_muxid, 0, K_TO_K, kcred, &ret); if (!rc) { @@ -2422,7 +2424,7 @@ static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach) } } else - LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to find position. rc=%d rc2=%d\n", rc, rc2)); + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to find position. rc=%d\n", rc)); releasef(Ip6MuxFd); } @@ -2430,10 +2432,10 @@ static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach) LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get vnode from MuxFd.\n")); } else - LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to unlink upper stream rc=%d rc2=%d.\n", rc, rc2)); + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to unlink upper stream rc=%d.\n", rc)); } else - LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get MuxFd from MuxId. rc=%d rc2=%d\n", rc, rc2)); + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get MuxFd from MuxId. rc=%d\n", rc)); } else LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get Mux Ids. rc=%d\n", rc)); @@ -2467,7 +2469,7 @@ static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach) */ static void vboxNetFltSolarispIp6Timer(PRTTIMER pTimer, void *pvData, uint64_t iTick) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarispIp6Timer pTimer=%p pvData=%p\n", pTimer, pvData)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarispIp6Timer pTimer=%p pvData=%p\n", pTimer, pvData)); PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData; if ( RT_LIKELY(pThis) @@ -2506,7 +2508,7 @@ static void vboxNetFltSolarispIp6Timer(PRTTIMER pTimer, void *pvData, uint64_t i */ static int vboxNetFltSolarisSetupIp6Polling(PVBOXNETFLTINS pThis) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisSetupIp6Polling pThis=%p\n", pThis)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisSetupIp6Polling pThis=%p\n", pThis)); int rc = VERR_GENERAL_FAILURE; vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream); @@ -2558,7 +2560,7 @@ static int vboxNetFltSolarisSetupIp6Polling(PVBOXNETFLTINS pThis) */ static int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetachFromInterface pThis=%p\n", pThis)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisDetachFromInterface pThis=%p\n", pThis)); ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true); vboxNetFltSolarisCloseStream(pThis); @@ -2591,8 +2593,13 @@ static int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis) */ static int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface pThis=%p\n", pThis)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface pThis=%p\n", pThis)); + /* + * Since this is asynchronous streams injection, let the attach succeed before we can start + * processing the stream. + */ + ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true); int rc = vboxNetFltSolarisOpenStream(pThis); if (RT_SUCCESS(rc)) { @@ -2625,9 +2632,24 @@ static int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis) #endif /* + * Report promiscuousness and capabilities. + */ + if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + Assert(pThis->pSwitchPort); + /** @todo There is no easy way of obtaining the global host side promiscuous + * counter. Currently we just return false. */ + pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); + pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); + vboxNetFltRelease(pThis, true /*fBusy*/); + } + + /* * Ipv4 is successful, and maybe Ipv6, we're ready for transfers. */ ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, false); + return VINF_SUCCESS; } @@ -2649,7 +2671,7 @@ static int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis) */ static mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n", pThis, pSG)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n", pThis, pSG)); mblk_t *pMsg = allocb(pSG->cbTotal, BPRI_MED); if (RT_UNLIKELY(!pMsg)) @@ -2713,19 +2735,12 @@ static unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pM */ static int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs)); - - pSG->pvOwnerData = NULL; - pSG->pvUserData = NULL; - pSG->pvUserData2 = NULL; - pSG->cUsers = 1; - pSG->cbTotal = 0; - pSG->fFlags = INTNETSG_FLAGS_TEMP; - pSG->cSegsAlloc = cSegs; + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs)); /* - * Convert the message block to segments. + * Convert the message block to segments. Work INTNETSG::cbTotal. */ + IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/); mblk_t *pCur = pMsg; unsigned iSeg = 0; while (pCur) @@ -2755,6 +2770,7 @@ static int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNET pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal; pSG->cbTotal = 60; pSG->cSegsUsed++; + Assert(iSeg + 1 < cSegs); } #endif @@ -2776,7 +2792,7 @@ static int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNET */ static int vboxNetFltSolarisRawToUnitData(mblk_t *pMsg, mblk_t **ppDlpiMsg) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisRawToUnitData pMsg=%p\n", pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisRawToUnitData pMsg=%p\n", pMsg)); if (DB_TYPE(pMsg) != M_DATA) return VERR_NO_MEMORY; @@ -2828,7 +2844,7 @@ static int vboxNetFltSolarisRawToUnitData(mblk_t *pMsg, mblk_t **ppDlpiMsg) */ static int vboxNetFltSolarisUnitDataToRaw(PVBOXNETFLTINS pThis, mblk_t *pMsg, mblk_t **ppRawMsg) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisUnitDataToRaw pMsg=%p\n", pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisUnitDataToRaw pMsg=%p\n", pMsg)); if ( !pMsg->b_cont || DB_TYPE(pMsg) != M_PROTO) @@ -2868,7 +2884,7 @@ static int vboxNetFltSolarisUnitDataToRaw(PVBOXNETFLTINS pThis, mblk_t *pMsg, mb dl_unitdata_req_t *pDlpiMsg = (dl_unitdata_req_t *)pMsg->b_rptr; bcopy(pMsg->b_rptr + pDlpiMsg->dl_dest_addr_offset, &EthHdr.DstMac, sizeof(EthHdr.DstMac)); - bcopy(&pThis->u.s.Mac, &EthHdr.SrcMac, sizeof(EthHdr.SrcMac)); + bcopy(&pThis->u.s.MacAddr, &EthHdr.SrcMac, sizeof(EthHdr.SrcMac)); vboxnetflt_dladdr_t *pDLSapAddr = (vboxnetflt_dladdr_t *)(pMsg->b_rptr + pDlpiMsg->dl_dest_addr_offset); EthHdr.EtherType = RT_H2BE_U16(pDLSapAddr->SAP); @@ -2947,7 +2963,7 @@ static int vboxNetFltSolarisQueueLoopback(PVBOXNETFLTINS pThis, vboxnetflt_promi Assert(DB_TYPE(pMsg) == M_DATA); Assert(pPromiscStream); - LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback pThis=%p pPromiscStream=%p pMsg=%p\n", pThis, pPromiscStream, pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback pThis=%p pPromiscStream=%p pMsg=%p\n", pThis, pPromiscStream, pMsg)); if (RT_UNLIKELY(pMsg->b_cont)) { @@ -3075,7 +3091,7 @@ static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_ Assert(pMsg); Assert(DB_TYPE(pMsg) == M_DATA); - LogFlow((DEVICE_NAME ":vboxNetFltSolarisIsOurMBlk pThis=%p pMsg=%p\n", pThis, pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisIsOurMBlk pThis=%p pMsg=%p\n", pThis, pMsg)); if (pMsg->b_cont) { @@ -3151,6 +3167,21 @@ static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_ /** + * Helper. + */ +DECLINLINE(bool) vboxNetFltPortSolarisIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) +{ + /* + * MAC address change acknowledgements are intercepted on the read side + * hence theoritically we are always update to date with any changes. + */ + return pThis->u.s.MacAddr.au16[0] == pMac->au16[0] + && pThis->u.s.MacAddr.au16[1] == pMac->au16[1] + && pThis->u.s.MacAddr.au16[2] == pMac->au16[2]; +} + + +/** * Worker for routing messages from the wire or from the host. * * @returns VBox status code. @@ -3161,7 +3192,7 @@ static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_ */ static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pMsg) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p pMsg=%p\n", pThis, pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p pMsg=%p\n", pThis, pMsg)); AssertCompile(sizeof(struct ether_header) == sizeof(RTNETETHERHDR)); Assert(pStream->Type == kPromiscStream); @@ -3212,7 +3243,7 @@ static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStr */ uint32_t fSrc = INTNETTRUNKDIR_WIRE; PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr; - if (vboxNetFltPortOsIsHostMac(pThis, &pEthHdr->SrcMac)) + if (vboxNetFltPortSolarisIsHostMac(pThis, &pEthHdr->SrcMac)) fSrc = INTNETTRUNKDIR_HOST; /* @@ -3287,7 +3318,7 @@ static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStr pMsg->b_rptr += cbEthPrefix + sizeof(VLANHEADER); pStrippedMsg->b_cont = pMsg; pMsg = pStrippedMsg; - LogFlow((DEVICE_NAME ":Stripped priority VLAN tag.\n")); + LogFlow((DEVICE_NAME ":Stripped VLAN tag.\n")); } else { @@ -3348,7 +3379,7 @@ static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStr */ static mblk_t *vboxNetFltSolarisFixChecksums(mblk_t *pMsg) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisFixChecksums pMsg=%p\n")); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisFixChecksums pMsg=%p\n")); Assert(DB_TYPE(pMsg) == M_DATA); @@ -3475,7 +3506,7 @@ static mblk_t *vboxNetFltSolarisFixChecksums(mblk_t *pMsg) */ static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg) { - LogFlow((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg)); PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr; uint8_t *pb = pMsg->b_rptr; @@ -3486,9 +3517,9 @@ static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg) if (!pMsg->b_cont) { if (pIpHdr->ip_p == RTNETIPV4_PROT_ICMP) - LogFlow((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12)))); + LogRel((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12)))); else if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP) - LogFlow((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6)); + LogRel((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6)); else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP) { PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl); @@ -3507,35 +3538,28 @@ static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg) } else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_VLAN)) { - typedef struct VLANHEADER - { - int Pcp:3; - int Cfi:1; - int Vid:12; - } VLANHEADER; - - VLANHEADER *pVlanHdr = (VLANHEADER *)(pMsg->b_rptr + sizeof(RTNETETHERHDR)); - LogFlow((DEVICE_NAME ":VLAN Pcp=%d Cfi=%d Id=%d\n", pVlanHdr->Pcp, pVlanHdr->Cfi, pVlanHdr->Vid >> 4)); - LogFlow((DEVICE_NAME "%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); + PVLANHEADER pVlanHdr = (PVLANHEADER)(pMsg->b_rptr + sizeof(RTNETETHERHDR) - sizeof(pEthHdr->EtherType)); + LogRel((DEVICE_NAME ":VLAN Pcp=%u Cfi=%u Id=%u\n", VLAN_PRI(RT_BE2H_U16(pVlanHdr->Data)), VLAN_CFI(RT_BE2H_U16(pVlanHdr->Data)), VLAN_ID(RT_BE2H_U16(pVlanHdr->Data)))); + LogRel((DEVICE_NAME "%.*Rhxd\n", sizeof(VLANHEADER), pVlanHdr)); } else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP)) { PRTNETARPHDR pArpHdr = (PRTNETARPHDR)(pEthHdr + 1); - LogFlow((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper)); + LogRel((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper)); } else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6)) { - LogFlow((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6)); + LogRel((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6)); } else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_1) || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_2) || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_3)) { - LogFlow((DEVICE_NAME ":IPX packet.\n")); + LogRel((DEVICE_NAME ":IPX packet.\n")); } else { - LogFlow((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac, + LogRel((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac, &pEthHdr->SrcMac)); /* LogFlow((DEVICE_NAME ":%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); */ } @@ -3544,38 +3568,12 @@ static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg) /* -=-=-=-=-=- Common Hooks -=-=-=-=-=- */ -bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis) -{ - /* - * There is no easy way of obtaining the global host side promiscuous counter. - * Currently we just return false. - */ - return false; -} - - -void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac) -{ - LogFlow((DEVICE_NAME ":vboxNetFltPortOsGetMacAddress pThis=%p\n", pThis)); - *pMac = pThis->u.s.Mac; -} - -bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) -{ - /* - * MAC address change acknowledgements are intercepted on the read side - * hence theoritically we are always update to date with any changes. - */ - return pThis->u.s.Mac.au16[0] == pMac->au16[0] - && pThis->u.s.Mac.au16[1] == pMac->au16[1] - && pThis->u.s.Mac.au16[2] == pMac->au16[2]; -} void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) { - LogFlow((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive)); /* * Enable/disable promiscuous mode. @@ -3599,7 +3597,7 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis) { - LogFlow((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis)); vboxNetFltSolarisDetachFromInterface(pThis); @@ -3630,14 +3628,14 @@ int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis) void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis) { - LogFlow((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis)); /* Nothing to do here. */ } int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) { - LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p\n")); + LogFlowFunc((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p\n")); /* * Mutex used for loopback lockouts. @@ -3646,7 +3644,7 @@ int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) if (RT_SUCCESS(rc)) { #ifdef VBOXNETFLT_SOLARIS_IPV6_POLLING - int rc = RTSemFastMutexCreate(&pThis->u.s.hPollMtx); + rc = RTSemFastMutexCreate(&pThis->u.s.hPollMtx); if (RT_SUCCESS(rc)) { #endif @@ -3685,12 +3683,14 @@ int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis) pThis->u.s.pvIp6Stream = NULL; pThis->u.s.pvArpStream = NULL; pThis->u.s.pvPromiscStream = NULL; + pThis->u.s.fAttaching = false; + pThis->u.s.fVLAN = false; pThis->u.s.hFastMtx = NIL_RTSEMFASTMUTEX; pThis->u.s.fVLAN = false; #ifdef VBOXNETFLT_SOLARIS_IPV6_POLLING pThis->u.s.hPollMtx = NIL_RTSEMFASTMUTEX; #endif - bzero(&pThis->u.s.Mac, sizeof(pThis->u.s.Mac)); + bzero(&pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); return VINF_SUCCESS; } @@ -3707,7 +3707,7 @@ bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis) int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) { - LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p pSG=%p fDst=%d\n", pThis, pSG, fDst)); + LogFlowFunc((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p pSG=%p fDst=%d\n", pThis, pSG, fDst)); int rc = VINF_SUCCESS; if (fDst & INTNETTRUNKDIR_WIRE) @@ -3833,7 +3833,7 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) * Construct a DL_UNITDATA_IND style message for ARP as it doesn't understand fast path. */ mblk_t *pDlpiMsg; - int rc = vboxNetFltSolarisRawToUnitData(pMsg, &pDlpiMsg); + rc = vboxNetFltSolarisRawToUnitData(pMsg, &pDlpiMsg); if (RT_SUCCESS(rc)) { pMsg = pDlpiMsg; diff --git a/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFltBow-solaris.c b/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFltBow-solaris.c new file mode 100644 index 000000000..4c2ae1570 --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFltBow-solaris.c @@ -0,0 +1,1063 @@ +/* $Id: VBoxNetFltBow-solaris.c 28830 2010-04-27 14:05:25Z vboxsync $ */ +/** @file + * VBoxNetFlt - Network Filter Driver (Host), Solaris Specific Code. + */ + +/* + * Copyright (C) 2008 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#define LOG_GROUP LOG_GROUP_NET_FLT_DRV +#include <VBox/log.h> +#include <VBox/err.h> +#include <VBox/intnetinline.h> +#include <VBox/version.h> +#include <iprt/initterm.h> +#include <iprt/alloca.h> +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/string.h> +#include <iprt/net.h> +#include <iprt/spinlock.h> + +#include <sys/types.h> +#include <sys/modctl.h> +#include <sys/conf.h> +#include <sys/stat.h> +#include <sys/ddi.h> +#include <sys/gld.h> +#include <sys/sunddi.h> +#include <sys/strsubr.h> +#include <sys/dlpi.h> +#include <sys/dls_mgmt.h> +#include <sys/mac.h> +#include <sys/strsun.h> +#include <sys/sunddi.h> + +#include "include/mac_provider.h" /* dependency for other headers */ +#include "include/mac_client.h" /* for mac_* */ +#include "include/mac_client_priv.h" /* for mac_info, mac_capab_get etc. */ +#if 0 +#include "include/dls.h" /* for dls_mgmt_* */ +#include "include/dld_ioc.h" /* required by vnic.h */ +#include "include/vnic.h" /* for vnic_ioc_diag_t */ +#include "include/vnic_impl.h" /* for vnic_dev_create */ +#endif + +#define VBOXNETFLT_OS_SPECFIC 1 +#include "../VBoxNetFltInternal.h" + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** The module name. */ +#define DEVICE_NAME "vboxflt" +/** The module descriptions as seen in 'modinfo'. */ +#define DEVICE_DESC_DRV "VirtualBox NetBow" +/** The dynamically created VNIC name */ +#define VBOXFLT_VNIC_NAME "vboxvnic" +/** Debugging switch for using symbols in kmdb */ +# define LOCAL static + +#if defined(DEBUG_ramshankar) +# undef Log +# define Log LogRel +# undef LogFlow +# define LogFlow LogRel +# undef LOCAL +# define LOCAL +#endif + + +/******************************************************************************* +* Kernel Entry Hooks * +*******************************************************************************/ +LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd); +LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd); +LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult); + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * cb_ops: for drivers that support char/block entry points + */ +static struct cb_ops g_VBoxNetFltSolarisCbOps = +{ + nulldev, /* c open */ + nulldev, /* c close */ + nodev, /* b strategy */ + nodev, /* b dump */ + nodev, /* b print */ + nodev, /* c read */ + nodev, /* c write*/ + nodev, /* c ioctl*/ + nodev, /* c devmap */ + nodev, /* c mmap */ + nodev, /* c segmap */ + nochpoll, /* c poll */ + ddi_prop_op, /* property ops */ + NULL, /* streamtab */ + D_NEW | D_MP, /* compat. flag */ + CB_REV, /* revision */ + nodev, /* c aread */ + nodev /* c awrite */ +}; + +/** + * dev_ops: for driver device operations + */ +static struct dev_ops g_VBoxNetFltSolarisDevOps = +{ + DEVO_REV, /* driver build revision */ + 0, /* ref count */ + VBoxNetFltSolarisGetInfo, + nulldev, /* identify */ + nulldev, /* probe */ + VBoxNetFltSolarisAttach, + VBoxNetFltSolarisDetach, + nodev, /* reset */ + &g_VBoxNetFltSolarisCbOps, + NULL, /* bus ops */ + nodev, /* power */ + ddi_quiesce_not_needed +}; + +/** + * modldrv: export driver specifics to the kernel + */ +static struct modldrv g_VBoxNetFltSolarisModule = +{ + &mod_driverops, /* extern from kernel */ + DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV), + &g_VBoxNetFltSolarisDevOps +}; + +/** + * modlinkage: export install/remove/info to the kernel + */ +static struct modlinkage g_VBoxNetFltSolarisModLinkage = +{ + MODREV_1, + { + &g_VBoxNetFltSolarisModule, + NULL, + } +}; + + +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** Global Device handle we only support one instance. */ +static dev_info_t *g_pVBoxNetFltSolarisDip = NULL; +/** Global Mutex (actually an rw lock). */ +static RTSEMFASTMUTEX g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX; +/** The (common) global data. */ +static VBOXNETFLTGLOBALS g_VBoxNetFltSolarisGlobals; + + +/******************************************************************************* +* Internal Function * +*******************************************************************************/ +LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst); +LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg); +LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc); + +LOCAL int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery); +LOCAL int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis); +LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback); + + +/** + * Kernel entry points + */ +int _init(void) +{ + LogFlow((DEVICE_NAME ":_init\n")); + + /* + * Prevent module autounloading. + */ + modctl_t *pModCtl = mod_getctl(&g_VBoxNetFltSolarisModLinkage); + if (pModCtl) + pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD; + else + LogRel((DEVICE_NAME ":failed to disable autounloading!\n")); + + /* + * Initialize IPRT. + */ + int rc = RTR0Init(0); + if (RT_SUCCESS(rc)) + { + /* + * Initialize Solaris specific globals here. + */ + rc = RTSemFastMutexCreate(&g_VBoxNetFltSolarisMtx); + if (RT_SUCCESS(rc)) + { + /* + * Initialize the globals and connect to the support driver. + * + * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv) + * for establishing the connect to the support driver. + */ + memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals)); + rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltSolarisGlobals); + if (RT_SUCCESS(rc)) + { + rc = mod_install(&g_VBoxNetFltSolarisModLinkage); + if (!rc) + return rc; + + LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc)); + vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals); + } + else + LogRel((DEVICE_NAME ":failed to initialize globals.\n")); + + RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx); + g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX; + } + + RTR0Term(); + } + else + LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc)); + + memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals)); + return RTErrConvertToErrno(rc); +} + + +int _fini(void) +{ + int rc; + LogFlow((DEVICE_NAME ":_fini\n")); + + /* + * Undo the work done during start (in reverse order). + */ + rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals); + if (RT_FAILURE(rc)) + { + LogRel((DEVICE_NAME ":_fini - busy!\n")); + return EBUSY; + } + + rc = mod_remove(&g_VBoxNetFltSolarisModLinkage); + if (!rc) + { + if (g_VBoxNetFltSolarisMtx != NIL_RTSEMFASTMUTEX) + { + RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx); + g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX; + } + + RTR0Term(); + } + + return rc; +} + + +int _info(struct modinfo *pModInfo) +{ + LogFlow((DEVICE_NAME ":_info\n")); + + int rc = mod_info(&g_VBoxNetFltSolarisModLinkage, pModInfo); + + LogFlow((DEVICE_NAME ":_info returns %d\n", rc)); + return rc; +} + + +/** + * Attach entry point, to attach a device to the system or resume it. + * + * @param pDip The module structure instance. + * @param enmCmd Operation type (attach/resume). + * + * @returns corresponding solaris error code. + */ +LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) +{ + LogFlow((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd)); + + switch (enmCmd) + { + case DDI_ATTACH: + { + int instance = ddi_get_instance(pDip); + int rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0, "none", "none", 0666); + if (rc == DDI_SUCCESS) + { + g_pVBoxNetFltSolarisDip = pDip; + ddi_report_dev(pDip); + return DDI_SUCCESS; + } + else + LogRel((DEVICE_NAME ":VBoxNetFltSolarisAttach failed to create minor node. rc=%d\n", rc)); + return DDI_FAILURE; + } + + case DDI_RESUME: + { + /* Nothing to do here... */ + return DDI_SUCCESS; + } + + /* case DDI_PM_RESUME: */ + default: + return DDI_FAILURE; + } +} + + +/** + * Detach entry point, to detach a device to the system or suspend it. + * + * @param pDip The module structure instance. + * @param enmCmd Operation type (detach/suspend). + * + * @returns corresponding solaris error code. + */ +LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) +{ + LogFlow((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd)); + + switch (enmCmd) + { + case DDI_DETACH: + { + ddi_remove_minor_node(pDip, NULL); + return DDI_SUCCESS; + } + + case DDI_RESUME: + { + /* Nothing to do here... */ + return DDI_SUCCESS; + } + + /* case DDI_PM_SUSPEND: */ + /* case DDI_HOT_PLUG_DETACH: */ + default: + return DDI_FAILURE; + } +} + + +/** + * Info entry point, called by solaris kernel for obtaining driver info. + * + * @param pDip The module structure instance (do not use). + * @param enmCmd Information request type. + * @param pvArg Type specific argument. + * @param ppvResult Where to store the requested info. + * + * @returns corresponding solaris error code. + */ +LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppResult) +{ + LogFlow((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd, getminor((dev_t)pvArg))); + + switch (enmCmd) + { + case DDI_INFO_DEVT2DEVINFO: + { + *ppResult = g_pVBoxNetFltSolarisDip; + return DDI_SUCCESS; + } + + case DDI_INFO_DEVT2INSTANCE: + { + int instance = getminor((dev_t)pvArg); + *ppResult = (void *)(uintptr_t)instance; + return DDI_SUCCESS; + } + } + + return DDI_FAILURE; +} + + +/** + * Create a solaris message block from the SG list. + * + * @param pThis The instance. + * @param pSG Pointer to the scatter-gather list. + * + * @returns Solaris message block. + */ +LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) +{ + LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n", pThis, pSG)); + + mblk_t *pMsg = allocb(pSG->cbTotal, BPRI_HI); + if (RT_UNLIKELY(!pMsg)) + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG failed to alloc %d bytes for mblk_t.\n", pSG->cbTotal)); + return NULL; + } + + /* + * Single buffer copy. Maybe later explore the + * need/possibility for using a mblk_t chain rather. + */ + for (unsigned i = 0; i < pSG->cSegsUsed; i++) + { + if (pSG->aSegs[i].pv) + { + bcopy(pSG->aSegs[i].pv, pMsg->b_wptr, pSG->aSegs[i].cb); + pMsg->b_wptr += pSG->aSegs[i].cb; + } + } + DB_TYPE(pMsg) = M_DATA; + return pMsg; +} + + +/** + * Calculate the number of segments required for this message block. + * + * @param pThis The instance + * @param pMsg Pointer to the data message. + * + * @returns Number of segments. + */ +LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg) +{ + unsigned cSegs = 0; + for (mblk_t *pCur = pMsg; pCur; pCur = pCur->b_cont) + if (MBLKL(pCur)) + cSegs++; + +#ifdef PADD_RUNT_FRAMES_FROM_HOST + if (msgdsize(pMsg) < 60) + cSegs++; +#endif + + NOREF(pThis); + return RT_MAX(cSegs, 1); +} + + +/** + * Initializes an SG list from the given message block. + * + * @param pThis The instance. + * @param pMsg Pointer to the data message. + The caller must ensure it's not a control message block. + * @param pSG Pointer to the SG. + * @param cSegs Number of segments in the SG. + * This should match the number in the message block exactly! + * @param fSrc The source of the message. + * + * @returns VBox status code. + */ +LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc) +{ + LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs)); + + /* + * Convert the message block to segments. Works cbTotal and sets cSegsUsed. + */ + IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/); + mblk_t *pCur = pMsg; + unsigned iSeg = 0; + while (pCur) + { + size_t cbSeg = MBLKL(pCur); + if (cbSeg) + { + void *pvSeg = pCur->b_rptr; + pSG->aSegs[iSeg].pv = pvSeg; + pSG->aSegs[iSeg].cb = cbSeg; + pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS; + pSG->cbTotal += cbSeg; + iSeg++; + } + pCur = pCur->b_cont; + } + pSG->cSegsUsed = iSeg; + +#ifdef PADD_RUNT_FRAMES_FROM_HOST + if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST)) + { + LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pulling up to length.\n")); + + static uint8_t const s_abZero[128] = {0}; + pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS; + pSG->aSegs[iSeg].pv = (void *)&s_abZero[0]; + pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal; + pSG->cbTotal = 60; + pSG->cSegsUsed++; + Assert(iSeg + 1 < cSegs); + } +#endif + + LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG iSeg=%d pSG->cbTotal=%d msgdsize=%d\n", iSeg, pSG->cbTotal, msgdsize(pMsg))); + return VINF_SUCCESS; +} + + +/** + * Simple packet dump, used for internal debugging. + * + * @param pMsg Pointer to the message to analyze and dump. + */ +static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg) +{ + LogFlow((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg)); + + PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr; + uint8_t *pb = pMsg->b_rptr; + if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4)) + { + PRTNETIPV4 pIpHdr = (PRTNETIPV4)(pEthHdr + 1); + if (!pMsg->b_cont) + { + if (pIpHdr->ip_p == RTNETIPV4_PROT_ICMP) + LogFlow((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12)))); + else if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP) + LogFlow((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6)); + else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP) + { + PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl); + if ( RT_BE2H_U16(pUdpHdr->uh_sport) == 67 + && RT_BE2H_U16(pUdpHdr->uh_dport) == 68) + { + LogRel((DEVICE_NAME ":UDP bootp ack D=%.6Rhxs S=%.6Rhxs UDP_CheckSum=%04x Computex=%04x\n", pb, pb + 6, + RT_BE2H_U16(pUdpHdr->uh_sum), RT_BE2H_U16(RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1)))); + } + } + } + else + { + LogFlow((DEVICE_NAME ":Chained IP packet. Skipping validity check.\n")); + } + } + else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_VLAN)) + { + typedef struct VLANHEADER + { + int Pcp:3; + int Cfi:1; + int Vid:12; + } VLANHEADER; + + VLANHEADER *pVlanHdr = (VLANHEADER *)(pMsg->b_rptr + sizeof(RTNETETHERHDR)); + LogFlow((DEVICE_NAME ":VLAN Pcp=%d Cfi=%d Id=%d\n", pVlanHdr->Pcp, pVlanHdr->Cfi, pVlanHdr->Vid >> 4)); + LogFlow((DEVICE_NAME "%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); + } + else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP)) + { + PRTNETARPHDR pArpHdr = (PRTNETARPHDR)(pEthHdr + 1); + LogFlow((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper)); + } + else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6)) + { + LogFlow((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6)); + } + else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_1) + || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_2) + || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_3)) + { + LogFlow((DEVICE_NAME ":IPX packet.\n")); + } + else + { + LogFlow((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac, + &pEthHdr->SrcMac)); + /* LogFlow((DEVICE_NAME ":%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); */ + } +} + + +/** + * Helper. + */ +DECLINLINE(bool) vboxNetFltPortSolarisIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) +{ + return pThis->u.s.MacAddr.au16[0] == pMac->au16[0] + && pThis->u.s.MacAddr.au16[1] == pMac->au16[1] + && pThis->u.s.MacAddr.au16[2] == pMac->au16[2]; +} + + +/** + * Receive (rx) entry point. + * + * @param pvData Private data. + * @param hResource The resource handle. + * @param pMsg The packet. + * @param fLoopback Whether this is a loopback packet or not. + */ +LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback) +{ + LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pvData=%p pMsg=%p fLoopback=%d cbData=%d\n", pvData, pMsg, fLoopback, pMsg ? MBLKL(pMsg) : 0)); + + PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData; + AssertPtrReturnVoid(pThis); + AssertPtrReturnVoid(pMsg); + + /* + * Active? Retain the instance and increment the busy counter. + */ + if (!vboxNetFltTryRetainBusyActive(pThis)) + return; + + uint32_t fSrc = INTNETTRUNKDIR_WIRE; + PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr; + if ( MBLKL(pMsg) >= sizeof(RTNETETHERHDR) + && vboxNetFltPortSolarisIsHostMac(pThis, &pEthHdr->SrcMac)) + fSrc = INTNETTRUNKDIR_HOST; + + /* + * Route all received packets into the internal network. + */ + unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pMsg); + PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); + int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc); + if (RT_SUCCESS(rc)) + pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc); + else + LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed. rc=%d\n", rc)); + + vboxNetFltRelease(pThis, true /* fBusy */); + freemsgchain(pMsg); + + NOREF(hResource); +} + + +/** + * Create a VNIC dynamically over the given interface. + * + * @param pThis The VM connection instance. + * + * @returns corresponding VBox error code. + */ +LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis) +{ +#if 0 + LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC pThis=%p\n", pThis)); + + datalink_id_t InterfaceLinkId; + int rc = dls_mgmt_get_linkid(pThis->szName, &InterfaceLinkId); + if (!rc) + { + dev_t DeviceNum = makedevice(ddi_driver_major(g_pVBoxNetFltSolarisDip), pThis->u.s.uInstance); + char szVNICName[sizeof(VBOXFLT_VNIC_NAME) + 16]; + RTStrPrintf(szVNICName, sizeof(szVNICName), "%s%d", VBOXFLT_VNIC_NAME, pThis->u.s.uInstance); + LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC Creating VNIC '%s' over '%s'\n", szVNICName, pThis->szName)); + rc = dls_mgmt_create(szVNICName, DeviceNum, DATALINK_CLASS_VNIC, DL_ETHER, B_FALSE /* Persist */, &pThis->u.s.VNICLinkId); + if (!rc) + { + /* -XXX- @todo remove hardcoded Guest MAC address, should be sent from guest later. */ + RTMAC GuestMac; + GuestMac.au8[0] = 0x08; + GuestMac.au8[1] = 0x00; + GuestMac.au8[2] = 0x27; + GuestMac.au8[3] = 0xFE; + GuestMac.au8[4] = 0x21; + GuestMac.au8[5] = 0x03; + + AssertCompile(sizeof(RTMAC) <= MAXMACADDRLEN); + uchar_t MacAddr[MAXMACADDRLEN]; + bzero(MacAddr, sizeof(MacAddr)); + bcopy(GuestMac.au8, MacAddr, RT_MIN(sizeof(GuestMac), sizeof(MacAddr))); + + int MacSlot = 0; + vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE; + vnic_mac_addr_type_t MacAddrType = VNIC_MAC_ADDR_TYPE_FIXED; + int cbMac = sizeof(RTMAC); + int fFlags = VNIC_IOC_CREATE_NODUPCHECK | VNIC_IOC_CREATE_REQ_HWRINGS; + rc = vnic_dev_create(pThis->u.s.VNICLinkId, InterfaceLinkId, &MacAddrType, &cbMac, MacAddr, + &MacSlot, 0 /* Mac Prefix */, 0 /* VLAN Id */, NULL /* Resources Caps */, + fFlags, &Diag, kcred); + if (rc) + { + if (Diag == VNIC_IOC_DIAG_NO_HWRINGS) + { + /* + * No hardware rings available, retry without requesting hardware ring. + */ + LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC No hardware rings available for VNIC over '%s'. Recreating VNIC '%s'\n", pThis->szName, + szVNICName)); + + fFlags = VNIC_IOC_CREATE_NODUPCHECK; + rc = vnic_dev_create(pThis->u.s.VNICLinkId, InterfaceLinkId, &MacAddrType, &cbMac, MacAddr, + &MacSlot, 0 /* Mac Prefix */, 0 /* VLAN Id */, NULL /* Resources Caps */, + fFlags, &Diag, kcred); + } + } + + if (!rc) + { + pThis->u.s.fCreatedVNIC = true; + pThis->u.s.uInstance++; + LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC successfully created VNIC '%s' over '%s'\n", "vboxvnic", pThis->szName)); + return VINF_SUCCESS; + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to create VNIC over '%s'. rc=%d Diagnosis=%d\n", pThis->szName, + rc, Diag)); + rc = VERR_INTNET_FLT_VNIC_CREATE_FAILED; + } + + dls_mgmt_destroy(pThis->u.s.VNICLinkId, B_FALSE /* Persist */); + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to create a link id for a VNIC over '%s' rc=%d\n", pThis->szName, rc)); + rc = VERR_INTNET_FLT_VNIC_CREATE_FAILED; + } + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to find interface '%s' rc=%d\n", pThis->szName, rc)); + rc = VERR_INTNET_FLT_IF_NOT_FOUND; + } + + return rc; +#endif +} + + +/** + * Attach to the network interface. + * + * @param pThis The VM connection instance. + * @param fRediscovery Whether this is a rediscovery attempt after disconnect. + * + * @returns corresponding VBox error code. + */ +LOCAL int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery) +{ + LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface pThis=%p fRediscovery=%d\n", pThis, fRediscovery)); + + AssertPtrReturn(pThis, VERR_INVALID_POINTER); + + /* + * Open the underlying interface (lower MAC) and get it's handle. + */ + int rc = mac_open_by_linkname(pThis->szName, &pThis->u.s.hInterface); + if (RT_LIKELY(!rc)) + { + /* + * If this is not a VNIC, create a VNIC and open it instead. + */ + rc = mac_is_vnic(pThis->u.s.hInterface); + if (!rc) + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface '%s' is not a VNIC. Creating one.\n", pThis->szName)); + + mac_close(pThis->u.s.hInterface); + pThis->u.s.hInterface = NULL; + rc = vboxNetFltSolarisCreateVNIC(pThis); + if (RT_SUCCESS(rc)) + rc = mac_open_by_linkid(pThis->u.s.VNICLinkId, &pThis->u.s.hInterface); + else + { + pThis->u.s.hInterface = NULL; + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to create VNIC. rc=%Rrc\n", rc)); + } + } + else + rc = VINF_SUCCESS; + + /* + * At this point "hInterface" should be a handle to a VNIC, we no longer would deal with physical interface + * if it has been passed by the user. + */ + if (RT_SUCCESS(rc)) + { + const mac_info_t *pMacInfo = mac_info(pThis->u.s.hInterface); + if (RT_LIKELY(pMacInfo)) + { + if ( pMacInfo->mi_media == DL_ETHER + && pMacInfo->mi_nativemedia == DL_ETHER) + { + /* + * Obtain the MAC address of the interface. + */ + AssertCompile(sizeof(RTMAC) == ETHERADDRL); + mac_unicast_primary_get(pThis->u.s.hInterface, (uint8_t *)&pThis->u.s.MacAddr.au8); + + LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface MAC address of %s is %.*Rhxs\n", pThis->szName, + sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); + + /** @todo Obtain the MTU size using mac_sdu_get() */ + /** @todo Obtain capabilities (hardware checksum etc.) using mac_capab_get() */ + + /* + * Open a client connection to the lower MAC interface. + */ + rc = mac_client_open(pThis->u.s.hInterface, &pThis->u.s.hClient, + NULL /* name of this client */, + MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */ + MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */ + ); + if (RT_LIKELY(!rc)) + { + /** @todo -XXX- if possible we must move unicast_add and rx_set to when the Guest advertises it's MAC to us. */ + + /* + * Set a unicast address for this client and the packet receive callback. + * We want to use the primary unicast address of the underlying interface (VNIC) hence we pass NULL. + * Also we don't really set the RX function here, this is done when we activate promiscuous mode. + */ + mac_diag_t MacDiag; + rc = mac_unicast_add(pThis->u.s.hClient, NULL /* MAC Address */, + MAC_UNICAST_PRIMARY | MAC_UNICAST_STRIP_DISABLE | + MAC_UNICAST_DISABLE_TX_VID_CHECK | MAC_UNICAST_NODUPCHECK | MAC_UNICAST_HW, + &pThis->u.s.hUnicast, 0 /* VLAN id */, &MacDiag); + if (!rc) + { + /* + * Report MAC address, promiscuous mode and capabilities. + */ + if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + Assert(pThis->pSwitchPort); + pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); + pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); /** @todo Promisc */ + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); + pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); + vboxNetFltRelease(pThis, true /*fBusy*/); + } + + LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface successfully attached over '%s'\n", pThis->szName)); + return VINF_SUCCESS; + } + + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to set client MAC address over link '%s' rc=%d\n", + pThis->szName, rc)); + + mac_client_close(pThis->u.s.hClient, 0 /* fFlags */); + pThis->u.s.hClient = NULL; + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to create client over link '%s' rc=%d\n", + pThis->szName, rc)); + } + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface media type incompatible: %d %d\n", pMacInfo->mi_media, + pMacInfo->mi_nativemedia)); + rc = EPROTO; + } + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to obtain info for link '%s'\n", pThis->szName)); + rc = ENXIO; + } + } + else + { + LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface VNIC creation failed over '%s'\n", pThis->szName)); + rc = ENXIO; + } + + if (pThis->u.s.hInterface) + { + mac_close(pThis->u.s.hInterface); + pThis->u.s.hInterface = NULL; + } + } + else + LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to open link '%s' rc=%d\n", pThis->szName, rc)); + + return RTErrConvertFromErrno(rc); +} + + + +/** + * Detach from the network interface. + * + * @param pThis The VM connection instance. + * @returns corresponding VBox error code. + */ +LOCAL int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis) +{ + AssertPtrReturn(pThis, VERR_INVALID_POINTER); + + if (pThis->u.s.hPromiscuous) + { + mac_promisc_remove(pThis->u.s.hPromiscuous); + pThis->u.s.hPromiscuous = NULL; + } + + if (pThis->u.s.hClient) + { + if (pThis->u.s.hUnicast) + { + mac_unicast_remove(pThis->u.s.hClient, pThis->u.s.hUnicast); + pThis->u.s.hUnicast = NULL; + } + + mac_rx_clear(pThis->u.s.hClient); + + mac_client_close(pThis->u.s.hClient, 0 /* fFlags */); + pThis->u.s.hClient = NULL; + } + + if (pThis->u.s.hInterface) + { + mac_close(pThis->u.s.hInterface); + pThis->u.s.hInterface = NULL; + } + + if (pThis->u.s.fCreatedVNIC) + { +#if 0 + vnic_dev_delete(pThis->u.s.VNICLinkId, 0 /* Flags -- ununsed in snv_127 */, kcred); + dls_mgmt_destroy(pThis->u.s.VNICLinkId, B_FALSE /* Persist */); + pThis->u.s.VNICLinkId = DATALINK_INVALID_LINKID; + pThis->u.s.fCreatedVNIC = false; +#endif + } +} + + +/* -=-=-=-=-=- Common Hooks -=-=-=-=-=- */ + + +void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) +{ + LogFlow((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive)); + + if (fActive) + { + /* + * Activate promiscuous mode. + */ + if (!pThis->u.s.hPromiscuous) + { + int rc = mac_promisc_add(pThis->u.s.hClient, MAC_CLIENT_PROMISC_ALL, vboxNetFltSolarisRecv, pThis, &pThis->u.s.hPromiscuous, + MAC_PROMISC_FLAGS_NO_TX_LOOP); + if (rc) + LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive cannot enable promiscuous mode for '%s' rc=%d\n", pThis->szName, rc)); + } + } + else + { + /* + * Deactivate promiscuous mode. + */ + if (pThis->u.s.hPromiscuous) + { + mac_promisc_remove(pThis->u.s.hPromiscuous); + pThis->u.s.hPromiscuous = NULL; + } + } +} + + +int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis) +{ + LogFlow((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis)); + return vboxNetFltSolarisDetachFromInterface(pThis); +} + + +int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis) +{ + LogFlow((DEVICE_NAME ":vboxNetFltOsConnectIt pThis=%p\n", pThis)); + return vboxNetFltSolarisAttachToInterface(pThis, false /* fRediscovery */); +} + + +void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis) +{ + LogFlow((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis)); +} + + +int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) +{ + LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p pvContext=%p\n", pThis, pvContext)); + + return VINF_SUCCESS; +} + + +int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis) +{ + /* + * Init. the solaris specific data. + */ + pThis->u.s.VNICLinkId = DATALINK_INVALID_LINKID; + pThis->u.s.uInstance = 0; + pThis->u.s.fCreatedVNIC = false; + pThis->u.s.hInterface = NULL; + pThis->u.s.hClient = NULL; + pThis->u.s.hUnicast = NULL; + pThis->u.s.hPromiscuous = NULL; + bzero(&pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); + return VINF_SUCCESS; +} + + +bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis) +{ + /* + * @todo Think about this. + */ + return false; +} + + +int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) +{ + /* + * Xmit the packet down the interface (tx) + */ + int rc = VERR_INVALID_HANDLE; + if (RT_LIKELY(pThis->u.s.hClient)) + { + mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst); + if (RT_LIKELY(pMsg)) + { + LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p cbData=%d\n", pThis, MBLKL(pMsg))); + + mac_tx_cookie_t pXmitCookie = mac_tx(pThis->u.s.hClient, pMsg, 0 /* Hint */, MAC_DROP_ON_NO_DESC, NULL /* return message */); + if (RT_LIKELY(!pXmitCookie)) + return VINF_SUCCESS; + + pMsg = NULL; + rc = VERR_NET_IO_ERROR; + LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit Xmit failed.\n")); + } + else + { + LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit no memory for allocating Xmit packet.\n")); + rc = VERR_NO_MEMORY; + } + } + else + LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit missing client.\n")); + + return rc; +} + diff --git a/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_client.h b/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_client.h new file mode 100644 index 000000000..e5524214e --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_client.h @@ -0,0 +1,199 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009-2010 Oracle Corporation. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This file captures the MAC client API definitions. It can be + * included from any MAC clients. + */ + +#ifndef _SYS_MAC_CLIENT_H +#define _SYS_MAC_CLIENT_H + +#include <sys/mac.h> +#include <sys/mac_flow.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _KERNEL + +/* + * MAC client interface. + */ + +typedef struct __mac_client_handle *mac_client_handle_t; +typedef struct __mac_unicast_handle *mac_unicast_handle_t; +typedef struct __mac_promisc_handle *mac_promisc_handle_t; +typedef struct __mac_perim_handle *mac_perim_handle_t; +typedef uintptr_t mac_tx_cookie_t; + +typedef void (*mac_tx_notify_t)(void *, mac_tx_cookie_t); + +typedef enum { + MAC_DIAG_NONE, + MAC_DIAG_MACADDR_NIC, + MAC_DIAG_MACADDR_INUSE, + MAC_DIAG_MACADDR_INVALID, + MAC_DIAG_MACADDRLEN_INVALID, + MAC_DIAG_MACFACTORYSLOTINVALID, + MAC_DIAG_MACFACTORYSLOTUSED, + MAC_DIAG_MACFACTORYSLOTALLUSED, + MAC_DIAG_MACFACTORYNOTSUP, + MAC_DIAG_MACPREFIX_INVALID, + MAC_DIAG_MACPREFIXLEN_INVALID, + MAC_DIAG_MACNO_HWRINGS +} mac_diag_t; + +typedef enum { + MAC_CLIENT_PROMISC_ALL, + MAC_CLIENT_PROMISC_FILTERED, + MAC_CLIENT_PROMISC_MULTI +} mac_client_promisc_type_t; + +/* flags passed to mac_unicast_add() */ +#define MAC_UNICAST_NODUPCHECK 0x0001 +#define MAC_UNICAST_PRIMARY 0x0002 +#define MAC_UNICAST_HW 0x0004 +#define MAC_UNICAST_VNIC_PRIMARY 0x0008 +#define MAC_UNICAST_TAG_DISABLE 0x0010 +#define MAC_UNICAST_STRIP_DISABLE 0x0020 +#define MAC_UNICAST_DISABLE_TX_VID_CHECK 0x0040 + +/* flags passed to mac_client_open */ +#define MAC_OPEN_FLAGS_IS_VNIC 0x0001 +#define MAC_OPEN_FLAGS_EXCLUSIVE 0x0002 +#define MAC_OPEN_FLAGS_IS_AGGR_PORT 0x0004 +#define MAC_OPEN_FLAGS_NO_HWRINGS 0x0008 +#define MAC_OPEN_FLAGS_SHARES_DESIRED 0x0010 +#define MAC_OPEN_FLAGS_USE_DATALINK_NAME 0x0020 +#define MAC_OPEN_FLAGS_REQ_HWRINGS 0x0040 +#define MAC_OPEN_FLAGS_MULTI_PRIMARY 0x0080 + +/* flags passed to mac_client_close */ +#define MAC_CLOSE_FLAGS_IS_VNIC 0x0001 +#define MAC_CLOSE_FLAGS_EXCLUSIVE 0x0002 +#define MAC_CLOSE_FLAGS_IS_AGGR_PORT 0x0004 + +/* flags passed to mac_promisc_add() */ +#define MAC_PROMISC_FLAGS_NO_TX_LOOP 0x0001 +#define MAC_PROMISC_FLAGS_NO_PHYS 0x0002 +#define MAC_PROMISC_FLAGS_VLAN_TAG_STRIP 0x0004 +#define MAC_PROMISC_FLAGS_NO_COPY 0x0008 + +/* flags passed to mac_tx() */ +#define MAC_DROP_ON_NO_DESC 0x01 /* freemsg() if no tx descs */ +#define MAC_TX_NO_ENQUEUE 0x02 /* don't enqueue mblks if not xmit'ed */ +#define MAC_TX_NO_HOLD 0x04 /* don't bump the active Tx count */ + +extern int mac_client_open(mac_handle_t, mac_client_handle_t *, char *, + uint16_t); +extern void mac_client_close(mac_client_handle_t, uint16_t); + +extern int mac_unicast_add(mac_client_handle_t, uint8_t *, uint16_t, + mac_unicast_handle_t *, uint16_t, mac_diag_t *); +extern int mac_unicast_add_set_rx(mac_client_handle_t, uint8_t *, uint16_t, + mac_unicast_handle_t *, uint16_t, mac_diag_t *, mac_rx_t, void *); +extern int mac_unicast_remove(mac_client_handle_t, mac_unicast_handle_t); + +extern int mac_multicast_add(mac_client_handle_t, const uint8_t *); +extern void mac_multicast_remove(mac_client_handle_t, const uint8_t *); + +extern void mac_rx_set(mac_client_handle_t, mac_rx_t, void *); +extern void mac_rx_clear(mac_client_handle_t); +extern mac_tx_cookie_t mac_tx(mac_client_handle_t, mblk_t *, + uintptr_t, uint16_t, mblk_t **); +extern boolean_t mac_tx_is_flow_blocked(mac_client_handle_t, mac_tx_cookie_t); +extern uint64_t mac_client_stat_get(mac_client_handle_t, uint_t); + +extern int mac_promisc_add(mac_client_handle_t, mac_client_promisc_type_t, + mac_rx_t, void *, mac_promisc_handle_t *, uint16_t); +extern void mac_promisc_remove(mac_promisc_handle_t); + +extern mac_notify_handle_t mac_notify_add(mac_handle_t, mac_notify_t, void *); +extern int mac_notify_remove(mac_notify_handle_t, boolean_t); +extern void mac_notify_remove_wait(mac_handle_t); +extern int mac_rename_primary(mac_handle_t, const char *); +extern char *mac_client_name(mac_client_handle_t); + +extern int mac_open(const char *, mac_handle_t *); +extern void mac_close(mac_handle_t); +extern uint64_t mac_stat_get(mac_handle_t, uint_t); + +extern int mac_unicast_primary_set(mac_handle_t, const uint8_t *); +extern void mac_unicast_primary_get(mac_handle_t, uint8_t *); +extern void mac_unicast_primary_info(mac_handle_t, char *, boolean_t *); + +extern boolean_t mac_dst_get(mac_handle_t, uint8_t *); + +extern int mac_addr_random(mac_client_handle_t, uint_t, uint8_t *, + mac_diag_t *); + +extern int mac_addr_factory_reserve(mac_client_handle_t, int *); +extern void mac_addr_factory_release(mac_client_handle_t, uint_t); +extern void mac_addr_factory_value(mac_handle_t, int, uchar_t *, uint_t *, + char *, boolean_t *); +extern uint_t mac_addr_factory_num(mac_handle_t); + +extern mac_tx_notify_handle_t mac_client_tx_notify(mac_client_handle_t, + mac_tx_notify_t, void *); + +extern int mac_set_resources(mac_handle_t, mac_resource_props_t *); +extern void mac_get_resources(mac_handle_t, mac_resource_props_t *); +extern int mac_client_set_resources(mac_client_handle_t, + mac_resource_props_t *); +extern void mac_client_get_resources(mac_client_handle_t, + mac_resource_props_t *); + +/* bridging-related interfaces */ +extern int mac_set_pvid(mac_handle_t, uint16_t); +extern uint16_t mac_get_pvid(mac_handle_t); +extern uint32_t mac_get_llimit(mac_handle_t); +extern uint32_t mac_get_ldecay(mac_handle_t); + +extern int mac_share_capable(mac_handle_t); +extern int mac_share_bind(mac_client_handle_t, uint64_t, uint64_t *); +extern void mac_share_unbind(mac_client_handle_t); + +extern int mac_set_mtu(mac_handle_t, uint_t, uint_t *); + +extern uint_t mac_hwgrp_num(mac_handle_t); +extern void mac_get_hwgrp_info(mac_handle_t, int, uint_t *, uint_t *, + uint_t *, uint_t *, char *); + +extern uint32_t mac_no_notification(mac_handle_t); +extern int mac_set_prop(mac_handle_t, mac_prop_t *, void *, uint_t); +extern int mac_get_prop(mac_handle_t, mac_prop_t *, void *, uint_t, uint_t *); + +extern boolean_t mac_is_vnic(mac_handle_t); + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MAC_CLIENT_H */ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_client_priv.h b/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_client_priv.h new file mode 100644 index 000000000..19ae1d057 --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_client_priv.h @@ -0,0 +1,156 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009-2010 Oracle Corporation. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This file contains *private* MAC API definitions. This header file + * should only be included by kernel components which are part of the + * GLDv3 stack (dld, dls, aggr, softmac). + */ + +#ifndef _SYS_MAC_CLIENT_PRIV_H +#define _SYS_MAC_CLIENT_PRIV_H + +#include <sys/mac.h> +#include <sys/mac_flow.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _KERNEL + +#ifdef DEBUG +#define MAC_PERIM_HELD(mph) mac_perim_held(mph) +#else +#define MAC_PERIM_HELD(mph) +#endif + +extern boolean_t mac_rx_bypass_set(mac_client_handle_t, mac_direct_rx_t, + void *); +extern void mac_rx_bypass_enable(mac_client_handle_t); +extern void mac_rx_bypass_disable(mac_client_handle_t); + +extern const mac_info_t *mac_info(mac_handle_t); +extern boolean_t mac_info_get(const char *, mac_info_t *); +extern boolean_t mac_promisc_get(mac_handle_t); + +extern int mac_start(mac_handle_t); +extern void mac_stop(mac_handle_t); + +extern void mac_ioctl(mac_handle_t, queue_t *, mblk_t *); +extern link_state_t mac_link_get(mac_handle_t); +extern void mac_resource_set(mac_client_handle_t, mac_resource_add_t, void *); +extern dev_info_t *mac_devinfo_get(mac_handle_t); +extern void *mac_driver(mac_handle_t); +extern boolean_t mac_capab_get(mac_handle_t, mac_capab_t, void *); +extern boolean_t mac_sap_verify(mac_handle_t, uint32_t, uint32_t *); +extern mblk_t *mac_header(mac_handle_t, const uint8_t *, uint32_t, mblk_t *, + size_t); +extern int mac_header_info(mac_handle_t, mblk_t *, mac_header_info_t *); +extern int mac_vlan_header_info(mac_handle_t, mblk_t *, mac_header_info_t *); +extern mblk_t *mac_header_cook(mac_handle_t, mblk_t *); +extern mblk_t *mac_header_uncook(mac_handle_t, mblk_t *); + +extern void mac_resource_set_common(mac_client_handle_t, + mac_resource_add_t, mac_resource_remove_t, mac_resource_quiesce_t, + mac_resource_restart_t, mac_resource_bind_t, void *); + +extern void mac_perim_enter_by_mh(mac_handle_t, mac_perim_handle_t *); +extern int mac_perim_enter_by_macname(const char *, mac_perim_handle_t *); +extern int mac_perim_enter_by_linkid(datalink_id_t, mac_perim_handle_t *); +extern void mac_perim_exit(mac_perim_handle_t); +extern boolean_t mac_perim_held(mac_handle_t); + +extern uint16_t mac_client_vid(mac_client_handle_t); +extern int mac_vnic_unicast_set(mac_client_handle_t, const uint8_t *); +extern boolean_t mac_client_is_vlan_vnic(mac_client_handle_t); + +extern void mac_client_poll_enable(mac_client_handle_t); +extern void mac_client_poll_disable(mac_client_handle_t); + +extern int mac_resource_ctl_set(mac_client_handle_t, mac_resource_props_t *); +extern void mac_resource_ctl_get(mac_client_handle_t, mac_resource_props_t *); + +/* + * Flow-related APIs for MAC clients. + */ + +extern void mac_link_init_flows(mac_client_handle_t); +extern void mac_link_release_flows(mac_client_handle_t); +extern int mac_link_flow_add(datalink_id_t, char *, flow_desc_t *, + mac_resource_props_t *); +extern int mac_link_flow_remove(char *); +extern int mac_link_flow_modify(char *, mac_resource_props_t *); +extern boolean_t mac_link_has_flows(mac_client_handle_t); + +typedef struct { + char fi_flow_name[MAXFLOWNAMELEN]; + datalink_id_t fi_link_id; + flow_desc_t fi_flow_desc; + mac_resource_props_t fi_resource_props; +} mac_flowinfo_t; + +extern int mac_link_flow_walk(datalink_id_t, + int (*)(mac_flowinfo_t *, void *), void *); +extern int mac_link_flow_info(char *, mac_flowinfo_t *); + +extern void *mac_tx_hold(mac_client_handle_t); +extern void mac_tx_rele(mac_client_handle_t, void *); +extern void mac_rx_client_quiesce(mac_client_handle_t); +extern void mac_rx_client_restart(mac_client_handle_t); +extern void mac_srs_perm_quiesce(mac_client_handle_t, boolean_t); +extern int mac_hwrings_get(mac_client_handle_t, mac_group_handle_t *, + mac_ring_handle_t *, mac_ring_type_t); +extern void mac_hwring_setup(mac_ring_handle_t, mac_resource_handle_t); +extern void mac_hwring_teardown(mac_ring_handle_t); +extern int mac_hwring_disable_intr(mac_ring_handle_t); +extern int mac_hwring_enable_intr(mac_ring_handle_t); +extern int mac_hwring_start(mac_ring_handle_t); +extern void mac_hwring_stop(mac_ring_handle_t); +extern mblk_t *mac_hwring_poll(mac_ring_handle_t, int); +#define MAC_HWRING_POLL(ring, bytes) \ + (((ring)->mr_info.mri_poll) \ + ((ring)->mr_info.mri_driver, (bytes))) + +extern int mac_hwgroup_addmac(mac_group_handle_t, const uint8_t *); +extern int mac_hwgroup_remmac(mac_group_handle_t, const uint8_t *); + +extern void mac_set_upper_mac(mac_client_handle_t, mac_handle_t); + +extern int mac_mark_exclusive(mac_handle_t); +extern void mac_unmark_exclusive(mac_handle_t); + +extern int32_t mac_client_intr_cpu(mac_client_handle_t); +extern void mac_client_set_intr_cpu(void *, mac_client_handle_t, int32_t); +extern void *mac_get_devinfo(mac_handle_t); + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MAC_CLIENT_PRIV_H */ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_provider.h b/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_provider.h new file mode 100644 index 000000000..6960f9229 --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetFlt/solaris/include/mac_provider.h @@ -0,0 +1,498 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009-2010 Oracle Corporation. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_MAC_PROVIDER_H +#define _SYS_MAC_PROVIDER_H + +#include <sys/types.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/stream.h> +#include <sys/mkdev.h> +#include <sys/mac_flow.h> +#include <sys/mac.h> + +/* + * MAC Provider Interface + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MAC version identifier. This is used by mac_alloc() mac_register() to + * verify that incompatible drivers don't register. + */ +#define MAC_VERSION 0x2 + +/* + * Opaque handle types + */ +typedef struct __mac_rule_handle *mac_rule_handle_t; + +/* + * Statistics + */ + +#define XCVR_UNDEFINED 0 +#define XCVR_NONE 1 +#define XCVR_10 2 +#define XCVR_100T4 3 +#define XCVR_100X 4 +#define XCVR_100T2 5 +#define XCVR_1000X 6 +#define XCVR_1000T 7 + +#ifdef _KERNEL + +/* + * Definitions for MAC Drivers Capabilities + */ +/* + * MAC layer capabilities. These capabilities are handled by the drivers' + * mc_capab_get() callbacks. Some capabilities require the driver to fill + * in a given data structure, and others are simply boolean capabilities. + * Note that capability values must be powers of 2 so that consumers and + * providers of this interface can keep track of which capabilities they + * care about by keeping a bitfield of these things around somewhere. + */ +typedef enum { + /* + * Capabilities reserved for internal use only + */ + MAC_CAPAB_VNIC = 0x0001, /* data is mac_capab_vnic_t */ + MAC_CAPAB_ANCHOR_VNIC = 0x0002, /* boolean only, no data */ + MAC_CAPAB_AGGR = 0x0004, /* data is mac_capab_aggr_t */ + MAC_CAPAB_NO_NATIVEVLAN = 0x0008, /* boolean only, no data */ + MAC_CAPAB_NO_ZCOPY = 0x0010, /* boolean only, no data */ + MAC_CAPAB_LEGACY = 0x0020, /* data is mac_capab_legacy_t */ + MAC_CAPAB_VRRP = 0x0040, /* data is mac_capab_vrrp_t */ + + /* + * Public Capabilities + */ + MAC_CAPAB_HCKSUM = 0x0100, /* data is a uint32_t */ + MAC_CAPAB_LSO = 0x0200, /* data is mac_capab_lso_t */ + MAC_CAPAB_RINGS = 0x0400, /* data is mac_capab_rings_t */ + MAC_CAPAB_MULTIFACTADDR = 0x0800, /* mac_data_multifactaddr_t */ + MAC_CAPAB_SHARES = 0x1000 /* data is mac_capab_share_t */ + + /* add new capabilities here */ +} mac_capab_t; + + +/* + * LSO capability + */ +typedef struct lso_basic_tcp_ipv4_s { + t_uscalar_t lso_max; /* maximum payload */ +} lso_basic_tcp_ipv4_t; + +/* + * Currently supported flags for LSO. + */ +#define LSO_TX_BASIC_TCP_IPV4 0x01 /* TCP LSO capability */ + +/* + * Future LSO capabilities can be added at the end of the mac_capab_lso_t. + * When such capability is added to the GLDv3 framework, the size of the + * mac_capab_lso_t it allocates and passes to the drivers increases. Older + * drivers wil access only the (upper) sections of that structure, that is the + * sections carrying the capabilities they understand. This ensures the + * interface can be safely extended in a binary compatible way. + */ +typedef struct mac_capab_lso_s { + t_uscalar_t lso_flags; + lso_basic_tcp_ipv4_t lso_basic_tcp_ipv4; + /* Add future lso capabilities here */ +} mac_capab_lso_t; + +/* + * Multiple Factory MAC Addresses Capability + */ +typedef struct mac_capab_multifactaddr_s { + /* + * Number of factory addresses + */ + uint_t mcm_naddr; + + /* + * Callbacks to query all the factory addresses. + */ + void (*mcm_getaddr)(void *, uint_t, uint8_t *); +} mac_capab_multifactaddr_t; + +/* + * Info and callbacks of legacy devices. + */ +typedef struct mac_capab_legacy_s { + /* + * Notifications that the legacy device does not support. + */ + uint32_t ml_unsup_note; + /* + * dev_t of the legacy device; can be held to force attach. + */ + dev_t ml_dev; + boolean_t (*ml_active_set)(void *); + void (*ml_active_clear)(void *); + int (*ml_fastpath_disable)(void *); + void (*ml_fastpath_enable)(void *); +} mac_capab_legacy_t; + +/* + * MAC driver entry point types. + */ +typedef int (*mac_getstat_t)(void *, uint_t, uint64_t *); +typedef int (*mac_start_t)(void *); +typedef void (*mac_stop_t)(void *); +typedef int (*mac_setpromisc_t)(void *, boolean_t); +typedef int (*mac_multicst_t)(void *, boolean_t, const uint8_t *); +typedef int (*mac_unicst_t)(void *, const uint8_t *); +typedef void (*mac_ioctl_t)(void *, queue_t *, mblk_t *); +typedef void (*mac_resources_t)(void *); +typedef mblk_t *(*mac_tx_t)(void *, mblk_t *); +typedef boolean_t (*mac_getcapab_t)(void *, mac_capab_t, void *); +typedef int (*mac_open_t)(void *); +typedef void (*mac_close_t)(void *); +typedef int (*mac_set_prop_t)(void *, const char *, mac_prop_id_t, + uint_t, const void *); +typedef int (*mac_get_prop_t)(void *, const char *, mac_prop_id_t, + uint_t, uint_t, void *, uint_t *); + +/* + * Drivers must set all of these callbacks except for mc_resources, + * mc_ioctl, and mc_getcapab, which are optional. If any of these optional + * callbacks are set, their appropriate flags must be set in mc_callbacks. + * Any future additions to this list must also be accompanied by an + * associated mc_callbacks flag so that the framework can grow without + * affecting the binary compatibility of the interface. + */ +typedef struct mac_callbacks_s { + uint_t mc_callbacks; /* Denotes which callbacks are set */ + mac_getstat_t mc_getstat; /* Get the value of a statistic */ + mac_start_t mc_start; /* Start the device */ + mac_stop_t mc_stop; /* Stop the device */ + mac_setpromisc_t mc_setpromisc; /* Enable or disable promiscuous mode */ + mac_multicst_t mc_multicst; /* Enable or disable a multicast addr */ + mac_unicst_t mc_unicst; /* Set the unicast MAC address */ + mac_tx_t mc_tx; /* Transmit a packet */ + mac_ioctl_t mc_ioctl; /* Process an unknown ioctl */ + mac_getcapab_t mc_getcapab; /* Get capability information */ + mac_open_t mc_open; /* Open the device */ + mac_close_t mc_close; /* Close the device */ + mac_set_prop_t mc_setprop; + mac_get_prop_t mc_getprop; +} mac_callbacks_t; + +typedef struct mac_priv_prop_s { + char mpp_name[MAXLINKPROPNAME]; + uint_t mpp_flags; +} mac_priv_prop_t; + +/* + * Virtualization Capabilities + */ +/* + * The ordering of entries below is important. MAC_HW_CLASSIFIER + * is the cutoff below which are entries which don't depend on + * H/W. MAC_HW_CLASSIFIER and entries after that are cases where + * H/W has been updated through add/modify/delete APIs. + */ +typedef enum { + MAC_NO_CLASSIFIER = 0, + MAC_SW_CLASSIFIER, + MAC_HW_CLASSIFIER +} mac_classify_type_t; + +typedef void (*mac_rx_func_t)(void *, mac_resource_handle_t, mblk_t *, + boolean_t); + +/* + * The virtualization level conveys the extent of the NIC hardware assistance + * for traffic steering employed for virtualization: + * + * MAC_VIRT_NONE: No assist for v12n. + * + * MAC_VIRT_LEVEL1: Multiple Rx rings with MAC address level + * classification between groups of rings. + * Requires the support of the MAC_CAPAB_RINGS + * capability. + * + * MAC_VIRT_HIO: Hybrid I/O capable MAC. Require the support + * of the MAC_CAPAB_SHARES capability. + * + * MAC_VIRT_SERIALIZE: Temporary flag *ONLY* for nxge. Mac layer + * uses this to enable mac Tx serializer on + * outbound traffic and to always enqueue + * incoming traffic on Rx soft rings in mac. + */ +#define MAC_VIRT_NONE 0x0 +#define MAC_VIRT_LEVEL1 0x1 +#define MAC_VIRT_HIO 0x2 +#define MAC_VIRT_SERIALIZE 0x4 + +typedef enum { + MAC_RING_TYPE_RX = 1, /* Receive ring */ + MAC_RING_TYPE_TX /* Transmit ring */ +} mac_ring_type_t; + +#define MAX_RINGS_PER_GROUP 128 + +/* + * Grouping type of a ring group + * + * MAC_GROUP_TYPE_STATIC: The ring group can not be re-grouped. + * MAC_GROUP_TYPE_DYNAMIC: The ring group support dynamic re-grouping + */ +typedef enum { + MAC_GROUP_TYPE_STATIC = 1, /* Static ring group */ + MAC_GROUP_TYPE_DYNAMIC /* Dynamic ring group */ +} mac_group_type_t; + +typedef struct __mac_ring_driver *mac_ring_driver_t; +typedef struct __mac_group_driver *mac_group_driver_t; + +typedef struct mac_ring_info_s mac_ring_info_t; +typedef struct mac_group_info_s mac_group_info_t; + +typedef void (*mac_get_ring_t)(void *, mac_ring_type_t, const int, const int, + mac_ring_info_t *, mac_ring_handle_t); +typedef void (*mac_get_group_t)(void *, mac_ring_type_t, const int, + mac_group_info_t *, mac_group_handle_t); + +typedef void (*mac_group_add_ring_t)(mac_group_driver_t, + mac_ring_driver_t, mac_ring_type_t); +typedef void (*mac_group_rem_ring_t)(mac_group_driver_t, + mac_ring_driver_t, mac_ring_type_t); + +/* + * Multiple Rings Capability + */ +typedef struct mac_capab_rings_s { + mac_ring_type_t mr_type; /* Ring type: Rx vs Tx */ + mac_group_type_t mr_group_type; /* Dynamic vs static grouping */ + uint_t mr_rnum; /* Number of rings */ + uint_t mr_gnum; /* Number of ring groups */ + mac_get_ring_t mr_rget; /* Get ring from driver */ + mac_get_group_t mr_gget; /* Get ring group from driver */ + mac_group_add_ring_t mr_gaddring; /* Add ring into a group */ + mac_group_rem_ring_t mr_gremring; /* Remove ring from a group */ +} mac_capab_rings_t; + +/* + * Common ring functions and driver interfaces + */ +typedef int (*mac_ring_start_t)(mac_ring_driver_t, uint64_t); +typedef void (*mac_ring_stop_t)(mac_ring_driver_t); + +typedef mblk_t *(*mac_ring_send_t)(void *, mblk_t *); +typedef mblk_t *(*mac_ring_poll_t)(void *, int); + +typedef struct mac_ring_info_s { + mac_ring_driver_t mri_driver; + mac_ring_start_t mri_start; + mac_ring_stop_t mri_stop; + mac_intr_t mri_intr; + union { + mac_ring_send_t send; + mac_ring_poll_t poll; + } mrfunion; +} mac_ring_info_s; + +#define mri_tx mrfunion.send +#define mri_poll mrfunion.poll + +typedef int (*mac_group_start_t)(mac_group_driver_t); +typedef void (*mac_group_stop_t)(mac_group_driver_t); +typedef int (*mac_add_mac_addr_t)(void *, const uint8_t *); +typedef int (*mac_rem_mac_addr_t)(void *, const uint8_t *); + +struct mac_group_info_s { + mac_group_driver_t mgi_driver; /* Driver reference */ + mac_group_start_t mgi_start; /* Start the group */ + mac_group_stop_t mgi_stop; /* Stop the group */ + uint_t mgi_count; /* Count of rings */ + mac_intr_t mgi_intr; /* Optional per-group intr */ + + /* Only used for rx groups */ + mac_add_mac_addr_t mgi_addmac; /* Add a MAC address */ + mac_rem_mac_addr_t mgi_remmac; /* Remove a MAC address */ +}; + +/* + * Share management functions. + */ +typedef uint64_t mac_share_handle_t; + +/* + * Allocate and free a share. Returns ENOSPC if all shares have been + * previously allocated. + */ +typedef int (*mac_alloc_share_t)(void *, mac_share_handle_t *); +typedef void (*mac_free_share_t)(mac_share_handle_t); + +/* + * Bind and unbind a share. Binding a share allows a domain + * to have direct access to the groups and rings associated with + * that share. + */ +typedef int (*mac_bind_share_t)(mac_share_handle_t, uint64_t, uint64_t *); +typedef void (*mac_unbind_share_t)(mac_share_handle_t); + +/* + * Return information on about a share. + */ +typedef void (*mac_share_query_t)(mac_share_handle_t, mac_ring_type_t, + mac_ring_handle_t *, uint_t *); + +/* + * Basic idea, bind previously created ring groups to shares + * for them to be exported (or shared) by another domain. + * These interfaces bind/unbind the ring group to a share. + * The groups and their rings will be shared with the guest + * as soon as the share is bound. + */ +typedef int (*mac_share_add_group_t)(mac_share_handle_t, + mac_group_driver_t); +typedef int (*mac_share_rem_group_t)(mac_share_handle_t, + mac_group_driver_t); + +typedef struct mac_capab_share_s { + uint_t ms_snum; /* Number of shares (vr's) */ + void *ms_handle; /* Handle to driver. */ + mac_alloc_share_t ms_salloc; /* Get a share from driver. */ + mac_free_share_t ms_sfree; /* Return a share to driver. */ + mac_share_add_group_t ms_sadd; /* Add a group to the share. */ + mac_share_rem_group_t ms_sremove; /* Remove group from share. */ + mac_share_query_t ms_squery; /* Query share constraints */ + mac_bind_share_t ms_sbind; /* Bind a share */ + mac_unbind_share_t ms_sunbind; /* Unbind a share */ +} mac_capab_share_t; + +typedef struct mac_capab_vrrp_s { + /* IPv6 or IPv4? */ + int mcv_af; +} mac_capab_vrrp_t; + +/* + * MAC registration interface + */ +typedef struct mac_register_s { + uint_t m_version; /* set by mac_alloc() */ + const char *m_type_ident; + void *m_driver; /* Driver private data */ + dev_info_t *m_dip; + uint_t m_instance; + uint8_t *m_src_addr; + uint8_t *m_dst_addr; + mac_callbacks_t *m_callbacks; + uint_t m_min_sdu; + uint_t m_max_sdu; + void *m_pdata; + size_t m_pdata_size; + uint32_t m_margin; + mac_priv_prop_t *m_priv_props; + size_t m_priv_prop_count; + uint32_t m_v12n; /* Virtualization level */ +} mac_register_t; + +/* + * Flags for mc_callbacks. Requiring drivers to set the flags associated + * with optional callbacks initialized in the structure allows the mac + * module to add optional callbacks in the future without requiring drivers + * to recompile. + */ +#define MC_IOCTL 0x001 +#define MC_GETCAPAB 0x002 +#define MC_OPEN 0x004 +#define MC_CLOSE 0x008 +#define MC_SETPROP 0x010 +#define MC_GETPROP 0x020 + +/* + * Driver interface functions. + */ +extern void mac_sdu_get(mac_handle_t, uint_t *, uint_t *); +extern int mac_maxsdu_update(mac_handle_t, uint_t); + +extern mac_register_t *mac_alloc(uint_t); +extern void mac_free(mac_register_t *); +extern int mac_register(mac_register_t *, mac_handle_t *); +extern int mac_disable_nowait(mac_handle_t); +extern int mac_disable(mac_handle_t); +extern int mac_unregister(mac_handle_t); +extern void mac_rx(mac_handle_t, mac_resource_handle_t, + mblk_t *); +extern void mac_rx_ring(mac_handle_t, mac_ring_handle_t, + mblk_t *, uint64_t); +extern void mac_link_update(mac_handle_t, link_state_t); +extern void mac_link_redo(mac_handle_t, link_state_t); +extern void mac_unicst_update(mac_handle_t, + const uint8_t *); +extern void mac_dst_update(mac_handle_t, const uint8_t *); +extern void mac_tx_update(mac_handle_t); +extern void mac_tx_ring_update(mac_handle_t, + mac_ring_handle_t); +extern void mac_capab_update(mac_handle_t); +extern int mac_pdata_update(mac_handle_t, void *, + size_t); +extern void mac_multicast_refresh(mac_handle_t, + mac_multicst_t, void *, boolean_t); +extern void mac_unicst_refresh(mac_handle_t, mac_unicst_t, + void *); +extern void mac_promisc_refresh(mac_handle_t, + mac_setpromisc_t, void *); +extern boolean_t mac_margin_update(mac_handle_t, uint32_t); +extern void mac_margin_get(mac_handle_t, uint32_t *); +extern int mac_margin_remove(mac_handle_t, uint32_t); +extern int mac_margin_add(mac_handle_t, uint32_t *, + boolean_t); +extern void mac_init_ops(struct dev_ops *, const char *); +extern void mac_fini_ops(struct dev_ops *); +extern int mac_devt_to_instance(dev_t); +extern minor_t mac_private_minor(void); + +extern mactype_register_t *mactype_alloc(uint_t); +extern void mactype_free(mactype_register_t *); +extern int mactype_register(mactype_register_t *); +extern int mactype_unregister(const char *); + +extern boolean_t mac_unicst_verify(mac_handle_t, + const uint8_t *, uint_t); + +extern int mac_group_add_ring(mac_group_handle_t, int); +extern void mac_group_rem_ring(mac_group_handle_t, + mac_ring_handle_t); + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MAC_PROVIDER_H */ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/solaris/vboxflt.conf b/src/VBox/HostDrivers/VBoxNetFlt/solaris/vboxflt.conf index 2fe35f518..38737beaf 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/solaris/vboxflt.conf +++ b/src/VBox/HostDrivers/VBoxNetFlt/solaris/vboxflt.conf @@ -2,7 +2,7 @@ # Sun VirtualBox # Solaris Host VBoxFlt Configuration # -# Copyright (C) 2008-2009 Sun Microsystems, Inc. +# Copyright (C) 2008-2009 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -12,10 +12,6 @@ # VirtualBox OSE distribution. VirtualBox OSE is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -# Clara, CA 95054 USA or visit http://www.sun.com if you need -# additional information or have any questions. -# # This needs to go into /platform/i86pc/kernel/drv, # while the 64-bit driver object goes into the amd64 diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpInstall.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpInstall.cpp index b441034a3..303508892 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpInstall.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpInstall.cpp @@ -1,10 +1,10 @@ -/* $Id: NetAdpInstall.cpp $ */ +/* $Id: NetAdpInstall.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * NetAdpInstall - VBoxNetAdp installer command line tool */ /* - * Copyright (C) 2009 Sun Microsystems, Inc. + * Copyright (C) 2009 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #include <vbox/WinNetConfig.h> diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpUninstall.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpUninstall.cpp index c53977320..c2628ad9f 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpUninstall.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/NetAdpUninstall.cpp @@ -1,10 +1,10 @@ -/* $Id: NetAdpUninstall.cpp $ */ +/* $Id: NetAdpUninstall.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * NetAdpUninstall - VBoxNetAdp uninstaller command line tool */ /* - * Copyright (C) 2009 Sun Microsystems, Inc. + * Copyright (C) 2009 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #include <vbox/WinNetConfig.h> diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltInstall.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltInstall.cpp index b0d00d2e5..ef3aa122b 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltInstall.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltInstall.cpp @@ -1,10 +1,10 @@ -/* $Id: NetFltInstall.cpp $ */ +/* $Id: NetFltInstall.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * NetFltInstall - VBoxNetFlt installer command line tool */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #include <vbox/WinNetConfig.h> @@ -36,14 +32,13 @@ static VOID winNetCfgLogger (LPCWSTR szString) } /** Wrapper aroung GetfullPathNameW that will try an alternative INF location. - * - * The default location is the current directory. If not found there, the - * alternative locatoin is the executable directory. If not found there either, - * the first alternative is present to the caller. - */ + * + * The default location is the current directory. If not found there, the + * alternative locatoin is the executable directory. If not found there either, + * the first alternative is present to the caller. + */ static DWORD MyGetfullPathNameW(LPCWSTR pwszName, size_t cchFull, LPWSTR pwszFull) { -#ifdef DEBUG_bird /** @todo make this default behavior after 3.1. */ LPWSTR pwszFilePart; DWORD dwSize = GetFullPathNameW(pwszName, cchFull, pwszFull, &pwszFilePart); if(dwSize <= 0) @@ -65,7 +60,7 @@ static DWORD MyGetfullPathNameW(LPCWSTR pwszName, size_t cchFull, LPWSTR pwszFul if(!wsz[cch]) { dwSize = GetFullPathNameW(wsz, cchFull, pwszFull, NULL); - if( dwSize > 0 + if( dwSize > 0 && GetFileAttributesW(pwszFull) != INVALID_FILE_ATTRIBUTES) return dwSize; break; @@ -76,7 +71,6 @@ static DWORD MyGetfullPathNameW(LPCWSTR pwszName, size_t cchFull, LPWSTR pwszFul } /* fallback */ -#endif return GetFullPathNameW(pwszName, cchFull, pwszFull, NULL); } diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltUninstall.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltUninstall.cpp index a40f9edc5..711042dd0 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltUninstall.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/NetFltUninstall.cpp @@ -1,10 +1,10 @@ -/* $Id: NetFltUninstall.cpp $ */ +/* $Id: NetFltUninstall.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * NetFltUninstall - VBoxNetFlt uninstaller command line tool */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #include <vbox/WinNetConfig.h> diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetAdp.inf b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetAdp.inf index 6907c1e89..5b4b226e7 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetAdp.inf +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetAdp.inf @@ -3,7 +3,7 @@ ; ; -; Copyright (C) 2008 Sun Microsystems, Inc. +; Copyright (C) 2008 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ ; VirtualBox OSE distribution. VirtualBox OSE is distributed in the ; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. ; -; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -; Clara, CA 95054 USA or visit http://www.sun.com if you need -; additional information or have any questions. -; ; ; Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.c b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.c index ae53204dc..056bfdc12 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.c @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFlt-win.c $ */ +/* $Id: VBoxNetFlt-win.c 29108 2010-05-05 20:17:42Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Integration with IntNet/NetFlt */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. @@ -24,6 +20,7 @@ */ #include "VBoxNetFltCommon-win.h" +#include <VBox/intnetinline.h> #include <iprt/thread.h> /** represents the job element of the job queue @@ -157,7 +154,7 @@ DECLHIDDEN(void) vboxNetFltWinWaitDereference(PADAPT_DEVICE pState) if(CurNanoTS - StartNanoTS > 20000000) { DBGPRINT(("device not idle")); - Assert(0); + AssertFailed(); // break; } #endif @@ -179,9 +176,9 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMemAlloc(PVOID* ppMemBuf, UINT cbLength) } /* frees memory allocated with vboxNetFltWinMemAlloc */ -DECLHIDDEN(void) vboxNetFltWinMemFree(PVOID pMemBuf) +DECLHIDDEN(void) vboxNetFltWinMemFree(PVOID pvMemBuf) { - NdisFreeMemory(pMemBuf, 0, 0); + NdisFreeMemory(pvMemBuf, 0, 0); } /* frees ndis buffers used on send/receive */ @@ -262,7 +259,7 @@ static NDIS_STATUS vboxNetFltWinPpAllocatePacketInfoPool(PPACKET_INFO_POOL pPool } else { - Assert(0); + AssertFailed(); } return fStatus; @@ -288,7 +285,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinCopyString(PNDIS_STRING pDst, PNDIS_STRING { if(pDst->MaximumLength < pSrc->Length) { - Assert(0); + AssertFailed(); Status = NDIS_STATUS_RESOURCES; } else @@ -307,35 +304,13 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinCopyString(PNDIS_STRING pDst, PNDIS_STRING /************************************************************************************ * PINTNETSG pSG manipulation functions ************************************************************************************/ -static void vboxNetFltWinReinitSG(PINTNETSG pSG) -{ - pSG->pvOwnerData = NULL; - pSG->pvUserData = NULL; - pSG->pvUserData2 = NULL; - pSG->cUsers = 1; - pSG->fFlags = INTNETSG_FLAGS_TEMP; - pSG->cSegsUsed = 0; - pSG->cbTotal = 0; -} - -static void vboxNetFltWinInitSG(PINTNETSG pSG, UINT cBufferCount) -{ - pSG->pvOwnerData = NULL; - pSG->pvUserData = NULL; - pSG->pvUserData2 = NULL; - pSG->cUsers = 1; - pSG->fFlags = INTNETSG_FLAGS_TEMP; - pSG->cSegsAlloc = cBufferCount; - pSG->cSegsUsed = 0; - pSG->cbTotal = 0; -} /* moves the contents of the given NDIS_BUFFER and all other buffers chained to it to the PINTNETSG * the PINTNETSG is expected to contain one segment whose bugger is large enough to maintain * the contents of the given NDIS_BUFFER and all other buffers chained to it */ static NDIS_STATUS vboxNetFltWinNdisBufferMoveToSG0(PNDIS_BUFFER pBuffer, PINTNETSG pSG) { - UINT cbSeg = 0; + UINT cSegs = 0; PINTNETSEG paSeg; uint8_t * ptr; PVOID pVirtualAddress; @@ -388,7 +363,7 @@ static NDIS_STATUS vboxNetFltWinNdisBufferMoveToSG0(PNDIS_BUFFER pBuffer, PINTNE * ndis buffer(s) point to (as opposed to vboxNetFltWinNdisBufferMoveToSG0 which copies the memory from ndis buffers(s) to PINTNETSG) */ static NDIS_STATUS vboxNetFltWinNdisBuffersToSG(PNDIS_BUFFER pBuffer, PINTNETSG pSG) { - UINT cbSeg = 0; + UINT cSegs = 0; NDIS_STATUS fStatus = NDIS_STATUS_SUCCESS; PVOID pVirtualAddress; UINT cbCurrentLength; @@ -407,21 +382,21 @@ static NDIS_STATUS vboxNetFltWinNdisBuffersToSG(PNDIS_BUFFER pBuffer, PINTNETSG } pSG->cbTotal += cbCurrentLength; - pSG->aSegs[cbSeg].cb = cbCurrentLength; - pSG->aSegs[cbSeg].pv = pVirtualAddress; - pSG->aSegs[cbSeg].Phys = NIL_RTHCPHYS; - cbSeg++; + pSG->aSegs[cSegs].cb = cbCurrentLength; + pSG->aSegs[cSegs].pv = pVirtualAddress; + pSG->aSegs[cSegs].Phys = NIL_RTHCPHYS; + cSegs++; NdisGetNextBuffer( pBuffer, &pBuffer); } - AssertFatal(cbSeg <= pSG->cSegsAlloc); + AssertFatal(cSegs <= pSG->cSegsAlloc); if(fStatus == NDIS_STATUS_SUCCESS) { - pSG->cSegsUsed = cbSeg; + pSG->cSegsUsed = cSegs; } return fStatus; @@ -432,13 +407,13 @@ static void vboxNetFltWinDeleteSG(PINTNETSG pSG) vboxNetFltWinMemFree(pSG); } -static PINTNETSG vboxNetFltWinCreateSG(uint32_t cSize) +static PINTNETSG vboxNetFltWinCreateSG(uint32_t cSegs) { PINTNETSG pSG; - NTSTATUS Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, RT_OFFSETOF(INTNETSG, aSegs[cSize])); + NTSTATUS Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, RT_OFFSETOF(INTNETSG, aSegs[cSegs])); if(Status == STATUS_SUCCESS) { - vboxNetFltWinInitSG(pSG, cSize); + IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/); return pSG; } @@ -448,7 +423,7 @@ static PINTNETSG vboxNetFltWinCreateSG(uint32_t cSize) /************************************************************************************ * packet queue functions ************************************************************************************/ - +#ifndef VBOXNETFLT_NO_PACKET_QUEUE #if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) static NDIS_STATUS vboxNetFltWinQuPostPacket(PADAPT pAdapt, PNDIS_PACKET pPacket, PINTNETSG pSG, uint32_t fFlags # ifdef DEBUG_NETFLT_PACKETS @@ -548,7 +523,7 @@ static NDIS_STATUS vboxNetFltWinQuPostPacket(PADAPT pAdapt, PNDIS_PACKET pPacket /* should never be here since the PINTNETSG is stored only when the underlying miniport * indicates NDIS_STATUS_RESOURCES, we should never have this when processing * the "from-host" packets */ - Assert(0); + AssertFailed(); LogFlow(("status is not pending, freeing myPacket (%p)\n", pMyPacket)); vboxNetFltWinFreeSGNdisPacket(pMyPacket, false); } @@ -565,7 +540,7 @@ static NDIS_STATUS vboxNetFltWinQuPostPacket(PADAPT pAdapt, PNDIS_PACKET pPacket else { /*we failed to create our packet */ - Assert(0); + AssertFailed(); fStatus = NDIS_STATUS_FAILURE; } @@ -573,24 +548,30 @@ static NDIS_STATUS vboxNetFltWinQuPostPacket(PADAPT pAdapt, PNDIS_PACKET pPacket } #endif -static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_WORKER pWorker, PPACKET_INFO pInfo) +static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_WORKER pWorker, PVOID pvPacket, const UINT fFlags) +#else +DECLHIDDEN(bool) vboxNetFltWinPostIntnet(PVBOXNETFLTINS pNetFltIf, PVOID pvPacket, const UINT fFlags) +#endif { PNDIS_PACKET pPacket = NULL; PINTNETSG pSG = NULL; PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pNetFltIf); - UINT fFlags; NDIS_STATUS Status; #ifndef VBOXNETADP bool bSrcHost; - bool bPending; bool bDropIt; +# ifndef VBOXNETFLT_NO_PACKET_QUEUE + bool bPending; +# endif +#endif +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + bool bDeleteSG = false; #endif #ifdef DEBUG_NETFLT_PACKETS /* packet used for matching */ PNDIS_PACKET pTmpPacket = NULL; #endif - fFlags = GET_FLAGS_FROM_INFO(pInfo); #ifndef VBOXNETADP bSrcHost = (fFlags & PACKET_SRC_HOST) != 0; #endif @@ -618,7 +599,8 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W UINT uBytesCopied = 0; UINT cbPacketLength; - pPacket = (PNDIS_PACKET)GET_PACKET_FROM_INFO(pInfo); + pPacket = (PNDIS_PACKET)pvPacket; + LogFlow(("ndis packet info, packet (%p)\n", pPacket)); LogFlow(("preparing pSG")); @@ -631,6 +613,9 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W Assert(cBufferCount); +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + pSG = vboxNetFltWinCreateSG(cBufferCount); +#else /* we can not allocate the INTNETSG on stack since in this case we may get stack overflow * somewhere outside of our driver (3 pages of system thread stack does not seem to be enough) * @@ -651,11 +636,15 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W LogRel(("Failed to reallocate the pSG\n")); } } +#endif if(pSG) { +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + bDeleteSG = true; +#endif /* reinitialize */ - vboxNetFltWinReinitSG(pSG); + IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, pSG->cSegsAlloc, 0 /*cSegsUsed*/); /* convert the ndis buffers to INTNETSG */ Status = vboxNetFltWinNdisBuffersToSG(pCurrentBuffer, pSG); @@ -683,7 +672,7 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W #else /* we have both host and wire in ProtocolReceive */ #endif - pSG = (PINTNETSG)GET_PACKET_FROM_INFO(pInfo); + pSG = (PINTNETSG)pvPacket; LogFlow(("not ndis packet info, pSG (%p)\n", pSG)); } @@ -728,13 +717,15 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W } #endif -#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) +#ifndef VBOXNETFLT_NO_PACKET_QUEUE + +# if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) if(!bDropIt) { Status = vboxNetFltWinQuPostPacket(pAdapt, pPacket, pSG, fFlags -# ifdef DEBUG_NETFLT_PACKETS +# ifdef DEBUG_NETFLT_PACKETS , pTmpPacket -# endif +# endif ); if(Status == NDIS_STATUS_PENDING) @@ -745,7 +736,7 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W } } else -#endif +# endif { Status = NDIS_STATUS_SUCCESS; } @@ -755,32 +746,32 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W { if(!(fFlags & PACKET_MINE)) { -#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) +# if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) /* complete the packets */ if(fFlags & PACKET_SRC_HOST) { -#endif -#ifndef VBOX_NETFLT_ONDEMAND_BIND +# endif +# ifndef VBOX_NETFLT_ONDEMAND_BIND /* NDIS_SET_PACKET_STATUS(pPacket, Status); */ NdisMSendComplete(pAdapt->hMiniportHandle, pPacket, Status); -#endif -#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) +# endif +# if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) } else { -#endif -#ifndef VBOXNETADP +# endif +# ifndef VBOXNETADP NdisReturnPackets(&pPacket, 1); -#endif -#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) +# endif +# if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP) } -#endif +# endif } else { -#ifndef VBOX_NETFLT_ONDEMAND_BIND +# ifndef VBOX_NETFLT_ONDEMAND_BIND Assert(!(fFlags & PACKET_SRC_HOST)); -#endif +# endif vboxNetFltWinFreeSGNdisPacket(pPacket, true); } } @@ -789,9 +780,9 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W Assert(pSG); vboxNetFltWinMemFree(pSG); } -#ifndef VBOXNETADP +# ifndef VBOXNETADP bPending = false; -#endif +# endif } while(0); #ifdef DEBUG_NETFLT_PACKETS @@ -806,7 +797,17 @@ static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_W #else return false; #endif +#else /* #ifdef VBOXNETFLT_NO_PACKET_QUEUE */ + } while(0); +# ifndef VBOXNETADP + return bDropIt; +# else + return true; +# endif +#endif } + +#ifndef VBOXNETFLT_NO_PACKET_QUEUE /* * thread start function for the thread which processes the packets enqueued in our send and receive callbacks called by ndis * @@ -870,7 +871,7 @@ static VOID vboxNetFltWinQuPacketQueueWorkerThreadProc(PVBOXNETFLTINS pNetFltIf) LogFlow(("==> found info (%p)\n", pInfo)); - if(vboxNetFltWinQuProcessInfo(pNetFltIf, pWorker, pInfo)) + if(vboxNetFltWinQuProcessInfo(pNetFltIf, pWorker, pInfo->pPacket, pInfo->fFlags)) { cNumPostedToHostWire++; } @@ -895,7 +896,7 @@ static VOID vboxNetFltWinQuPacketQueueWorkerThreadProc(PVBOXNETFLTINS pNetFltIf) PsTerminateSystemThread(STATUS_SUCCESS); } - +#endif /** * thread start function for the job processing thread * @@ -1077,6 +1078,8 @@ static void vboxNetFltWinJobFiniQueue(PJOB_QUEUE pQueue) } } +#ifndef VBOXNETFLT_NO_PACKET_QUEUE + /** * initializes the packet queue * */ @@ -1136,12 +1139,12 @@ DECLHIDDEN(void) vboxNetFltWinQuFiniPacketQueue(PVBOXNETFLTINS pInstance) // Assert(pAdapt->pPacketQueueSG); /* using the pPacketQueueSG as an indicator that the packet queue is initialized */ - RTSpinlockAcquire((pInstance)->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts((pInstance)->hSpinlock, &Tmp); if(pWorker->pSG) { pSG = pWorker->pSG; pWorker->pSG = NULL; - RTSpinlockRelease((pInstance)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pInstance)->hSpinlock, &Tmp); KeSetEvent(&pWorker->KillEvent, 0, FALSE); KeWaitForSingleObject(pWorker->pThread, Executive, @@ -1155,50 +1158,36 @@ DECLHIDDEN(void) vboxNetFltWinQuFiniPacketQueue(PVBOXNETFLTINS pInstance) } else { - RTSpinlockRelease((pInstance)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pInstance)->hSpinlock, &Tmp); } } +#endif + /* * creates the INTNETSG containing one segment pointing to the buffer of size cbBufSize * the INTNETSG created should be cleaned with vboxNetFltWinMemFree */ -DECLHIDDEN(NDIS_STATUS) vboxNetFltWinAllocSG(UINT cbBufSize, PINTNETSG *ppSG) +DECLHIDDEN(NDIS_STATUS) vboxNetFltWinAllocSG(UINT cbPacket, PINTNETSG *ppSG) { - UINT cbBufferOffset; - UINT cbMemSize; NDIS_STATUS Status; PINTNETSG pSG; /* allocation: * 1. SG_PACKET - with one aSegs pointing to - * 2. buffer of cbPacketLength containing the entire packet */ - cbBufferOffset = sizeof(INTNETSG); - /* make sure the buffer is aligned */ - if((cbBufferOffset & (sizeof(PVOID) - 1)) != 0) - { - cbBufferOffset += sizeof(PVOID); - cbBufferOffset &= ~(sizeof(PVOID) - 1); - } - - cbMemSize = cbBufferOffset + cbBufSize; - Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, cbMemSize); + * 2. buffer of cbPacket containing the entire packet */ + AssertCompileSizeAlignment(INTNETSG, sizeof(PVOID)); + Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, cbPacket + sizeof(INTNETSG)); if(Status == NDIS_STATUS_SUCCESS) { - vboxNetFltWinInitSG(pSG, 1); - pSG->aSegs[0].pv = (uint8_t *)pSG + cbBufferOffset; - pSG->aSegs[0].Phys = NIL_RTHCPHYS; - pSG->aSegs[0].cb = cbBufSize; - pSG->cbTotal = cbBufSize; - pSG->cSegsUsed = 1; - + IntNetSgInitTemp(pSG, pSG + 1, cbPacket); LogFlow(("pSG created (%p)\n", pSG)); - *ppSG = pSG; } return Status; } +#ifndef VBOXNETFLT_NO_PACKET_QUEUE /** * put the packet info to the queue */ @@ -1209,7 +1198,6 @@ DECLINLINE(void) vboxNetFltWinQuEnqueueInfo(PPACKET_QUEUE_WORKER pWorker, PPACKE KeSetEvent(&pWorker->NotifyEvent, IO_NETWORK_INCREMENT, FALSE); } - /** * puts the packet to the queue * @@ -1251,7 +1239,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, P fStatus = vboxNetFltWinAllocSG(cbPacketLength, &pSG); if(fStatus != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); break; } @@ -1259,7 +1247,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, P if(!pInfo) { - Assert(0); + AssertFailed(); /* TODO: what status to set? */ fStatus = NDIS_STATUS_FAILURE; vboxNetFltWinMemFree(pSG); @@ -1275,7 +1263,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, P fStatus = vboxNetFltWinNdisBufferMoveToSG0(pBuffer, pSG); if(fStatus != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); vboxNetFltWinPpFreePacketInfo(pInfo); vboxNetFltWinMemFree(pSG); break; @@ -1289,7 +1277,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, P if(!pInfo) { - Assert(0); + AssertFailed(); /* TODO: what status to set? */ fStatus = NDIS_STATUS_FAILURE; break; @@ -1307,6 +1295,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, P return fStatus; } +#endif #ifndef VBOX_NETFLT_ONDEMAND_BIND /* @@ -1471,7 +1460,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinGetMacAddress(PADAPT pAdapt, PRTMAC pMac) if(status != NDIS_STATUS_SUCCESS) { /* TODO */ - Assert(0); + AssertFailed(); } return status; @@ -1496,7 +1485,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQueryPhysicalMedium(PADAPT pAdapt, NDIS_PHY else { LogRel(("OID_GEN_PHYSICAL_MEDIUM failed: Status (0x%x)", Status)); - Assert(0); + AssertFailed(); } } return Status; @@ -1519,7 +1508,7 @@ DECLHIDDEN(bool) vboxNetFltWinIsPromiscuous(PADAPT pAdapt) if(status != NDIS_STATUS_SUCCESS) { /* TODO */ - Assert(0); + AssertFailed(); return false; } return (filter & NDIS_PACKET_TYPE_PROMISCUOUS) != 0; @@ -1527,6 +1516,9 @@ DECLHIDDEN(bool) vboxNetFltWinIsPromiscuous(PADAPT pAdapt) DECLHIDDEN(NDIS_STATUS) vboxNetFltWinSetPromiscuous(PADAPT pAdapt, bool bYes) { +/** @todo Need to report changes to the switch via: + * pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, fPromisc); + */ Assert(VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)); if(VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)) { @@ -1543,7 +1535,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinSetPromiscuous(PADAPT pAdapt, bool bYes) if(fStatus != NDIS_STATUS_SUCCESS) { /* TODO: */ - Assert(0); + AssertFailed(); return fStatus; } @@ -1576,7 +1568,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinSetPromiscuous(PADAPT pAdapt, bool bYes) if(fStatus != NDIS_STATUS_SUCCESS) { /* TODO */ - Assert(0); + AssertFailed(); return fStatus; } } @@ -1698,11 +1690,13 @@ DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG NDIS_STATUS fStatus; PNDIS_PACKET pPacket; - Assert(pSG->cSegsUsed == 1); - Assert(pSG->cbTotal == pSG->aSegs[0].cb); Assert(pSG->aSegs[0].pv); Assert(pSG->cbTotal >= sizeof(ETH_HEADER_SIZE)); +/** @todo Hrmpf, how can we fix this assumption? I fear this'll cause data + * corruption and maybe even BSODs ... */ + AssertReturn(pSG->cSegsUsed == 1 || bCopyMemory, NULL); + #ifdef VBOX_NETFLT_ONDEMAND_BIND NdisAllocatePacket(&fStatus, &pPacket, pAdapt->hSendPacketPoolHandle); #elif defined(VBOXNETADP) @@ -1713,7 +1707,7 @@ DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG if(fStatus == NDIS_STATUS_SUCCESS) { PNDIS_BUFFER pBuffer; - PVOID pMemBuf; + PVOID pvMemBuf; /* @todo: generally we do not always need to zero-initialize the complete OOB data here, reinitialize only when/what we need, * however we DO need to reset the status for the packets we indicate via NdisMIndicateReceivePacket to avoid packet loss @@ -1722,38 +1716,38 @@ DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG if(bCopyMemory) { - fStatus = vboxNetFltWinMemAlloc(&pMemBuf, pSG->cbTotal); + fStatus = vboxNetFltWinMemAlloc(&pvMemBuf, pSG->cbTotal); if(fStatus == NDIS_STATUS_SUCCESS) { - NdisMoveMemory(pMemBuf, pSG->aSegs[0].pv, pSG->cbTotal); + IntNetSgRead(pSG, pvMemBuf); } else { - Assert(0); + AssertFailed(); NdisFreePacket(pPacket); pPacket = NULL; } } else { - pMemBuf = pSG->aSegs[0].pv; + pvMemBuf = pSG->aSegs[0].pv; } if(fStatus == NDIS_STATUS_SUCCESS) { #ifdef VBOX_NETFLT_ONDEMAND_BIND NdisAllocateBuffer(&fStatus, &pBuffer, pAdapt->hSendBufferPoolHandle, - pMemBuf, + pvMemBuf, pSG->cbTotal); #elif defined(VBOXNETADP) NdisAllocateBuffer(&fStatus, &pBuffer, pAdapt->hRecvBufferPoolHandle, - pMemBuf, + pvMemBuf, pSG->cbTotal); #else NdisAllocateBuffer(&fStatus, &pBuffer, bToWire ? pAdapt->hSendBufferPoolHandle : pAdapt->hRecvBufferPoolHandle, - pMemBuf, + pvMemBuf, pSG->cbTotal); #endif @@ -1795,10 +1789,10 @@ DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG } else { - Assert(0); + AssertFailed(); if(bCopyMemory) { - vboxNetFltWinMemFree(pMemBuf); + vboxNetFltWinMemFree(pvMemBuf); } NdisFreePacket(pPacket); pPacket = NULL; @@ -1806,7 +1800,7 @@ DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG } else { - Assert(0); + AssertFailed(); NdisFreePacket(pPacket); pPacket = NULL; } @@ -1840,14 +1834,14 @@ DECLHIDDEN(void) vboxNetFltWinFreeSGNdisPacket(PNDIS_PACKET pPacket, bool bFreeM NdisUnchainBufferAtBack(pPacket, &pBuffer); if(pBuffer != NULL) { - PVOID pMemBuf; + PVOID pvMemBuf; UINT cbLength; - NdisQueryBufferSafe(pBuffer, &pMemBuf, &cbLength, NormalPagePriority); + NdisQueryBufferSafe(pBuffer, &pvMemBuf, &cbLength, NormalPagePriority); NdisFreeBuffer(pBuffer); if(bFreeMem) { - vboxNetFltWinMemFree(pMemBuf); + vboxNetFltWinMemFree(pvMemBuf); } } else @@ -1918,7 +1912,7 @@ vboxNetFltWinUnload( if (RT_FAILURE(rc)) { /* TODO: we can not prevent driver unload here */ - Assert(0); + AssertFailed(); Log(("vboxNetFltWinTryFiniIdc - failed, busy.\n")); } @@ -2187,8 +2181,8 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT *ppAdapt, PNDIS_STRING pO RtlFreeAnsiString(&AnsiString); if(RT_FAILURE(rc)) { - Assert(0); - Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE; + AssertFailed(); + Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE; break; } @@ -2204,8 +2198,8 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT *ppAdapt, PNDIS_STRING pO rc = vboxNetFltWinAttachToInterface(pInstance, &Context, true); if(RT_FAILURE(rc)) { - Assert(0); - Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE; + AssertFailed(); + Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE; /* release netflt */ vboxNetFltRelease(pInstance, false); @@ -2270,7 +2264,7 @@ static NDIS_STATUS vboxNetFltWinPtFiniUnbind(PADAPT pAdapt) Status = vboxNetFltWinPtDoUnbinding(pAdapt, true); if(Status != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); /* TODO: should we break ? */ /* break; */ } @@ -2311,7 +2305,9 @@ DECLHIDDEN(VOID) vboxNetFltWinPtFiniPADAPT(PADAPT pAdapt) #ifndef VBOX_NETFLT_ONDEMAND_BIND /* moved to vboxNetFltWinDetachFromInterfaceWorker */ #else +# ifndef VBOXNETFLT_NO_PACKET_QUEUE vboxNetFltWinQuFiniPacketQueue(pAdapt); +# endif #endif vboxNetFltWinFiniBuffers(pAdapt); @@ -2392,7 +2388,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitPADAPT(IN PADAPT pAdapt) Status = vboxNetFltWinMemAlloc((PVOID*)&pAdapt->DeviceName.Buffer, pOurDeviceName->Length); if(Status != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); pAdapt->DeviceName.Buffer = NULL; break; } @@ -2401,7 +2397,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitPADAPT(IN PADAPT pAdapt) Status = vboxNetFltWinCopyString(&pAdapt->DeviceName, pOurDeviceName); if(Status != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); break; } # endif @@ -2445,7 +2441,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitPADAPT(IN PADAPT pAdapt) rc = vboxNetFltWinConnectIt(pNetFlt); if(RT_FAILURE(rc)) { - Assert(0); + AssertFailed(); Status = NDIS_STATUS_FAILURE; break; } @@ -2691,7 +2687,7 @@ DECLHIDDEN(bool) vboxNetFltWinMatchPacketAndSG(PNDIS_PACKET pPacket, PINTNETSG p if(uTotalPacketLength1 != uTotalPacketLength2) { - Assert(0); + AssertFailed(); bMatch = false; } else @@ -2744,7 +2740,7 @@ DECLHIDDEN(bool) vboxNetFltWinMatchPacketAndSG(PNDIS_PACKET pPacket, PINTNETSG p if(memcmp((PVOID*)pMemBuf1, (PVOID*)pMemBuf2, ucbLength2Match)) { bMatch = false; - Assert(0); + AssertFailed(); break; } @@ -2791,7 +2787,7 @@ static bool vboxNetFltWinMatchSGs(PINTNETSG pSG1, PINTNETSG pSG2, const INT cbMa if(uTotalPacketLength1 != uTotalPacketLength2) { - Assert(0); + AssertFailed(); bMatch = false; } else @@ -2833,7 +2829,7 @@ static bool vboxNetFltWinMatchSGs(PINTNETSG pSG1, PINTNETSG pSG2, const INT cbMa if(memcmp(pMemBuf1, pMemBuf2, ucbLength2Match)) { bMatch = false; - Assert(0); + AssertFailed(); break; } ucbMatch -= ucbLength2Match; @@ -2944,7 +2940,7 @@ static int vboxNetFltWinInitIdc() if(g_bIdcInitialized) { #ifdef VBOX_NETFLT_ONDEMAND_BIND - Assert(0); + AssertFailed(); #endif rc = VINF_ALREADY_INITIALIZED; break; @@ -3024,7 +3020,7 @@ static int vboxNetFltWinInitNetFlt() rc = vboxNetFltWinInitNetFltBase(); if(RT_FAILURE(rc)) { - Assert(0); + AssertFailed(); break; } @@ -3037,7 +3033,7 @@ static int vboxNetFltWinInitNetFlt() rc = vboxNetFltWinInitIdc(); if (RT_FAILURE(rc)) { - Assert(0); + AssertFailed(); vboxNetFltWinFiniNetFltBase(); break; } @@ -3059,13 +3055,15 @@ static int vboxNetFltWinDeleteInstance(PVBOXNETFLTINS pThis) Assert(pThis); Assert(pThis->fDisconnectedFromHost); Assert(!pThis->fRediscoveryPending); - Assert(!pThis->fActive); + Assert(pThis->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE); #ifndef VBOXNETADP Assert(pAdapt->PTState.OpState == kVBoxNetDevOpState_Deinitialized); Assert(!pAdapt->hBindingHandle); #endif Assert(pAdapt->MPState.OpState == kVBoxNetDevOpState_Deinitialized); +#ifndef VBOXNETFLT_NO_PACKET_QUEUE Assert(!pThis->u.s.PacketQueueWorker.pSG); +#endif // Assert(!pAdapt->hMiniportHandle); #ifndef VBOX_NETFLT_ONDEMAND_BIND @@ -3075,7 +3073,7 @@ static int vboxNetFltWinDeleteInstance(PVBOXNETFLTINS pThis) Status = vboxNetFltWinPtFiniUnbind(pAdapt); if(Status != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); /* pDetachInfo->Status = VERR_GENERAL_FAILURE; */ } #endif @@ -3087,7 +3085,9 @@ static int vboxNetFltWinDeleteInstance(PVBOXNETFLTINS pThis) static NDIS_STATUS vboxNetFltWinDisconnectIt(PVBOXNETFLTINS pInstance) { +#ifndef VBOXNETFLT_NO_PACKET_QUEUE vboxNetFltWinQuFiniPacketQueue(pInstance); +#endif return NDIS_STATUS_SUCCESS; } @@ -3156,7 +3156,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinDetachFromInterface(PADAPT pAdapt, bool bOn Status = vboxNetFltWinPtFiniUnbind(pAdapt); if(Status != NDIS_STATUS_SUCCESS) { - Assert(0); + AssertFailed(); /* pDetachInfo->Status = VERR_GENERAL_FAILURE; */ } #endif @@ -3187,6 +3187,35 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinDetachFromInterface(PADAPT pAdapt, bool bOn return Status; } + +/** + * Checks if the host (not us) has put the adapter in promiscuous mode. + * + * @returns true if promiscuous, false if not. + * @param pThis The instance. + */ +static bool vboxNetFltWinIsPromiscuous2(PVBOXNETFLTINS pThis) +{ +#ifndef VBOXNETADP + PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pThis); + if(VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)) + { + bool bPromiscuous; + if(!vboxNetFltWinReferenceAdapt(pAdapt)) + return false; + + bPromiscuous = (pAdapt->fUpperProtocolSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == NDIS_PACKET_TYPE_PROMISCUOUS; + /*vboxNetFltWinIsPromiscuous(pAdapt);*/ + + vboxNetFltWinDereferenceAdapt(pAdapt); + return bPromiscuous; + } + return false; +#else + return true; +#endif +} + /** * Worker for vboxNetFltWinAttachToInterface. * @@ -3262,12 +3291,11 @@ static void vboxNetFltWinAttachToInterfaceWorker(PATTACH_INFO pAttachInfo) // vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Initialized); //#endif - RTSpinlockAcquire(pThis->hSpinlock, &Tmp); /* 4. mark as connected */ + RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); - - RTSpinlockRelease(pThis->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); pAttachInfo->Status = VINF_SUCCESS; pAttachInfo->pCreateContext->Status = NDIS_STATUS_SUCCESS; @@ -3276,6 +3304,20 @@ static void vboxNetFltWinAttachToInterfaceWorker(PATTACH_INFO pAttachInfo) vboxNetFltRelease(pThis, false); + /* 5. Report MAC address, promiscuousness and GSO capabilities. */ + /** @todo Keep these up to date, esp. the promiscuous mode bit. */ + if ( pThis->pSwitchPort + && vboxNetFltTryRetainBusyNotDisconnected(pThis)) + { + pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); + pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, + vboxNetFltWinIsPromiscuous2(pThis)); + pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, + INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); + /** @todo We should be able to do pfnXmit at DISPATCH_LEVEL... */ + pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); + vboxNetFltRelease(pThis, true /*fBusy*/); + } return; } AssertBreakpoint(); @@ -3319,7 +3361,7 @@ static void vboxNetFltWinAttachToInterfaceWorker(PATTACH_INFO pAttachInfo) break; } - Status = vboxNetFltWinGetMacAddress(pAdapt, &pThis->u.s.Mac); + Status = vboxNetFltWinGetMacAddress(pAdapt, &pThis->u.s.MacAddr); if (Status != NDIS_STATUS_SUCCESS) { vboxNetFltWinPtFiniUnbind(pAdapt); @@ -3455,7 +3497,7 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) } else { - Assert(0); + AssertFailed(); rc = VERR_NO_MEMORY; } } @@ -3479,7 +3521,7 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) } else { - Assert(0); + AssertFailed(); #ifdef VBOXNETADP STATISTIC_INCREASE(pAdapt->cRxError); #endif @@ -3498,41 +3540,6 @@ int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst) return rc; } -bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis) -{ -#ifndef VBOXNETADP - PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pThis); - if(VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)) - { - bool bPromiscuous; - if(!vboxNetFltWinReferenceAdapt(pAdapt)) - return false; - - bPromiscuous = (pAdapt->fUpperProtocolSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == NDIS_PACKET_TYPE_PROMISCUOUS; - /*vboxNetFltWinIsPromiscuous(pAdapt);*/ - - vboxNetFltWinDereferenceAdapt(pAdapt); - return bPromiscuous; - } - return false; -#else - return true; -#endif -} - -void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac) -{ - *pMac = pThis->u.s.Mac; -} - -bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac) -{ - /* ASSUMES that the MAC address never changes. */ - return pThis->u.s.Mac.au16[0] == pMac->au16[0] - && pThis->u.s.Mac.au16[1] == pMac->au16[1] - && pThis->u.s.Mac.au16[2] == pMac->au16[2]; -} - void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) { #ifndef VBOXNETADP @@ -3544,25 +3551,25 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) * this might include all packets queued for processing */ for(;;) { - if(fActive) - { - if(!pThis->u.s.cModePassThruRefs) - { - break; - } - } - else - { - if(!pThis->u.s.cModeNetFltRefs) - { - break; - } - } - vboxNetFltWinSleep(2); + if(fActive) + { + if(!pThis->u.s.cModePassThruRefs) + { + break; + } + } + else + { + if(!pThis->u.s.cModeNetFltRefs) + { + break; + } + } + vboxNetFltWinSleep(2); } if(!vboxNetFltWinReferenceAdapt(pAdapt)) - return; + return; #ifndef VBOXNETADP /* the packets put to ReceiveQueue Array are currently not holding the references, @@ -3609,7 +3616,7 @@ void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive) if(Status != NDIS_STATUS_SUCCESS) { DBGPRINT(("vboxNetFltWinSetPromiscuous failed, Status (0x%x), fActive (%d)\n", Status, fActive)); - Assert(0); + AssertFailed(); LogRel(("vboxNetFltWinSetPromiscuous failed, Status (0x%x), fActive (%d)\n", Status, fActive)); } } @@ -3658,7 +3665,9 @@ int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis) static void vboxNetFltWinConnectItWorker(PWORKER_INFO pInfo) { +#if !defined(VBOXNETADP) || !defined(VBOXNETFLT_NO_PACKET_QUEUE) NDIS_STATUS Status; +#endif PVBOXNETFLTINS pInstance = pInfo->pNetFltIf; PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pInstance); @@ -3668,10 +3677,13 @@ static void vboxNetFltWinConnectItWorker(PWORKER_INFO pInfo) if(vboxNetFltWinReferenceAdapt(pAdapt)) { #ifndef VBOXNETADP - Status = vboxNetFltWinGetMacAddress(pAdapt, &pInstance->u.s.Mac); + Status = vboxNetFltWinGetMacAddress(pAdapt, &pInstance->u.s.MacAddr); if (Status == NDIS_STATUS_SUCCESS) #endif { +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + pInfo->Status = VINF_SUCCESS; +#else Status = vboxNetFltWinQuInitPacketQueue(pInstance); if(Status == NDIS_STATUS_SUCCESS) { @@ -3681,6 +3693,7 @@ static void vboxNetFltWinConnectItWorker(PWORKER_INFO pInfo) { pInfo->Status = VERR_GENERAL_FAILURE; } +#endif } #ifndef VBOXNETADP else diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.h b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.h index 31d1cac7e..ae00a5a36 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.h +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.h @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFlt-win.h $ */ +/* $Id: VBoxNetFlt-win.h 29108 2010-05-05 20:17:42Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Integration with IntNet/NetFlt */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. @@ -210,6 +206,9 @@ DECLINLINE(void) vboxNetFltWinPpFreePacketInfo(PPACKET_INFO pInfo) /** sets flags to the packet info */ #define SET_FLAGS_TO_INFO(_pPacketInfo, _fFlags) (ASMAtomicUoWriteU32((volatile uint32_t *)&(_pPacketInfo)->fFlags, (_fFlags))) +#ifdef VBOXNETFLT_NO_PACKET_QUEUE +DECLHIDDEN(bool) vboxNetFltWinPostIntnet(PVBOXNETFLTINS pInstance, PVOID pvPacket, const UINT fFlags); +#else DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, PVOID pPacket, const UINT fPacketFlags); #ifndef VBOX_NETFLT_ONDEMAND_BIND @@ -218,6 +217,9 @@ DECLHIDDEN(void) vboxNetFltWinQuFiniPacketQueue(PVBOXNETFLTINS pInstance); DECLHIDDEN(NTSTATUS) vboxNetFltWinQuInitPacketQueue(PVBOXNETFLTINS pInstance); #endif +#endif /* #ifndef VBOXNETFLT_NO_PACKET_QUEUE */ + + #ifndef VBOXNETADP /** * searches the list entry in a single-linked list @@ -426,13 +428,13 @@ extern RTMAC g_vboxNetFltWinVerifyMACGuest; # define VBOXNETFLT_LBVERIFY(_pnf, _p) \ do { \ Assert(!vboxNetFltWinCheckMACs(_p, NULL, &g_vboxNetFltWinVerifyMACGuest)); \ - Assert(!vboxNetFltWinCheckMACs(_p, NULL, &(_pnf)->u.s.Mac)); \ + Assert(!vboxNetFltWinCheckMACs(_p, NULL, &(_pnf)->u.s.MacAddr)); \ } while(0) # define VBOXNETFLT_LBVERIFYSG(_pnf, _p) \ do { \ Assert(!vboxNetFltWinCheckMACsSG(_p, NULL, &g_vboxNetFltWinVerifyMACGuest)); \ - Assert(!vboxNetFltWinCheckMACsSG(_p, NULL, &(_pnf)->u.s.Mac)); \ + Assert(!vboxNetFltWinCheckMACsSG(_p, NULL, &(_pnf)->u.s.MacAddr)); \ } while(0) #else @@ -483,44 +485,44 @@ DECLHIDDEN(void) vboxNetFltWinWaitDereference(PADAPT_DEVICE pState); DECLINLINE(void) vboxNetFltWinReferenceModeNetFlt(PVBOXNETFLTINS pIns) { - ASMAtomicIncU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs); + ASMAtomicIncU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs); } DECLINLINE(void) vboxNetFltWinReferenceModePassThru(PVBOXNETFLTINS pIns) { - ASMAtomicIncU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs); + ASMAtomicIncU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs); } DECLINLINE(void) vboxNetFltWinIncReferenceModeNetFlt(PVBOXNETFLTINS pIns, uint32_t v) { - ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs, v); + ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs, v); } DECLINLINE(void) vboxNetFltWinIncReferenceModePassThru(PVBOXNETFLTINS pIns, uint32_t v) { - ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs, v); + ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs, v); } DECLINLINE(void) vboxNetFltWinDereferenceModeNetFlt(PVBOXNETFLTINS pIns) { - ASMAtomicDecU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs); + ASMAtomicDecU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs); } DECLINLINE(void) vboxNetFltWinDereferenceModePassThru(PVBOXNETFLTINS pIns) { - ASMAtomicDecU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs); + ASMAtomicDecU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs); } DECLINLINE(void) vboxNetFltWinDecReferenceModeNetFlt(PVBOXNETFLTINS pIns, uint32_t v) { - Assert(v); - ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs, (uint32_t)(-((int32_t)v))); + Assert(v); + ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModeNetFltRefs, (uint32_t)(-((int32_t)v))); } DECLINLINE(void) vboxNetFltWinDecReferenceModePassThru(PVBOXNETFLTINS pIns, uint32_t v) { - Assert(v); - ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs, (uint32_t)(-((int32_t)v))); + Assert(v); + ASMAtomicAddU32((volatile uint32_t *)&pIns->u.s.cModePassThruRefs, (uint32_t)(-((int32_t)v))); } DECLINLINE(void) vboxNetFltWinSetPowerState(PADAPT_DEVICE pState, NDIS_DEVICE_POWER_STATE State) @@ -592,7 +594,7 @@ DECLINLINE(void) vboxNetFltWinDereferenceDevices(PADAPT pAdapt, PADAPT_DEVICE pS DECLINLINE(void) vboxNetFltWinDecReferenceDevice(PADAPT pAdapt, PADAPT_DEVICE pState, uint32_t v) { - Assert(v); + Assert(v); ASMAtomicAddU32((uint32_t volatile *)&pState->cReferences, (uint32_t)(-((int32_t)v))); } @@ -606,7 +608,7 @@ DECLINLINE(void) vboxNetFltWinDecReferenceDevices(PADAPT pAdapt, PADAPT_DEVICE p DECLINLINE(bool) vboxNetFltWinDoIncReferenceDevice(PADAPT pAdapt, PADAPT_DEVICE pState, uint32_t v) { - Assert(v); + Assert(v); if (vboxNetFltWinGetPowerState(pState) == NdisDeviceStateD0 && vboxNetFltWinGetOpState(pState) == kVBoxNetDevOpState_Initialized) { ASMAtomicAddU32((uint32_t volatile *)&pState->cReferences, v); @@ -639,22 +641,22 @@ DECLINLINE(PVBOXNETFLTINS) vboxNetFltWinReferenceAdaptNetFltFromAdapt(PADAPT pAd pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt); - RTSpinlockAcquire((pNetFlt)->hSpinlock, &Tmp); - if(!ASMAtomicUoReadBool(&(pNetFlt)->fActive)) + RTSpinlockAcquireNoInts((pNetFlt)->hSpinlock, &Tmp); + if(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE) { - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); return NULL; } if(!vboxNetFltWinDoReferenceDevice(pAdapt, &pAdapt->PTState)) { - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); return NULL; } vboxNetFltRetain((pNetFlt), true /* fBusy */); - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); return pNetFlt; } @@ -663,29 +665,29 @@ DECLINLINE(bool) vboxNetFltWinReferenceAdaptNetFlt(PVBOXNETFLTINS pNetFlt, PADAP { RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts((pNetFlt)->hSpinlock, &Tmp); #ifndef VBOXNETADP if(!vboxNetFltWinDoReferenceDevices(pAdapt, &pAdapt->MPState, &pAdapt->PTState)) #else if(!vboxNetFltWinDoReferenceDevice(pAdapt, &pAdapt->MPState)) #endif { - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); *pbNetFltActive = false; return false; } - if(!ASMAtomicUoReadBool(&(pNetFlt)->fActive)) + if(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE) { - vboxNetFltWinReferenceModePassThru(pNetFlt); - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + vboxNetFltWinReferenceModePassThru(pNetFlt); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); *pbNetFltActive = false; return true; } vboxNetFltRetain((pNetFlt), true /* fBusy */); - vboxNetFltWinReferenceModeNetFlt(pNetFlt); - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + vboxNetFltWinReferenceModeNetFlt(pNetFlt); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); *pbNetFltActive = true; return true; @@ -707,22 +709,22 @@ DECLINLINE(PVBOXNETFLTINS) vboxNetFltWinIncReferenceAdaptNetFltFromAdapt(PADAPT pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt); - RTSpinlockAcquire((pNetFlt)->hSpinlock, &Tmp); - if(!ASMAtomicUoReadBool(&(pNetFlt)->fActive)) + RTSpinlockAcquireNoInts((pNetFlt)->hSpinlock, &Tmp); + if(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE) { - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); return NULL; } if(!vboxNetFltWinDoIncReferenceDevice(pAdapt, &pAdapt->PTState, v)) { - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); return NULL; } vboxNetFltRetain((pNetFlt), true /* fBusy */); - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); /* we have marked it as busy, so can do the res references outside the lock */ for(i = 0; i < v-1; i++) @@ -745,32 +747,32 @@ DECLINLINE(bool) vboxNetFltWinIncReferenceAdaptNetFlt(PVBOXNETFLTINS pNetFlt, PA return false; } - RTSpinlockAcquire((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts((pNetFlt)->hSpinlock, &Tmp); #ifndef VBOXNETADP if(!vboxNetFltWinDoIncReferenceDevices(pAdapt, &pAdapt->MPState, &pAdapt->PTState, v)) #else if(!vboxNetFltWinDoIncReferenceDevice(pAdapt, &pAdapt->MPState, v)) #endif { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); *pbNetFltActive = false; return false; } - if(!ASMAtomicUoReadBool(&(pNetFlt)->fActive)) + if(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE) { - vboxNetFltWinIncReferenceModePassThru(pNetFlt, v); + vboxNetFltWinIncReferenceModePassThru(pNetFlt, v); - RTSpinlockRelease((pNetFlt)->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts((pNetFlt)->hSpinlock, &Tmp); *pbNetFltActive = false; return true; } vboxNetFltRetain(pNetFlt, true /* fBusy */); - vboxNetFltWinIncReferenceModeNetFlt(pNetFlt, v); + vboxNetFltWinIncReferenceModeNetFlt(pNetFlt, v); - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); /* we have marked it as busy, so can do the res references outside the lock */ for(i = 0; i < v-1; i++) @@ -793,14 +795,14 @@ DECLINLINE(void) vboxNetFltWinDecReferenceNetFlt(PVBOXNETFLTINS pNetFlt, uint32_ vboxNetFltRelease(pNetFlt, true); } - vboxNetFltWinDecReferenceModeNetFlt(pNetFlt, n); + vboxNetFltWinDecReferenceModeNetFlt(pNetFlt, n); } DECLINLINE(void) vboxNetFltWinDereferenceNetFlt(PVBOXNETFLTINS pNetFlt) { vboxNetFltRelease(pNetFlt, true); - vboxNetFltWinDereferenceModeNetFlt(pNetFlt); + vboxNetFltWinDereferenceModeNetFlt(pNetFlt); } DECLINLINE(void) vboxNetFltWinDecReferenceAdapt(PADAPT pAdapt, uint32_t v) @@ -836,7 +838,7 @@ DECLINLINE(bool) vboxNetFltWinIncReferenceAdapt(PADAPT pAdapt, uint32_t v) return false; } - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); #ifdef VBOX_NETFLT_ONDEMAND_BIND if(vboxNetFltWinDoIncReferenceDevice(pAdapt, &pAdapt->PTState)) #elif defined(VBOXNETADP) @@ -845,11 +847,11 @@ DECLINLINE(bool) vboxNetFltWinIncReferenceAdapt(PADAPT pAdapt, uint32_t v) if(vboxNetFltWinDoIncReferenceDevices(pAdapt, &pAdapt->MPState, &pAdapt->PTState, v)) #endif { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); return true; } - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); return false; } @@ -857,7 +859,7 @@ DECLINLINE(bool) vboxNetFltWinReferenceAdapt(PADAPT pAdapt) { PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt); RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); #ifdef VBOX_NETFLT_ONDEMAND_BIND if(vboxNetFltWinDoReferenceDevice(pAdapt, &pAdapt->PTState)) #elif defined(VBOXNETADP) @@ -866,11 +868,11 @@ DECLINLINE(bool) vboxNetFltWinReferenceAdapt(PADAPT pAdapt) if(vboxNetFltWinDoReferenceDevices(pAdapt, &pAdapt->MPState, &pAdapt->PTState)) #endif { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); return true; } - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); return false; } diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.rc b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.rc index cad268553..69e252c59 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.rc +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt-win.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Sun Microsystems, Inc. + * Copyright (C) 2009 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -8,10 +8,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #include <windows.h> @@ -29,7 +25,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO FILEVERSION VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0 - PRODUCTVERSION VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0 + PRODUCTVERSION VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0x0L FILEOS VOS_NT_WINDOWS32 @@ -42,11 +38,11 @@ BEGIN BEGIN VALUE "CompanyName", VBOX_RC_COMPANY_NAME VALUE "FileDescription", DESCRIPTION_STR - VALUE "FileVersion", VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0" + VALUE "FileVersion", VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0" VALUE "InternalName", FILENAME_STR VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT VALUE "OriginalFilename", FILENAME_STR - VALUE "ProductName", "Sun VirtualBox\0" + VALUE "ProductName", "Sun VirtualBox\0" VALUE "ProductVersion", VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0" END END diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt.inf b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt.inf index 53bf94320..b11c2b559 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt.inf +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt.inf @@ -3,7 +3,7 @@ ; ; -; Copyright (C) 2008 Sun Microsystems, Inc. +; Copyright (C) 2008 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ ; VirtualBox OSE distribution. VirtualBox OSE is distributed in the ; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. ; -; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -; Clara, CA 95054 USA or visit http://www.sun.com if you need -; additional information or have any questions. -; ; ; Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltA-win.asm b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltA-win.asm deleted file mode 100644 index af47abbd7..000000000 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltA-win.asm +++ /dev/null @@ -1,33 +0,0 @@ -; $Id: VBoxNetFltA-win.asm $ -;; @file -; VBoxNetFlt - Unwind Wrappers for 64-bit NT. -; - -; -; Copyright (C) 2008 Sun Microsystems, Inc. -; -; This file is part of VirtualBox Open Source Edition (OSE), as -; available from http://www.virtualbox.org. This file is free software; -; you can redistribute it and/or modify it under the terms of the GNU -; General Public License (GPL) as published by the Free Software -; Foundation, in version 2 as it comes in the "COPYING" file of the -; VirtualBox OSE distribution. VirtualBox OSE is distributed in the -; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. -; -; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -; Clara, CA 95054 USA or visit http://www.sun.com if you need -; additional information or have any questions. -; - -%include "iprt/ntwrap.mac" - -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortRetain -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortRelease -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortDisconnectAndRelease -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortSetActive -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortWaitForIdle -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortGetMacAddress -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortIsHostMac -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortIsPromiscuous -NtWrapDyn2DrvFunctionWithAllRegParams netfltNtWrap, vboxNetFltPortXmit - diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltCommon-win.h b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltCommon-win.h index 6cd331557..42792a985 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltCommon-win.h +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltCommon-win.h @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFltCommon-win.h $ */ +/* $Id: VBoxNetFltCommon-win.h 29108 2010-05-05 20:17:42Z vboxsync $ */ /** @file * VBoxNetFltCommon.h - Network Filter Driver (Host), Windows Specific Code. Common headeer with commonly used defines and decls */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. @@ -26,15 +22,7 @@ #ifndef ___VBoxNetFltCommon_win_h___ #define ___VBoxNetFltCommon_win_h___ -#ifndef VBOX_NETFLT_ONDEMAND_BIND -# define NDIS_MINIPORT_DRIVER -# define NDIS50_MINIPORT 1 -#endif - -#define BINARY_COMPATIBLE 0 -#define NDIS_WDM 0 -#define NDIS50 1 -#define NTSTRSAFE_LIB +//#define NTSTRSAFE_LIB #ifdef DEBUG //# define DEBUG_NETFLT_PACKETS @@ -187,6 +175,7 @@ typedef struct VBOXNETFLTINS *PVBOXNETFLTINS; * if clear the packet comes from the wire (underlying miniport) */ #define PACKET_SRC_HOST 0x00000002 +#ifndef VBOXNETFLT_NO_PACKET_QUEUE /** flag specifying the packet was originated by our driver * i.e. we could use it on our needs and should not return it * we are enqueueing "our" packets on ProtocolReceive call-back when @@ -197,6 +186,7 @@ typedef struct VBOXNETFLTINS *PVBOXNETFLTINS; /** flag passed to vboxNetFltWinQuEnqueuePacket specifying that the packet should be copied * this is supported for Ndis Packet only */ #define PACKET_COPY 0x00000008 +#endif /** packet queue element containing the packet info */ typedef struct _PACKET_INFO diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.c b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.c index 40304dc7c..f55bb511c 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.c @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFltMp-win.c $ */ +/* $Id: VBoxNetFltMp-win.c 29108 2010-05-05 20:17:42Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Miniport edge of ndis filter driver */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. @@ -30,17 +26,17 @@ #else /** driver handle */ -static NDIS_HANDLE g_hDriverHandle = NULL; +static NDIS_HANDLE g_hDriverHandle = NULL; /** Ndis wrapper handle */ -static NDIS_HANDLE g_hNdisWrapperHandle; +static NDIS_HANDLE g_hNdisWrapperHandle; /** device handle for ioctl interface this is not used currently and should be removed soon */ -static NDIS_HANDLE g_hNdisDeviceHandle = NULL; +static NDIS_HANDLE g_hNdisDeviceHandle = NULL; /** device object used for ioctl interface this is not used currently and should be removed soon */ -static PDEVICE_OBJECT g_pControlDeviceObject = NULL; +static PDEVICE_OBJECT g_pControlDeviceObject = NULL; /** ioctl device ref count */ -static LONG g_cControlDeviceRefs = 0; +static LONG g_cControlDeviceRefs = 0; /** true if control device needs to be dereferenced before destroying */ -static bool g_bControlDeviceReferenced = false; +static bool g_bControlDeviceReferenced = false; enum _DEVICE_STATE { @@ -489,7 +485,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDoDeinitialization(PADAPT pAdapt) * Set the flag that the miniport below is unbinding, so the request handlers will * fail any request comming later */ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); ASMAtomicUoWriteBool(&pNetFlt->fDisconnectedFromHost, true); ASMAtomicUoWriteBool(&pNetFlt->fRediscoveryPending, false); @@ -497,7 +493,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDoDeinitialization(PADAPT pAdapt) vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing); - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); vboxNetFltWinWaitDereference(&pAdapt->MPState); @@ -551,7 +547,7 @@ static NDIS_STATUS vboxNetFltWinMpReadApplyConfig(PADAPT pAdapt, NDIS_HANDLE hMi { rc = vboxNetFltWinMACFromNdisString(&mac, &pParameterValue->ParameterData.StringData); - Assert(RT_SUCCESS(rc)); + AssertRC(rc); if(RT_SUCCESS(rc)) { break; @@ -587,7 +583,7 @@ static NDIS_STATUS vboxNetFltWinMpReadApplyConfig(PADAPT pAdapt, NDIS_HANDLE hMi vboxNetFltWinGenerateMACAddress(&mac); } - pThis->u.s.Mac = mac; + pThis->u.s.MacAddr = mac; return NDIS_STATUS_SUCCESS; } @@ -803,7 +799,7 @@ vboxNetFltWinMpSendPackets( ) { PADAPT pAdapt = (PADAPT)fMiniportAdapterContext; - NDIS_STATUS fStatus; + NDIS_STATUS fStatus = NDIS_STATUS_SUCCESS; UINT i; PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt); bool bNetFltActive; @@ -817,13 +813,13 @@ vboxNetFltWinMpSendPackets( uint32_t cPassThruRefs; if(bNetFltActive) { - cNetFltRefs = cNumberOfPackets; - cPassThruRefs = 0; + cNetFltRefs = cNumberOfPackets; + cPassThruRefs = 0; } else { - cPassThruRefs = cNumberOfPackets; - cNetFltRefs = 0; + cPassThruRefs = cNumberOfPackets; + cNetFltRefs = 0; } for (i = 0; i < cNumberOfPackets; i++) @@ -833,7 +829,12 @@ vboxNetFltWinMpSendPackets( pPacket = pPacketArray[i]; if(!cNetFltRefs - || (fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_SRC_HOST)) != NDIS_STATUS_SUCCESS) +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + || !vboxNetFltWinPostIntnet(pNetFlt, pPacket, PACKET_SRC_HOST) +#else + || (fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_SRC_HOST)) != NDIS_STATUS_SUCCESS +#endif + ) { #ifndef VBOXNETADP fStatus = vboxNetFltWinSendPassThru(pAdapt, pPacket); @@ -862,8 +863,14 @@ vboxNetFltWinMpSendPackets( } else { +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + NdisMSendComplete(pAdapt->hMiniportHandle, + pPacket, + NDIS_STATUS_SUCCESS); +#else cAdaptRefs--; cNetFltRefs--; +#endif } } @@ -1004,11 +1011,11 @@ vboxNetFltWinMpQueryInformation( /* * If the miniport below is binding, fail the request */ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized) { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Status = NDIS_STATUS_FAILURE; break; } @@ -1020,7 +1027,7 @@ vboxNetFltWinMpQueryInformation( && (pAdapt->bStandingBy == FALSE)) { pAdapt->bQueuedRequest = TRUE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Status = NDIS_STATUS_PENDING; break; } @@ -1029,13 +1036,13 @@ vboxNetFltWinMpQueryInformation( */ if (pAdapt->bStandingBy == TRUE) { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Status = NDIS_STATUS_FAILURE; break; } pAdapt->bOutstandingRequests = TRUE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)) { bool fNetFltActive; @@ -1053,14 +1060,14 @@ vboxNetFltWinMpQueryInformation( vboxNetFltWinDereferenceNetFlt(pNetFlt); vboxNetFltWinDereferenceAdapt(pAdapt); - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); pAdapt->bOutstandingRequests = FALSE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); break; } else if(fAdaptActive) { - pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_PASSTHRU; + pAdapt->fProcessingPacketFilter = VBOXNETFLT_PFP_PASSTHRU; /* we're cleaning it in RequestComplete */ } } @@ -1349,10 +1356,10 @@ vboxNetFltWinMpSetInformation( /* * If the miniport below is unbinding, fail the request */ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); if (vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized) { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Status = NDIS_STATUS_FAILURE; break; } @@ -1365,7 +1372,7 @@ vboxNetFltWinMpSetInformation( && (pAdapt->bStandingBy == FALSE)) { pAdapt->bQueuedRequest = TRUE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Status = NDIS_STATUS_PENDING; break; } @@ -1374,18 +1381,18 @@ vboxNetFltWinMpSetInformation( */ if (pAdapt->bStandingBy == TRUE) { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Status = NDIS_STATUS_FAILURE; break; } pAdapt->bOutstandingRequests = TRUE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)) { /* need to disable cleaning promiscuous here ?? */ - bool fNetFltActive; + bool fNetFltActive; const bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &fNetFltActive); Assert(InformationBuffer); @@ -1416,9 +1423,9 @@ vboxNetFltWinMpSetInformation( vboxNetFltWinDereferenceNetFlt(pNetFlt); vboxNetFltWinDereferenceAdapt(pAdapt); - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); pAdapt->bOutstandingRequests = FALSE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); break; } } @@ -1862,7 +1869,7 @@ Notes: Read "Minimizing Miniport Driver Initialization Time" in the DDK // { PVBOXNETFLTINS pNetFlt = (PADAPT_2_PVBOXNETFLTINS(pAdapt)); - pInfo = &pNetFlt->u.s.Mac; + pInfo = &pNetFlt->u.s.MacAddr; ulInfoLen = VBOXNETADP_ETH_ADDRESS_LENGTH; } break; @@ -1876,7 +1883,7 @@ Notes: Read "Minimizing Miniport Driver Initialization Time" in the DDK // { PVBOXNETFLTINS pNetFlt = (PADAPT_2_PVBOXNETFLTINS(pAdapt)); - pInfo = &pNetFlt->u.s.Mac; + pInfo = &pNetFlt->u.s.MacAddr; ulInfoLen = VBOXNETADP_ETH_ADDRESS_LENGTH; } break; diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.h b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.h index 82de0714a..317622957 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.h +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltMp-win.h @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFltMp-win.h $ */ +/* $Id: VBoxNetFltMp-win.h 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Miniport edge of ndis filter driver */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.c b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.c index 23191fef9..182e8fd5f 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.c @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFltPt-win.c $ */ +/* $Id: VBoxNetFltPt-win.c 29108 2010-05-05 20:17:42Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Protocol edge of ndis filter driver */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. @@ -302,7 +298,7 @@ vboxNetFltWinPtDoUnbinding(PADAPT pAdapt, bool bOnUnbind) * Set the flag that the miniport below is unbinding, so the request handlers will * fail any request comming later */ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); ASMAtomicUoWriteBool(&pNetFlt->fDisconnectedFromHost, true); ASMAtomicUoWriteBool(&pNetFlt->fRediscoveryPending, false); @@ -335,7 +331,7 @@ vboxNetFltWinPtDoUnbinding(PADAPT pAdapt, bool bOnUnbind) } - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); if (CompleteRequest == TRUE) { @@ -581,15 +577,15 @@ vboxNetFltWinPtRequestComplete( } if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt)) { - /* we're here _ONLY_ in the passthru mode */ - Assert(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU); - if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU) - { - PVBOXNETFLTINS pNetFltIf = PADAPT_2_PVBOXNETFLTINS(pAdapt); - Assert(!pNetFltIf->fActive); - vboxNetFltWinDereferenceModePassThru(pNetFltIf); - vboxNetFltWinDereferenceAdapt(pAdapt); - } + /* we're here _ONLY_ in the passthru mode */ + Assert(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU); + if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU) + { + PVBOXNETFLTINS pNetFltIf = PADAPT_2_PVBOXNETFLTINS(pAdapt); + Assert(pNetFltIf->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE); + vboxNetFltWinDereferenceModePassThru(pNetFltIf); + vboxNetFltWinDereferenceAdapt(pAdapt); + } if(Status == NDIS_STATUS_SUCCESS) { @@ -616,7 +612,7 @@ vboxNetFltWinPtRequestComplete( Assert(Status == NDIS_STATUS_SUCCESS); if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_NETFLT) { - Assert(pNetFltIf->fActive); + Assert(pNetFltIf->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE); if(Status == NDIS_STATUS_SUCCESS) { pAdapt->fOurSetFilter = *((PULONG)pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer); @@ -628,7 +624,7 @@ vboxNetFltWinPtRequestComplete( } else if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU) { - Assert(!pNetFltIf->fActive); + Assert(pNetFltIf->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE); if(Status == NDIS_STATUS_SUCCESS) { @@ -852,7 +848,7 @@ vboxNetFltWinPtQueueReceivedPacket( Assert(KeGetCurrentIrql() == DISPATCH_LEVEL); do{ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); Assert(pAdapt->cReceivedPacketCount < MAX_RECEIVE_PACKET_ARRAY_SIZE); @@ -896,7 +892,7 @@ vboxNetFltWinPtQueueReceivedPacket( DoIndicate = TRUE; } } - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); } while(0); if(!bReturn) @@ -987,6 +983,7 @@ static bool vboxNetFltWinPtTransferDataCompleteActive(IN PADAPT pAdapt, /* 2. enqueue */ /* use the same packet info to put the packet in the processing packet queue */ #ifdef VBOX_NETFLT_ONDEMAND_BIND +# error "port me or remove VBOX_NETFLT_ONDEMAND_BIND" PNDIS_BUFFER pBuffer; PVOID pVA; UINT cbLength; @@ -995,7 +992,7 @@ static bool vboxNetFltWinPtTransferDataCompleteActive(IN PADAPT pAdapt, NdisQueryPacket(pPacket, NULL, NULL, &pBuffer, NULL); NdisQueryBufferSafe(pBuffer, &pVA, &cbLength, NormalPagePriority); - fFlags = MACS_EQUAL(((PRTNETETHERHDR)pVA)->SrcMac, pNetFltIf->u.s.Mac) ? + fFlags = MACS_EQUAL(((PRTNETETHERHDR)pVA)->SrcMac, pNetFltIf->u.s.MacAddr) ? PACKET_MINE | PACKET_SRC_HOST : PACKET_MINE; SET_FLAGS_TO_INFO(pInfo, fFlags); @@ -1014,14 +1011,28 @@ static bool vboxNetFltWinPtTransferDataCompleteActive(IN PADAPT pAdapt, pRecvRsvd->pBufToFree = NULL; NdisSetPacketFlags(pPacket, 0); - +# ifdef VBOXNETFLT_NO_PACKET_QUEUE + if (vboxNetFltWinPostIntnet(pNetFltIf, pPacket, 0)) + { + /* drop it */ + vboxNetFltWinFreeSGNdisPacket(pPacket, true); + vboxNetFltWinDereferenceAdapt(pAdapt); + } + else + { + NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, &pPacket, 1); + } + vboxNetFltWinDereferenceNetFlt(pNetFltIf); + break; +# else Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, PACKET_MINE); -#endif - if(Status == NDIS_STATUS_SUCCESS) + if (Status == NDIS_STATUS_SUCCESS) { break; } Assert(0); +# endif +#endif } } else @@ -1092,7 +1103,7 @@ vboxNetFltWinPtFlushReceiveQueue( do { - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); if (pAdapt->cReceivedPacketCount > 0) { @@ -1106,7 +1117,7 @@ vboxNetFltWinPtFlushReceiveQueue( */ pAdapt->cReceivedPacketCount = 0; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); if(!bReturn) { @@ -1135,7 +1146,7 @@ vboxNetFltWinPtFlushReceiveQueue( } /* we are here only in case pAdapt->cReceivedPacketCount == 0 */ - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); } while (FALSE); } @@ -1379,20 +1390,56 @@ vboxNetFltWinPtReceiveActive( /* enqueue SG */ #ifdef VBOX_NETFLT_ONDEMAND_BIND +# ifdef VBOXNETFLT_NO_PACKET_QUEUE +# error "port me or remove VBOX_NETFLT_ONDEMAND_BIND" +# endif { - uint32_t fFlags = MACS_EQUAL(((PRTNETETHERHDR)pRcvData)->SrcMac, pNetFlt->u.s.Mac) ? + uint32_t fFlags = MACS_EQUAL(((PRTNETETHERHDR)pRcvData)->SrcMac, pNetFlt->u.s.MacAddr) ? PACKET_SG | PACKET_MINE | PACKET_SRC_HOST : PACKET_SG | PACKET_MINE; Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pSG, fFlags); } #else +# ifdef VBOXNETFLT_NO_PACKET_QUEUE + if (vboxNetFltWinPostIntnet(pNetFlt, pSG, PACKET_SG)) + { + /* drop it */ + vboxNetFltWinMemFree(pSG); + vboxNetFltWinDereferenceAdapt(pAdapt); + } + else + { + PNDIS_PACKET pMyPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, /* PADAPT */ + pSG, /* PINTNETSG */ + pSG, /* PVOID pBufToFree */ + false, /* bool bToWire */ + false); /* bool bCopyMemory */ + Assert(pMyPacket); + if (pMyPacket) + { + NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_SUCCESS); + + DBG_CHECK_PACKET_AND_SG(pMyPacket, pSG); + + LogFlow(("non-ndis packet info, packet created (%p)\n", pMyPacket)); + NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, &pMyPacket, 1); + } + else + { + vboxNetFltWinDereferenceAdapt(pAdapt); + Status = NDIS_STATUS_RESOURCES; + } + } + vboxNetFltWinDereferenceNetFlt(pNetFlt); +# else Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pSG, PACKET_SG | PACKET_MINE); -#endif if(Status != NDIS_STATUS_SUCCESS) { Assert(0); vboxNetFltWinMemFree(pSG); break; } +# endif +#endif } else #endif /* #ifndef DEBUG_NETFLT_RECV_TRANSFERDATA */ @@ -1571,7 +1618,7 @@ vboxNetFltWinPtReceive( // break; } - fFlags = MACS_EQUAL(((PRTNETETHERHDR)pHeaderBuffer)->SrcMac, pNetFltIf->u.s.Mac) ? + fFlags = MACS_EQUAL(((PRTNETETHERHDR)pHeaderBuffer)->SrcMac, pNetFltIf->u.s.MacAddr) ? PACKET_COPY | PACKET_SRC_HOST : PACKET_COPY; Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, fFlags); if(Status == NDIS_STATUS_SUCCESS) @@ -1660,6 +1707,13 @@ vboxNetFltWinPtReceive( { VBOXNETFLT_LBVERIFY(pNetFlt, pPacket); +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0)) + { + /* drop it */ + break; + } +#else Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_COPY); Assert(Status == NDIS_STATUS_SUCCESS); if(Status == NDIS_STATUS_SUCCESS) @@ -1669,6 +1723,7 @@ vboxNetFltWinPtReceive( bNetFltActive = false; break; } +#endif } #ifndef VBOX_LOOPBACK_USEFLAGS else if(vboxNetFltWinLbIsFromIntNet(pLb)) @@ -1693,11 +1748,13 @@ vboxNetFltWinPtReceive( Assert(fAdaptActive); } while(FALSE); +#ifdef VBOXNETFLT_NO_PACKET_QUEUE if(Status == NDIS_STATUS_SUCCESS || Status == NDIS_STATUS_NOT_ACCEPTED -#ifndef VBOX_LOOPBACK_USEFLAGS +# ifndef VBOX_LOOPBACK_USEFLAGS || pLb -#endif +# endif ) +#endif { break; } @@ -1911,7 +1968,7 @@ vboxNetFltWinPtReceivePacket( break; } - fFlags = MACS_EQUAL(((PRTNETETHERHDR)pVA)->SrcMac, pNetFltIf->u.s.Mac) ? PACKET_SRC_HOST : 0; + fFlags = MACS_EQUAL(((PRTNETETHERHDR)pVA)->SrcMac, pNetFltIf->u.s.MacAddr) ? PACKET_SRC_HOST : 0; Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, bResources ? fFlags | PACKET_COPY : fFlags); if(Status == NDIS_STATUS_SUCCESS) @@ -1977,7 +2034,9 @@ vboxNetFltWinPtReceivePacket( if(!pLb) #endif { +#ifndef VBOXNETFLT_NO_PACKET_QUEUE NDIS_STATUS fStatus; +#endif bool bResources = NDIS_GET_PACKET_STATUS(pPacket) == NDIS_STATUS_RESOURCES; VBOXNETFLT_LBVERIFY(pNetFlt, pPacket); @@ -1987,6 +2046,15 @@ vboxNetFltWinPtReceivePacket( * we're probably doing something wrong with the packets if the miniport reports NDIS_STATUS_RESOURCES */ Assert(!bResources); +#ifdef VBOXNETFLT_NO_PACKET_QUEUE + if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0)) + { + /* drop it */ + cRefCount = 0; + break; + } + +#else fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, bResources ? PACKET_COPY : 0); if(fStatus == NDIS_STATUS_SUCCESS) { @@ -2007,6 +2075,7 @@ vboxNetFltWinPtReceivePacket( { Assert(0); } +#endif } #ifndef VBOX_LOOPBACK_USEFLAGS else if(vboxNetFltWinLbIsFromIntNet(pLb)) @@ -2115,23 +2184,23 @@ DECLHIDDEN(bool) vboxNetFltWinPtCloseAdapter(PADAPT pAdapt, PNDIS_STATUS pStatus PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt); RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); if(pAdapt->bClosingAdapter) { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Assert(0); return false; } if (pAdapt->hBindingHandle == NULL) { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); Assert(0); return false; } pAdapt->bClosingAdapter = true; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); /* * Close the binding below. and wait for it to complete @@ -2180,7 +2249,7 @@ vboxNetFltWinPtPnPNetEventSetPower( /* * Set the Internal Device State, this blocks all new sends or receives */ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); vboxNetFltWinSetPowerState(&pAdapt->PTState, *pDeviceState); @@ -2196,7 +2265,7 @@ vboxNetFltWinPtPnPNetEventSetPower( { pAdapt->bStandingBy = TRUE; } - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); #ifndef VBOX_NETFLT_ONDEMAND_BIND vboxNetFltWinPtFlushReceiveQueue(pAdapt, false); @@ -2221,16 +2290,16 @@ vboxNetFltWinPtPnPNetEventSetPower( /* * If the below miniport is going to low power state, complete the queued request */ - RTSpinlockAcquire(pNetFlt->hSpinlock, &Tmp); + RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp); if (pAdapt->bQueuedRequest) { pAdapt->bQueuedRequest = FALSE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); vboxNetFltWinPtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE); } else { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); } #endif @@ -2258,7 +2327,7 @@ vboxNetFltWinPtPnPNetEventSetPower( } #ifdef VBOX_NETFLT_ONDEMAND_BIND - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); #else /* * The device below is being turned on. If we had a request @@ -2271,7 +2340,7 @@ vboxNetFltWinPtPnPNetEventSetPower( pAdapt->bQueuedRequest = FALSE; pAdapt->bOutstandingRequests = TRUE; - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); NdisRequest(&Status, pAdapt->hBindingHandle, @@ -2287,7 +2356,7 @@ vboxNetFltWinPtPnPNetEventSetPower( } else { - RTSpinlockRelease(pNetFlt->hSpinlock, &Tmp); + RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp); } #endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.h b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.h index 7958f683b..68dacbe72 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.h +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.h @@ -1,10 +1,10 @@ -/* $Id: VBoxNetFltPt-win.h $ */ +/* $Id: VBoxNetFltPt-win.h 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Protocol edge of ndis filter driver */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt_m.inf b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt_m.inf index 9e06cba75..2678d9506 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt_m.inf +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFlt_m.inf @@ -3,7 +3,7 @@ ; ; -; Copyright (C) 2008 Sun Microsystems, Inc. +; Copyright (C) 2008 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ ; VirtualBox OSE distribution. VirtualBox OSE is distributed in the ; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. ; -; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa -; Clara, CA 95054 USA or visit http://www.sun.com if you need -; additional information or have any questions. -; ; ; Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/WinNetConfig.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/WinNetConfig.cpp index 377742520..ec102391d 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/WinNetConfig.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/WinNetConfig.cpp @@ -1,10 +1,10 @@ -/* $Id: WinNetConfig.cpp $ */ +/* $Id: WinNetConfig.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */ /** @file * VBoxNetCfgWin - Briefly describe this file, optionally with a longer description in a separate paragraph. */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -13,10 +13,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample. @@ -1752,7 +1748,7 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPWSTR pPnPId, VBOXNETCF winEr = GetLastError(); if(winEr != ERROR_INSUFFICIENT_BUFFER) { - Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (1) failed winErr(%d)\n", winEr); + Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (1) failed winErr(%d)\n", winEr); hr = HRESULT_FROM_WIN32(winEr); break; } @@ -1774,7 +1770,7 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPWSTR pPnPId, VBOXNETCF )) { winEr = GetLastError(); - Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (2) failed winErr(%d)\n", winEr); + Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetDeviceRegistryPropertyW (2) failed winErr(%d)\n", winEr); hr = HRESULT_FROM_WIN32(winEr); break; } @@ -1808,9 +1804,9 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumNetDevices(LPWSTR pPnPId, VBOXNETCF } else { - DWORD winEr = GetLastError(); - Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetClassDevsExW failed winErr(%d)\n", winEr); - hr = HRESULT_FROM_WIN32(winEr); + DWORD winEr = GetLastError(); + Log(L"VBoxNetCfgWinEnumNetDevices: SetupDiGetClassDevsExW failed winErr(%d)\n", winEr); + hr = HRESULT_FROM_WIN32(winEr); } return hr; @@ -2310,6 +2306,159 @@ static BOOL vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority (IN INetCfg *pNc return true; } +static BOOL vboxNetCfgWinListUpperBindings (IN INetCfg *pNc, IN INetCfgComponent *pNcc, PVOID pContext) +{ + INetCfgComponentBindings *pNccb = NULL; + IEnumNetCfgBindingPath *pEnumNccbp; + GUID *pGuid = (GUID*)pContext; + HRESULT hr; + LPWSTR pszwCompDisplayName; + + hr = pNcc->GetDisplayName(&pszwCompDisplayName); + Assert(hr == S_OK); + if ( hr == S_OK ) + { + Log(L" enumerating bindings for component (%s)\n", pszwCompDisplayName); + /* Get component's binding. */ + hr = pNcc->QueryInterface( IID_INetCfgComponentBindings, + (PVOID *)&pNccb ); + Assert(hr == S_OK); + if ( hr == S_OK ) + { + /* Get binding path enumerator reference. */ + hr = pNccb->EnumBindingPaths(EBP_ABOVE, &pEnumNccbp); + Assert(hr == S_OK); + if(hr == S_OK) + { + INetCfgBindingPath *pNccbp; + hr = pEnumNccbp->Reset(); + Assert(hr == S_OK); + do + { + hr = VBoxNetCfgWinGetNextBindingPath(pEnumNccbp, &pNccbp); + Assert(hr == S_OK || hr == S_FALSE); + if(hr == S_OK) + { + LPWSTR pszwPathToken; + hr = pNccbp->GetPathToken(&pszwPathToken); + Assert(hr == S_OK); + if(hr == S_OK) + { + Log(L" enumerating bp (%s), enabled(0x%x)\n", pszwPathToken, pNccbp->IsEnabled()); + IEnumNetCfgBindingInterface *pEnumNcbi; + hr = VBoxNetCfgWinGetBindingInterfaceEnum(pNccbp, &pEnumNcbi); + Assert(hr == S_OK); + if ( hr == S_OK ) + { + INetCfgBindingInterface *pNcbi; + hr = pEnumNcbi->Reset(); + Assert(hr == S_OK); + do + { + hr = VBoxNetCfgWinGetNextBindingInterface(pEnumNcbi, &pNcbi); + Assert(hr == S_OK || hr == S_FALSE); + if(hr == S_OK) + { + LPWSTR pszwInterfaceName; + hr = pNcbi->GetName(&pszwInterfaceName); + if(hr == S_OK) + { + Log(L" enumerating bi (%s)\n", pszwInterfaceName); + INetCfgComponent * pNccBoud; + hr = pNcbi->GetUpperComponent(&pNccBoud); + Assert(hr == S_OK); + if(hr == S_OK) + { + LPWSTR pszwDisplayName; + hr = pNccBoud->GetDisplayName(&pszwDisplayName); + Assert(hr == S_OK); + if(hr == S_OK) + { + Log(L" name (%s)\n", pszwDisplayName); + CoTaskMemFree(pszwDisplayName); + } + else + { + Log(L" ERROR getting name (0x%x)\n", hr); + } + + VBoxNetCfgWinReleaseRef(pNccBoud); + } + VBoxNetCfgWinReleaseRef(pNcbi); + } + else + { + Log(L" ERROR getting bi name (0x%x)\n", hr); + } + } + else + { + if(hr == S_FALSE) + { + hr = S_OK; + break; + } + else + { + Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetNextBindingInterface failed, hr (0x%x)\n", hr); + } + break; + } + } while(true); + VBoxNetCfgWinReleaseRef(pEnumNcbi); + } + else + { + Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetBindingInterfaceEnum failed, hr (0x%x)\n", hr); + } + CoTaskMemFree(pszwPathToken); + } + else + { + Log(L" ERROR getting bp name (0x%x)\n", hr); + } + + VBoxNetCfgWinReleaseRef(pNccbp); + } + else + { + if(hr = S_FALSE) + { + hr = S_OK; + break; + } + else + { + Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: VBoxNetCfgWinGetNextBindingPath failed, hr (0x%x)\n", hr); + } + break; + } + } while(true); + + VBoxNetCfgWinReleaseRef(pEnumNccbp); + } + else + { + Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: EnumBindingPaths failed, hr (0x%x)\n", hr); + } + + VBoxNetCfgWinReleaseRef( pNccb ); + } + else + { + Log(L"vboxNetCfgWinAdjustHostOnlyNetworkInterfacePriority: QueryInterface for IID_INetCfgComponentBindings failed, hr (0x%x)\n", hr); + } + + CoTaskMemFree(pszwCompDisplayName); + } + else + { + Log(L" ERROR getting component name (0x%x)\n", hr); + } + + return true; +} + VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface (LPCWSTR pInfPath, bool bIsInfPathFile, /* <- input params */ GUID *pGuid, BSTR *lppszName, BSTR *pErrMsg) /* <- output params */ { @@ -2770,6 +2919,68 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface (LPCWSTR #undef SetErrBreak +VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnumUpperBindings () +{ + INetCfg *pNc; + LPWSTR lpszApp = NULL; + HRESULT hr = VBoxNetCfgWinQueryINetCfgEx( FALSE, + L"VirtualBox Host-Only Creation", + 30000, /* on Vista we often get 6to4svc.dll holding the lock, wait for 30 sec, */ + &pNc, /* TODO: special handling for 6to4svc.dll ???, i.e. several retrieves */ + &lpszApp ); + Assert(hr == S_OK); + if(hr == S_OK) + { + Log(L"Enumerating Net\n"); + hr = vboxNetCfgWinEnumNetCfgComponents(pNc, + &GUID_DEVCLASS_NET, + vboxNetCfgWinListUpperBindings, + NULL); + Assert(hr == S_OK); + + Log(L"Enumerating NetService\n"); + hr = vboxNetCfgWinEnumNetCfgComponents(pNc, + &GUID_DEVCLASS_NETSERVICE, + vboxNetCfgWinListUpperBindings, + NULL); + Assert(hr == S_OK); + + Log(L"Enumerating NetTrans\n"); + hr = vboxNetCfgWinEnumNetCfgComponents(pNc, + &GUID_DEVCLASS_NETTRANS, + vboxNetCfgWinListUpperBindings, + NULL); + Assert(hr == S_OK); + + Log(L"Enumerating NetClient\n"); + hr = vboxNetCfgWinEnumNetCfgComponents(pNc, + &GUID_DEVCLASS_NETCLIENT, + vboxNetCfgWinListUpperBindings, + NULL); + Assert(hr == S_OK); + + if(hr == S_OK) + { + hr = pNc->Apply(); + Assert(hr == S_OK); + } + + VBoxNetCfgWinReleaseINetCfg(pNc, FALSE); + } + else if(hr == NETCFG_E_NO_WRITE_LOCK && lpszApp) + { + Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: app %s is holding the lock, failed\n", lpszApp); + CoTaskMemFree(lpszApp); + } + else + { + Log(L"VBoxNetCfgWinCreateHostOnlyNetworkInterface: VBoxNetCfgWinQueryINetCfgEx failed, hr 0x%x\n", hr); + } + + return hr; +} + + #define VBOX_CONNECTION_NAME L"VirtualBox Host-Only Network" VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName (PCWSTR DevName, WCHAR *pBuf, PULONG pcbBuf) { diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.cpp index 84e3f289a..b5c57ea36 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -8,10 +8,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Sample Notify Object diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.h b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.h index 36815dea8..ae772727c 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.h +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -8,10 +8,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ /* * Based in part on Microsoft DDK sample code for Sample Notify Object diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.rc b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.rc index af11aa993..c7741a505 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.rc +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotify.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Sun Microsystems, Inc. + * Copyright (C) 2009 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -8,10 +8,6 @@ * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 USA or visit http://www.sun.com if you need - * additional information or have any questions. */ #include <windows.h> #include <VBox/version.h> diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotifyn.idl b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotifyn.idl index 6b9e9a115..90f752f1c 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotifyn.idl +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/notifyobj/VBoxNetFltNotifyn.idl @@ -1,13 +1,18 @@ -/* $Id: VBoxNetFltNotifyn.idl $ */ +/* $Id: VBoxNetFltNotifyn.idl 29200 2010-05-07 12:14:18Z vboxsync $ */ /** @file * VBoxNetFltNotify.idl - Network Filter Driver (Host), Windows Specific Code. Integration with IntNet/NetFlt */ /* - * Copyright (C) 2008 Sun Microsystems, Inc. + * Copyright (C) 2008 Oracle Corporation * - * Sun Microsystems, Inc. confidential - * All rights reserved + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ /* * Based in part on Microsoft DDK sample code for Sample Notify Object @@ -15,7 +20,7 @@ * * Microsoft Windows * Copyright (C) Microsoft Corporation, 1992-2001. - * + * *---------------------------------------------------------------------------- */ #include <netcfgn.idl> |