VBoxNetFlt-win.c revision 1d94ccd0c6d838a45dea3a79ba295adc4caabcf9
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Integration with IntNet/NetFlt
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (c) 1993-1999, Microsoft Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** represents the job element of the job queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * see comments for JOB_QUEUE */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct _JOB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** link in the job queue */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** job function to be executed */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /** parameter to be passed to the job function */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** event that will be fired on job completion */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** true if the job manager should use the completion even for completion indication, false-otherwise*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * represents the queue of jobs processed by the worker thred
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * we use the thread to process tasks which are required to be done at passive level
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * our callbacks may be called at APC level by IntNet, there are some tasks that we can not create at APC,
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * e.g. thread creation. This is why we schedule such jobs to the worker thread working at passive level
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct _JOB_QUEUE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we are using ExInterlocked..List functions to access the jobs list */
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync /** this event is used to initiate a job worker thread kill */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** this event is used to notify a worker thread that jobs are added to the queue */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** worker thread */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}CREATE_INSTANCE_CONTEXT, *PCREATE_INSTANCE_CONTEXT;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*contexts used for our jobs */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Attach context */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct _ATTACH_INFO
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* general worker context */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct _WORKER_INFO
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* idc initialization */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync volatile bool bStop;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync volatile int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** globals */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** global lock */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** global job queue. some operations are required to be done at passive level, e.g. thread creation, adapter bind/unbind initiation,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * while IntNet typically calls us APC_LEVEL, so we just create a system thread in our DriverEntry and enqueue the jobs to that thread */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The (common) global data.
fdea543f71872a3ec3909536a4fce37ab7aa3a8bvboxsyncvolatile static bool g_bIdcInitialized;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ( (PJOB)((uint8_t *)(pListEntry) - RT_OFFSETOF(JOB, ListEntry)) )
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vboxNetFltWinAttachToInterface(PVBOXNETFLTINS pThis, void * pContext, bool fRediscovery);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vboxNetFltWinConnectIt(PVBOXNETFLTINS pThis);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** makes the current thread to sleep for the given number of miliseconds */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** wait for the given device to be dereferenced */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(void) vboxNetFltWinWaitDereference(PADAPT_DEVICE pState)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (ASMAtomicUoReadU32((volatile uint32_t *)&pState->cReferences))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * mem functions
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* allocates and zeroes the nonpaged memory of a given size */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinMemAlloc(PVOID* ppMemBuf, UINT cbLength)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_STATUS fStatus = NdisAllocateMemoryWithTag(ppMemBuf, cbLength, MEM_TAG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* frees memory allocated with vboxNetFltWinMemAlloc */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(void) vboxNetFltWinMemFree(PVOID pMemBuf)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* frees ndis buffers used on send/receive */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: don't check for NULL since NULL is a valid handle */
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync/* initializes ndis buffers used on send/receive */
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsyncstatic NDIS_STATUS vboxNetFltWinInitBuffers(PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: NULL is a valid handle !!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: NULL is a valid handle !!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* initializes packet info pool and allocates the cSize packet infos for the pool */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NDIS_STATUS vboxNetFltWinPpAllocatePacketInfoPool(PPACKET_INFO_POOL pPool, UINT cSize)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinMemAlloc((PVOID*)&pPacketInfos, cbBufSize);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for(i = 0; i < cSize; i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinQuEnqueueTail(&pPool->Queue.Queue, pInfo);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* frees the packet info pool */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVOID vboxNetFltWinPpFreePacketInfoPool(PPACKET_INFO_POOL pPool)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * copies one string to another. in case the destination string size is not enough to hold the complete source string
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * does nothing and returns NDIS_STATUS_RESOURCES .
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinCopyString(PNDIS_STRING pDst, PNDIS_STRING pSrc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisMoveMemory(pDst->Buffer, pSrc->Buffer, pSrc->Length);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/************************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PINTNETSG pSG manipulation functions
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ************************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vboxNetFltWinInitSG(PINTNETSG pSG, UINT cBufferCount)
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync/* moves the contents of the given NDIS_BUFFER and all other buffers chained to it to the PINTNETSG
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * the PINTNETSG is expected to contain one segment whose bugger is large enough to maintain
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * the contents of the given NDIS_BUFFER and all other buffers chained to it */
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsyncstatic NDIS_STATUS vboxNetFltWinNdisBufferMoveToSG0(PNDIS_BUFFER pBuffer, PINTNETSG pSG)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisMoveMemory(ptr, pVirtualAddress, cbCurrentLength);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* converts the PNDIS_BUFFER to PINTNETSG by making the PINTNETSG segments to point to the memory buffers the
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * ndis buffer(s) point to (as opposed to vboxNetFltWinNdisBufferMoveToSG0 which copies the memory from ndis buffers(s) to PINTNETSG) */
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsyncstatic NDIS_STATUS vboxNetFltWinNdisBuffersToSG(PNDIS_BUFFER pBuffer, PINTNETSG pSG)
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsyncstatic PINTNETSG vboxNetFltWinCreateSG(uint32_t cSize)
03319aeaef07ef63a404237f2cb56199131f4a03vboxsync NTSTATUS Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, RT_OFFSETOF(INTNETSG, aSegs[cSize]));
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync/************************************************************************************
8e8844a522f5d335f177a0313b03067d79cce201vboxsync * packet queue functions
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync ************************************************************************************/
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsyncstatic NDIS_STATUS vboxNetFltWinQuPostPacket(PADAPT pAdapt, PNDIS_PACKET pPacket, PINTNETSG pSG, uint32_t fFlags
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync LogFlow(("posting packet back to driver stack..\n"));
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync /* INTNETSG was in the packet queue, create a new NdisPacket from INTNETSG*/
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync pMyPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, /* PADAPT */
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync false); /* bool bCopyMemory */
8e8844a522f5d335f177a0313b03067d79cce201vboxsync NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_SUCCESS);
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync LogFlow(("non-ndis packet info, packet created (%p)\n", pMyPacket));
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync /* NDIS_PACKET was in the packet queue */
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync /* the packet is the one that was passed to us in send/receive callback
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * According to the DDK, we can not post it further,
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * instead we should allocate our own packet.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * So, allocate our own packet (pMyPacket) and copy the packet info there */
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync fStatus = vboxNetFltWinPrepareSendPacket(pAdapt, pPacket, &pMyPacket/*, true*/);
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync LogFlow(("packet from wire, packet created (%p)\n", pMyPacket));
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync fStatus = vboxNetFltWinPrepareRecvPacket(pAdapt, pPacket, &pMyPacket, false);
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync LogFlow(("packet from wire, packet created (%p)\n", pMyPacket));
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync /* the packet enqueued is ours, simply assign pMyPacket and zero pPacket */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync /* we have successfuly initialized our packet, post it to the host or to the wire */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync vboxNetFltWinLbPutSendPacket(pAdapt, pMyPacket, false /* bFromIntNet */);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync NdisSend(&fStatus, pAdapt->hBindingHandle, pMyPacket);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync /* the status is NOT pending, complete the packet */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync bool bTmp = vboxNetFltWinLbRemoveSendPacket(pAdapt, pMyPacket);
8e8844a522f5d335f177a0313b03067d79cce201vboxsync LogFlow(("status is not pending, completing packet (%p)\n", pPacket));
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync NdisIMCopySendCompletePerPacketInfo (pPacket, pMyPacket);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync /* should never be here since the PINTNETSG is stored only when the underlying miniport
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * indicates NDIS_STATUS_RESOURCES, we should never have this when processing
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * the "from-host" packets */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync LogFlow(("status is not pending, freeing myPacket (%p)\n", pMyPacket));
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, &pMyPacket, 1);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync /* the packet receive completion is always indicated via MiniportReturnPacket */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync /*we failed to create our packet */
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsyncstatic bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_WORKER pWorker, PPACKET_INFO pInfo)
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pNetFltIf);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync /* packet used for matching */
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync /* we first need to obtain the INTNETSG to be passed to intnet */
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync /* the queue may contain two "types" of packets:
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * the NDIS_PACKET and the INTNETSG.
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * I.e. on send/receive we typically enqueue the NDIS_PACKET passed to us by ndis,
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * however in case our ProtocolReceive is called or the packet's status is set to NDIS_STSTUS_RESOURCES
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * in ProtocolReceivePacket, we must return the packet immediately on ProtocolReceive*** exit
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * In this case we allocate the INTNETSG, copy the ndis packet data there and enqueue it.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * In this case the packet info flags has the PACKET_SG fag set
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * Besides that the NDIS_PACKET contained in the queue could be either the one passed to us in our send/receive callback
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * or the one created by us. The latter is possible in case our ProtocolReceive callback is called and we call NdisTransferData
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * in this case we need to allocate the packet the data to be transfered to.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * If the enqueued packet is the one allocated by us the PACKET_MINE flag is set
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync /* we have NDIS_PACKET enqueued, we need to convert it to INTNETSG to be passed to intnet */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync pPacket = (PNDIS_PACKET)GET_PACKET_FROM_INFO(pInfo);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync LogFlow(("ndis packet info, packet (%p)\n", pPacket));
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync /* we can not allocate the INTNETSG on stack since in this case we may get stack overflow
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * somewhere outside of our driver (3 pages of system thread stack does not seem to be enough)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * since we have a "serialized" packet processing, i.e. all packets are being processed and passed
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to intnet by this thread, we just use one previously allocated INTNETSG which is stored in PADAPT */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* reinitialize */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* convert the ndis buffers to INTNETSG */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinNdisBuffersToSG(pCurrentBuffer, pSG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we have the INTNETSG enqueued. (see the above comment explaining why/when this may happen)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * just use the INTNETSG to pass it to intnet */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the PINTNETSG is stored only when the underlying miniport
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * indicates NDIS_STATUS_RESOURCES, we should never have this when processing
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the "from-host" packedts */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we have both host and wire in ProtocolReceive */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("not ndis packet info, pSG (%p)\n", pSG));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* create tmp packet that woud be used for matching */
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync pTmpPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, /* PADAPT */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync true); /* bool bCopyMemory */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_SET_PACKET_STATUS(pTmpPacket, NDIS_STATUS_SUCCESS);
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync /* the pSG was successfully initialized, post it to the netFlt*/
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync pSG ? pNetFltIf->pSwitchPort->pfnRecv(pNetFltIf->pSwitchPort, pSG,
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync bSrcHost ? INTNETTRUNKDIR_HOST : INTNETTRUNKDIR_WIRE
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync pNetFltIf->pSwitchPort->pfnRecv(pNetFltIf->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinQuPostPacket(pAdapt, pPacket, pSG, fFlags
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync /* we will process packet completion in the completion routine */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* drop it */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* complete the packets */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* NDIS_SET_PACKET_STATUS(pPacket, Status); */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisMSendComplete(pAdapt->hMiniportHandle, pPacket, Status);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * thread start function for the thread which processes the packets enqueued in our send and receive callbacks called by ndis
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * ndis calls us at DISPATCH_LEVEL, while IntNet is using kernel functions which require Irql<DISPATCH_LEVEL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * this is why we can not immediately post packets to IntNet from our sen/receive callbacks
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * instead we put the incoming packets to the queue and maintain the system thread running at passive level
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * which processes the queue and posts the packets to IntNet, and further to the host or to the wire.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic VOID vboxNetFltWinQuPacketQueueWorkerThreadProc(PVBOXNETFLTINS pNetFltIf)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fResume = true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pNetFltIf);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPACKET_QUEUE_WORKER pWorker = &pNetFltIf->u.s.PacketQueueWorker;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* two events we're waiting is "kill" and "notify" events
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the former is used for the thread termination
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the latter gets fired each time the packet is added to the queue */
e7081fdf0305eaa621e0dd6decf8b28c33febc58vboxsync fStatus = KeWaitForMultipleObjects(2, pEvents, WaitAny, Executive, KernelMode, FALSE,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(!NT_SUCCESS(fStatus) || fStatus == STATUS_WAIT_0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* "kill" event was set
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * will process queued packets and exit */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("==> processing vboxNetFltWinQuPacketQueueWorkerThreadProc\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* packet used for matching */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*TODO: FIXME: !!! the better approach for performance would be to dequeue all packets at once
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync * and then go through all dequeued packets
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync * the same should be done for enqueue !!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pInfo = vboxNetFltWinQuInterlockedDequeueHead(&pWorker->PacketQueue);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(vboxNetFltWinQuProcessInfo(pNetFltIf, pWorker, pInfo))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinDecReferenceNetFlt(pNetFltIf, cNumProcessed);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinDecReferenceAdapt(pAdapt, cNumProcessed - cNumPostedToHostWire);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * thread start function for the job processing thread
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * see comments for PJOB_QUEUE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic VOID vboxNetFltWinJobWorkerThreadProc(PJOB_QUEUE pQueue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fResume = true;
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync Status = KeWaitForMultipleObjects(2, pEvents, WaitAny, Executive, KernelMode, FALSE,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* will process queued jobs and exit */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PLIST_ENTRY pJobEntry = ExInterlockedRemoveHeadList(&pQueue->Jobs, &pQueue->Lock);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * enqueues the job to the job queue to be processed by the job worker thread
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * see comments for PJOB_QUEUE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic VOID vboxNetFltWinJobEnqueueJob(PJOB_QUEUE pQueue, PJOB pJob, bool bEnqueueHead)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ExInterlockedInsertHeadList(&pQueue->Jobs, &pJob->ListEntry, &pQueue->Lock);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ExInterlockedInsertTailList(&pQueue->Jobs, &pJob->ListEntry, &pQueue->Lock);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLINLINE(VOID) vboxNetFltWinJobInit(PJOB pJob, JOB_ROUTINE pRoutine, PVOID pContext, bool bUseEvent)
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync KeInitializeEvent(&pJob->CompletionEvent, NotificationEvent, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * enqueues the job to the job queue to be processed by the job worker thread and
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * blocks until the job is done
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * see comments for PJOB_QUEUE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic VOID vboxNetFltWinJobSynchExec(PJOB_QUEUE pQueue, JOB_ROUTINE pRoutine, PVOID pContext)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinJobInit(&Job, pRoutine, pContext, true);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeWaitForSingleObject(&Job.CompletionEvent, Executive, KernelMode, FALSE, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * enqueues the job to be processed by the job worker thread at passive level and
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * blocks until the job is done
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(VOID) vboxNetFltWinJobSynchExecAtPassive(JOB_ROUTINE pRoutine, PVOID pContext)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinJobSynchExec(&g_JobQueue, pRoutine, pContext);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * helper function used for system thread creation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NTSTATUS vboxNetFltWinQuCreateSystemThread(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync InitializeObjectAttributes(&fObjectAttributes, NULL, OBJ_KERNEL_HANDLE,
c20b837b2c912dd4dcaaa676e15acd2b230108f0vboxsync fStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS,
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * initialize the job queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * see comments for PJOB_QUEUE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NTSTATUS vboxNetFltWinJobInitQueue(PJOB_QUEUE pQueue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeInitializeEvent(&pQueue->KillEvent, NotificationEvent, FALSE);
96d8c2c77873591a51233b013fc1ec8bc774a096vboxsync KeInitializeEvent(&pQueue->NotifyEvent, SynchronizationEvent, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinQuCreateSystemThread(&pQueue->pThread, (PKSTART_ROUTINE)vboxNetFltWinJobWorkerThreadProc, pQueue);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * deinitialize the job queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * see comments for PJOB_QUEUE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vboxNetFltWinJobFiniQueue(PJOB_QUEUE pQueue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * initializes the packet queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NTSTATUS) vboxNetFltWinQuInitPacketQueue(PVBOXNETFLTINS pInstance)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPACKET_QUEUE_WORKER pWorker = &pInstance->u.s.PacketQueueWorker;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeInitializeEvent(&pWorker->KillEvent, NotificationEvent, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeInitializeEvent(&pWorker->NotifyEvent, SynchronizationEvent, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync INIT_INTERLOCKED_PACKET_QUEUE(&pWorker->PacketQueue);
ee5858e9d955811dae9e6b8ecbb336cc6d0e7197vboxsync Status = vboxNetFltWinPpAllocatePacketInfoPool(&pWorker->PacketInfoPool, PACKET_INFO_POOL_SIZE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pWorker->pSG = vboxNetFltWinCreateSG(PACKET_QUEUE_SG_SEGS_ALLOC);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinQuCreateSystemThread(&pWorker->pThread, (PKSTART_ROUTINE)vboxNetFltWinQuPacketQueueWorkerThreadProc, pInstance);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinPpFreePacketInfoPool(&pWorker->PacketInfoPool);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * deletes the packet queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(void) vboxNetFltWinQuFiniPacketQueue(PVBOXNETFLTINS pInstance)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPACKET_QUEUE_WORKER pWorker = &pInstance->u.s.PacketQueueWorker;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// Assert(pAdapt->pPacketQueueSG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* using the pPacketQueueSG as an indicator that the packet queue is initialized */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinPpFreePacketInfoPool(&pWorker->PacketInfoPool);
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync FINI_INTERLOCKED_PACKET_QUEUE(&pWorker->PacketQueue);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * creates the INTNETSG containing one segment pointing to the buffer of size cbBufSize
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the INTNETSG created should be cleaned with vboxNetFltWinMemFree
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinAllocSG(UINT cbBufSize, PINTNETSG *ppSG)
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync /* allocation:
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * 1. SG_PACKET - with one aSegs pointing to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 2. buffer of cbPacketLength containing the entire packet */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* make sure the buffer is aligned */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, cbMemSize);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pSG->aSegs[0].pv = (uint8_t *)pSG + cbBufferOffset;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * put the packet info to the queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLINLINE(void) vboxNetFltWinQuEnqueueInfo(PPACKET_QUEUE_WORKER pWorker, PPACKET_INFO pInfo)
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync vboxNetFltWinQuInterlockedEnqueueTail(&pWorker->PacketQueue, pInfo);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync KeSetEvent(&pWorker->NotifyEvent, IO_NETWORK_INCREMENT, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * puts the packet to the queue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return NDIST_STATUS_SUCCESS iff the packet was enqueued successfully
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and error status otherwise.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * NOTE: that the success status does NOT mean that the packet processing is completed, but only that it was enqueued successfully
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the packet can be returned to the caller protocol/moniport only in case the bReleasePacket was set to true (in this case the copy of the packet was enqueued)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * or if vboxNetFltWinQuEnqueuePacket failed, i.e. the packet was NOT enqueued
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, PVOID pPacket, const UINT fPacketFlags)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPACKET_QUEUE_WORKER pWorker = &pInstance->u.s.PacketQueueWorker;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the packet is Ndis packet */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinAllocSG(cbPacketLength, &pSG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pInfo = vboxNetFltWinPpAllocPacketInfo(&pWorker->PacketInfoPool);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* TODO: what status to set? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the packet we are queueing is SG, add PACKET_SG to flags */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SET_FLAGS_TO_INFO(pInfo, fPacketFlags | PACKET_SG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinNdisBufferMoveToSG0(pBuffer, pSG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DBG_CHECK_PACKET_AND_SG((PNDIS_PACKET)pPacket, pSG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pInfo = vboxNetFltWinPpAllocPacketInfo(&pWorker->PacketInfoPool);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* TODO: what status to set? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * ioctl i/f
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ULONG CtlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we are finalizing during unload */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* TODO: FIXME: need to prevent driver unload that can occur in case IntNet is connected to us,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * but we are not bound to any adapters */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* rc = vboxNetFltWinTryFiniIdc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(!RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = STATUS_UNSUCCESSFUL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRoutine Description:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Process IRPs sent to this device.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DeviceObject - pointer to a device object
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Irp - pointer to an I/O Request Packet
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncReturn Value:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NTSTATUS - STATUS_SUCCESS always - change this when adding
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync real code to handle ioctls.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinPtDispatchIoctl(pDeviceObject, pIrpStack);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * NOTE! the routine is NOT re-enterable for the given pAdapt
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the serialization is not implemented for performance reasons
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * since we are assuming the caller serializes the requests as IntNet does
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NDIS_STATUS vboxNetFltWinSynchNdisRequest(PADAPT pAdapt, PNDIS_REQUEST pRequest)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 1. serialize */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTSemFastMutexRequest(pAdapt->hSynchRequestMutex); AssertRC(rc);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* 2. set pAdapt->pSynchRequest */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 3. call NdisRequest */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisRequest(&fRequestStatus, pAdapt->hBindingHandle, pRequest);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 3.1 if pending wait and assign the resulting status */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeWaitForSingleObject(&pAdapt->hSynchCompletionEvent, Executive,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 4. clear the pAdapt->pSynchRequest */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTSemFastMutexRelease(pAdapt->hSynchRequestMutex); AssertRC(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinGetMacAddress(PADAPT pAdapt, PRTMAC pMac)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync request.DATA.QUERY_INFORMATION.InformationBuffer = pMac;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(RTMAC);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync request.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync status = vboxNetFltWinSynchNdisRequest(pAdapt, &request);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinQueryPhysicalMedium(PADAPT pAdapt, NDIS_PHYSICAL_MEDIUM * pMedium)
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync Request.DATA.QUERY_INFORMATION.InformationBuffer = pMedium;
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_PHYSICAL_MEDIUM);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_PHYSICAL_MEDIUM;
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Status = vboxNetFltWinSynchNdisRequest(pAdapt, &Request);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(Status == NDIS_STATUS_NOT_SUPPORTED || Status == NDIS_STATUS_NOT_RECOGNIZED || Status == NDIS_STATUS_INVALID_OID)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogRel(("OID_GEN_PHYSICAL_MEDIUM failed: Status (0x%x)", Status));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(bool) vboxNetFltWinIsPromiscuous(PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo r=bird: This is too slow and is probably returning the wrong
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * information. What we're interested in is whether someone besides us
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * has put the interface into promiscuous mode. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync request.DATA.QUERY_INFORMATION.InformationBuffer = &filter;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(filter);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync status = vboxNetFltWinSynchNdisRequest(pAdapt, &request);
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return (filter & NDIS_PACKET_TYPE_PROMISCUOUS) != 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinSetPromiscuous(PADAPT pAdapt, bool bYes)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Request.DATA.QUERY_INFORMATION.InformationBuffer = &fFilter;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(fFilter);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinSynchNdisRequest(pAdapt, &Request);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* TODO: */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the cache was not initialized yet, initiate it with the current filter value */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Request.DATA.SET_INFORMATION.InformationBuffer = &fExpectedFilter;
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(fExpectedFilter);
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync fStatus = vboxNetFltWinSynchNdisRequest(pAdapt, &Request);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* if defined VBOXNETADP */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Generates a new unique MAC address based on our vendor ID
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(void) vboxNetFltWinGenerateMACAddress(RTMAC *pMac)
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync /* temporary use a time info */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pMac->au8[0] = (uint8_t)((VBOXNETADP_VENDOR_ID >> 16) & 0xff);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pMac->au8[1] = (uint8_t)((VBOXNETADP_VENDOR_ID >> 8) & 0xff);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pMac->au8[2] = (uint8_t)(VBOXNETADP_VENDOR_ID & 0xff);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(int) vboxNetFltWinMAC2NdisString(RTMAC *pMac, PNDIS_STRING pNdisString)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync static const char s_achDigits[17] = "0123456789abcdef";
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate parameters */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pNdisString, VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pNdisString->MaximumLength >= 13*sizeof(pNdisString->Buffer[0]), VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for( i = 0; i < 6; i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pNdisString->Length = 12*sizeof(pNdisString->Buffer[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vboxNetFltWinWchar2Int(WCHAR c, uint8_t * pv)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(int) vboxNetFltWinMACFromNdisString(RTMAC *pMac, PNDIS_STRING pNdisString)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate parameters */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pNdisString, VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pNdisString->Length >= 12*sizeof(pNdisString->Buffer[0]), VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for(i = 0; i < 6; i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * creates a NDIS_PACKET from the PINTNETSG
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* TODO: the bToWire parameter seems to be unneeded here, remove them*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG pSG, PVOID pBufToFree, bool bToWire, bool bCopyMemory)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisAllocatePacket(&fStatus, &pPacket, pAdapt->hSendPacketPoolHandle);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisAllocatePacket(&fStatus, &pPacket, pAdapt->hRecvPacketPoolHandle);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisAllocatePacket(&fStatus, &pPacket, bToWire ? pAdapt->hSendPacketPoolHandle : pAdapt->hRecvPacketPoolHandle);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* @todo: generally we do not always need to zero-initialize the complete OOB data here, reinitialize only when/what we need,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * however we DO need to reset the status for the packets we indicate via NdisMIndicateReceivePacket to avoid packet loss
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * in case the status contains NDIS_STATUS_RESOURCES */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinMemAlloc(&pMemBuf, pSG->cbTotal);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisMoveMemory(pMemBuf, pSG->aSegs[0].pv, pSG->cbTotal);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bToWire ? pAdapt->hSendBufferPoolHandle : pAdapt->hRecvBufferPoolHandle,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pSendRsvd = (PSEND_RSVD)(pPacket->ProtocolReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* set "don't loopback" flags */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisSetPacketFlags(pPacket, g_fPacketDontLoopBack);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pRecvRsvd = (PRECV_RSVD)(pPacket->MiniportReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* me must set the header size on receive */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_SET_PACKET_HEADER_SIZE(pPacket, ETH_HEADER_SIZE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NdisAllocatePacket zero-initializes the OOB data,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * but keeps the packet flags, clean them here */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* TODO: set out of bound data */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * frees NDIS_PACKET creaed with vboxNetFltWinNdisPacketFromSG
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(void) vboxNetFltWinFreeSGNdisPacket(PNDIS_PACKET pPacket, bool bFreeMem)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryPacket(pPacket, NULL, &cBufCount, &pFirstBuffer, &uTotalPacketLength);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryBufferSafe(pBuffer, &pMemBuf, &cbLength, NormalPagePriority);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(true);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Free all packet pools on the specified adapter.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pAdapt - pointer to ADAPT structure
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Free the packet pool that is used to indicate receives
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Free the packet pool that is used to send packets below
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vboxNetFltWinAssociateMiniportProtocol()
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisIMAssociateMiniport(vboxNetFltWinMpGetHandle(), vboxNetFltWinPtGetHandle());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * NetFlt driver unload function
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* TODO: we can not prevent driver unload here */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("vboxNetFltWinTryFiniIdc - failed, busy.\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* don't use logging or any RT after de-init */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * First entry point to be called, when this driver is loaded.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Register with NDIS as an intermediate driver.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return STATUS_SUCCESS if all initialization is successful, STATUS_XXX
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * error code if not.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we are registering in the DriverEntry only when we are working as a protocol
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * since in this case our driver is loaded after the VBoxDrv*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the idc registration is initiated via IOCTL since our driver
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * can be loaded when the VBoxDrv is not in case we are a Ndis IM driver */
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync /* this is Win2k*/
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync g_fPacketDontLoopBack |= NDIS_FLAGS_SKIP_LOOPBACK_W2K;
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync g_fPacketIsLoopedBack = NDIS_FLAGS_IS_LOOPBACK_PACKET;
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync /* note: we do it after we initialize the Job Queue */
69a0f42fa2c531eb2cffb6d6f482d828d9adab34vboxsync Status = vboxNetFltWinMpRegister(DriverObject, RegistryPath);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync Status = vboxNetFltWinPtRegister(DriverObject, RegistryPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#ifndef VBOXNETADP
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// vboxNetFltWinPtDeregister();
c657bea826c7455c93bd45eaebab63a4c7742c42vboxsync#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * creates and initializes the packet to be sent to the underlying miniport given a packet posted to our miniport edge
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * according to DDK docs we must create our own packet rather than posting the one passed to us
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*, IN bool bNetFltActive */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pSendRsvd = (PSEND_RSVD)((*ppMyPacket)->ProtocolReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_PACKET_FIRST_NDIS_BUFFER(*ppMyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(pPacket);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_PACKET_LAST_NDIS_BUFFER(*ppMyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(pPacket);
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync vboxNetFltWinCopyPacketInfoOnSend(*ppMyPacket, pPacket);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisGetPacketFlags(*ppMyPacket) |= g_fPacketDontLoopBack;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * creates and initializes the packet to be sent to the upperlying protocol given a packet indicated to our protocol edge
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * according to DDK docs we must create our own packet rather than posting the one passed to us
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get a packet off the pool and indicate that up
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pRecvRsvd = (PRECV_RSVD)((*ppMyPacket)->MiniportReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_PACKET_FIRST_NDIS_BUFFER(*ppMyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(pPacket);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_PACKET_LAST_NDIS_BUFFER(*ppMyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(pPacket);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = vboxNetFltWinCopyPacketInfoOnRecv(*ppMyPacket, pPacket);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * initializes the ADAPT (our context structure) and binds to the given adapter
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT *ppAdapt, NDIS_HANDLE hMiniportAdapter, PNDIS_STRING pBindToMiniportName /* actually this is our miniport name*/, NDIS_HANDLE hWrapperConfigurationContext)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT *ppAdapt, PNDIS_STRING pOurMiniportName, PNDIS_STRING pBindToMiniportName)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync USHORT cbAnsiName = pBindToMiniportName->Length;/* the lenght is is bytes ; *2 ;RtlUnicodeStringToAnsiSize(pBindToMiniportName)*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Context.hWrapperConfigurationContext = hWrapperConfigurationContext;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AnsiString.Buffer = 0; /* will be allocated by RtlUnicodeStringToAnsiString */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = RtlUnicodeStringToAnsiString(&AnsiString, pBindToMiniportName, true);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = vboxNetFltSearchCreateInstance(&g_VBoxNetFltGlobals, AnsiString.Buffer, &pInstance, &Context);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pInstance);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the case when our adapter was unbound while IntNet was connected to it */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the instance remains valid until intNet disconnects from it, we simply search and re-use it*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* re-initialize PADAPT */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = vboxNetFltWinAttachToInterface(pInstance, &Context, true);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* release netflt */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * initializes the ADAPT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtAllocInitPADAPT(PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * unbinds from the adapter we are bound to and deinitializes the ADAPT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NDIS_STATUS vboxNetFltWinPtFiniUnbind(PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("==> vboxNetFltWinPtFiniUnbind: Adapt %p\n", pAdapt));
19b725c530eb49600728765de7ed451cbe290740vboxsync /* TODO: should we break ? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* break; */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(0);
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync LogFlow(("<== vboxNetFltWinPtFiniUnbind: Adapt %p\n", pAdapt));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * deinitializes the ADAPT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(VOID) vboxNetFltWinPtFiniPADAPT(PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("<== vboxNetFltWinPtFiniPADAPT : pAdapt %p\n", pAdapt));
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync FINI_INTERLOCKED_SINGLE_LIST(&pAdapt->TransferDataList);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync# if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync FINI_INTERLOCKED_SINGLE_LIST(&pAdapt->SendPacketQueue);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* moved to vboxNetFltWinDetachFromInterfaceWorker */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Free the memory here, if was not released earlier(by calling the HaltHandler)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTSemFastMutexDestroy(pAdapt->hSynchRequestMutex); AssertRC(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("<== vboxNetFltWinPtFiniPADAPT : pAdapt %p\n", pAdapt));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(VOID) vboxNetFltWinPtFiniPADAPT(PADAPT pAdapt);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitPADAPT(IN PADAPT pAdapt, IN PNDIS_STRING pOurDeviceName)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitPADAPT(IN PADAPT pAdapt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("==> vboxNetFltWinPtInitPADAPT : pAdapt %p\n", pAdapt));
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync KeInitializeEvent(&pAdapt->hSynchCompletionEvent, SynchronizationEvent, FALSE);
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync * Allocate a packet pool for sends. We need this to pass sends down.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We cannot use the same packet descriptor that came down to our send
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * handler (see also NDIS 5.1 packet stacking).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTSemFastMutexCreate(&pAdapt->hSynchRequestMutex);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinMemAlloc((PVOID*)&pAdapt->DeviceName.Buffer, pOurDeviceName->Length);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pAdapt->DeviceName.MaximumLength = pOurDeviceName->Length;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinCopyString(&pAdapt->DeviceName, pOurDeviceName);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate a packet pool for receives. We need this to indicate receives.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Same consideration as sends (see also NDIS 5.1 packet stacking).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync INIT_INTERLOCKED_SINGLE_LIST(&pAdapt->TransferDataList);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync INIT_INTERLOCKED_SINGLE_LIST(&pAdapt->SendPacketQueue);
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync /* TODO: do we need it here ?? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* moved to vboxNetFltOsInitInstance */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while(0);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync LogFlow(("<== vboxNetFltWinPtInitPADAPT : pAdapt %p, Status %x\n", pAdapt, Status));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * match packets
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsyncRTMAC g_vboxNetFltWinVerifyMACBroadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTMAC g_vboxNetFltWinVerifyMACGuest = {0x08, 0x00, 0x27, 0x01, 0x02, 0x03};
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(PRTNETETHERHDR) vboxNetFltWinGetEthHdr(PNDIS_PACKET pPacket)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryPacket(pPacket, NULL, &cBufCount1, &pBuffer1, &uTotalPacketLength1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryBufferSafe(pBuffer1, &pEth, &cbLength1, NormalPagePriority);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(PRTNETETHERHDR) vboxNetFltWinGetEthHdrSG(PINTNETSG pSG)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(bool) vboxNetFltWinCheckMACs(PNDIS_PACKET pPacket, PRTMAC pDst, PRTMAC pSrc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTNETETHERHDR pHdr = vboxNetFltWinGetEthHdr(pPacket);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(pDst && memcmp(pDst, &pHdr->DstMac, sizeof(RTMAC)))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(pSrc && memcmp(pSrc, &pHdr->SrcMac, sizeof(RTMAC)))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(bool) vboxNetFltWinCheckMACsSG(PINTNETSG pSG, PRTMAC pDst, PRTMAC pSrc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTNETETHERHDR pHdr = vboxNetFltWinGetEthHdrSG(pSG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(pDst && memcmp(pDst, &pHdr->DstMac, sizeof(RTMAC)))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(pSrc && memcmp(pSrc, &pHdr->SrcMac, sizeof(RTMAC)))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * answers whether the two given packets match based on the packet length and the first cbMatch bytes of the packets
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * if cbMatch < 0 matches complete packets.
9c425bdea5f0991df62922b1584b805a86f2f898vboxsyncDECLHIDDEN(bool) vboxNetFltWinMatchPackets(PNDIS_PACKET pPacket1, PNDIS_PACKET pPacket2, const INT cbMatch)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool bMatch = true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryPacket(pPacket1, NULL, &cBufCount1, &pBuffer1, &uTotalPacketLength1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryPacket(pPacket2, NULL, &cBufCount2, &pBuffer2, &uTotalPacketLength2);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(cbMatch < 0 || (UINT)cbMatch > uTotalPacketLength1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryBufferSafe(pBuffer1, &pMemBuf1, &cbLength1, NormalPagePriority);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisQueryBufferSafe(pBuffer2, &pMemBuf2, &cbLength2, NormalPagePriority);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(memcmp((PVOID*)pMemBuf1, (PVOID*)pMemBuf2, ucbLength2Match))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* check that the packets fully match */
d4e6f63a0c6bcae052cc381e93f0224111b19753vboxsync * answers whether the ndis packet and PINTNETSG match based on the packet length and the first cbMatch bytes of the packet and PINTNETSG
e7074f973370e187bac5f4d3dd0cb193b4dfce62vboxsync * if cbMatch < 0 matches complete packets.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsyncDECLHIDDEN(bool) vboxNetFltWinMatchPacketAndSG(PNDIS_PACKET pPacket, PINTNETSG pSG, const INT cbMatch)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync bool bMatch = true;
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync NdisQueryPacket(pPacket, NULL, &cBufCount1, &pBuffer1, &uTotalPacketLength1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(cbMatch < 0 || (UINT)cbMatch > uTotalPacketLength1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync NdisQueryBufferSafe(pBuffer1, &pMemBuf1, &cbLength1, NormalPagePriority);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(memcmp((PVOID*)pMemBuf1, (PVOID*)pMemBuf2, ucbLength2Match))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* check that the packets fully match */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * answers whether the two PINTNETSGs match based on the packet length and the first cbMatch bytes of the PINTNETSG
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * if cbMatch < 0 matches complete packets.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic bool vboxNetFltWinMatchSGs(PINTNETSG pSG1, PINTNETSG pSG2, const INT cbMatch)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool bMatch = true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(cbMatch < 0 || (UINT)cbMatch > uTotalPacketLength1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* check that the packets fully match */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Undo the work done during start (in reverse order).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memset(&g_VBoxNetFltGlobals, 0, sizeof(g_VBoxNetFltGlobals));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * base netflt initialization
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memset(&g_VBoxNetFltGlobals, 0, sizeof(g_VBoxNetFltGlobals));
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * initialize IDC
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * connect to the support driver.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * for establishing the connect to the support driver.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vboxNetFltWinInitIdcProbingWorker(PINIT_IDC_INFO pInitIdcInfo)
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync bool bInterupted = ASMAtomicUoReadBool(&pInitIdcInfo->bStop);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bInterupted = ASMAtomicUoReadBool(&pInitIdcInfo->bStop);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync vboxNetFltWinJobEnqueueJob(&g_JobQueue, &pInitIdcInfo->Job, false);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* it's interupted */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeSetEvent(&pInitIdcInfo->hCompletionEvent, 0, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeWaitForSingleObject(&g_InitIdcInfo.hCompletionEvent, Executive, KernelMode, FALSE, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync KeInitializeEvent(&g_InitIdcInfo.hCompletionEvent, NotificationEvent, FALSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinJobInit(&g_InitIdcInfo.Job, vboxNetFltWinInitIdcProbingWorker, &g_InitIdcInfo, false);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinJobEnqueueJob(&g_JobQueue, &g_InitIdcInfo.Job, false);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * connect to the support driver.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * for establishing the connect to the support driver.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vboxNetFltWinDeleteInstance(PVBOXNETFLTINS pThis)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vboxNetFltWinDeleteInstance: pThis=%p \n", pThis));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pAdapt->PTState.OpState == kVBoxNetDevOpState_Deinitialized);
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync Assert(pAdapt->MPState.OpState == kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// Assert(!pAdapt->hMiniportHandle);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinMpDereferenceControlDevice();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* pDetachInfo->Status = VERR_GENERAL_FAILURE; */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NDIS_STATUS vboxNetFltWinDisconnectIt(PVBOXNETFLTINS pInstance)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinDetachFromInterface(PADAPT pAdapt, bool bOnUnbind)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PVBOXNETFLTINS pThis = PADAPT_2_PVBOXNETFLTINS(pAdapt);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vboxNetFltWinDetachFromInterface: pThis=%p\n", pThis));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Assert(!pThis->fActive); */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* paranoya to ensyre the instance is not removed while we're waiting on the mutex
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * in case ndis does something unpredictable, e.g. calls our miniport halt independently
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * from protocol unbind and concurrently with it*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTSemMutexRequest(pThis->u.s.hAdaptMutex, RT_INDEFINITE_WAIT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetAdaptState(pAdapt) == kVBoxAdaptState_Connected);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Initialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#ifdef VBOXNETADP
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Initialized
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//// && vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(vboxNetFltWinGetAdaptState(pAdapt) == kVBoxAdaptState_Connected)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetAdaptState(pAdapt, kVBoxAdaptState_Disconnecting);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinPtDoUnbinding(pAdapt, bOnUnbind);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinMpDoDeinitialization(pAdapt);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetAdaptState(pAdapt, kVBoxAdaptState_Disconnected);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// /* paranoya */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#ifndef VBOXNETADP
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we're unbinding, make an unbind-related release */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* pDetachInfo->Status = VERR_GENERAL_FAILURE; */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* release for the retain we made before waining on the mutex */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Worker for vboxNetFltWinAttachToInterface.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pAttachInfo Structure for communicating with
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * vboxNetFltWinAttachToInterface.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vboxNetFltWinAttachToInterfaceWorker(PATTACH_INFO pAttachInfo)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* to ensure we're not removed while we're here */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTSemMutexRequest(pThis->u.s.hAdaptMutex, RT_INDEFINITE_WAIT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetAdaptState(pAdapt) == kVBoxAdaptState_Disconnected);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// if(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#ifndef VBOXNETADP
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// && vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(vboxNetFltWinGetAdaptState(pAdapt) == kVBoxAdaptState_Disconnected)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* rediscovery means adaptor bind is performed while intnet is already using it
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * i.e. adaptor was unbound while being used by intnet and now being bound back again */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(((VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState)) == kVBoxNetFltInsState_Connected);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinPtInitPADAPT(pAdapt, pAttachInfo->pCreateContext->pOurName);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetAdaptState(pAdapt, kVBoxAdaptState_Connecting);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinPtDoBinding(pAdapt, pAttachInfo->pCreateContext->pOurName, pAttachInfo->pCreateContext->pBindToName);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinMpDoInitialization(pAdapt, pAttachInfo->pCreateContext->hMiniportAdapter, pAttachInfo->pCreateContext->hWrapperConfigurationContext);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(pAttachInfo->fRediscovery || (Status = vboxNetFltWinMpReferenceControlDevice()) == NDIS_STATUS_SUCCESS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetAdaptState(pAdapt, kVBoxAdaptState_Connected);
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync// Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Initialized);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// /* paranoya */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//// vboxNetFltWinSetAdaptState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync//#ifndef VBOXNETADP
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync// vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Initialized);
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync /* 4. mark as connected */
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync pAttachInfo->pCreateContext->Status = NDIS_STATUS_SUCCESS;
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync vboxNetFltWinSetAdaptState(pAdapt, kVBoxAdaptState_Disconnected);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Deinitialized);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync// /* paranoya */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync// vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync//#ifndef VBOXNETADP
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync// vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync#else /* VBOX_NETFLT_ONDEMAND_BIND */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Status = vboxNetFltWinGetMacAddress(pAdapt, &pThis->u.s.Mac);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync#endif /* VBOX_NETFLT_ONDEMAND_BIND */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Common code for vboxNetFltOsInitInstance and
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * vboxNetFltOsMaybeRediscovered.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pThis The instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fRediscovery True if vboxNetFltOsMaybeRediscovered is calling,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * false if it's vboxNetFltOsInitInstance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vboxNetFltWinAttachToInterface(PVBOXNETFLTINS pThis, void * pContext, bool fRediscovery)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Info.pCreateContext = (PCREATE_INSTANCE_CONTEXT)pContext;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* packet queue worker thread gets created on attach interface, need to do it via job at passive level */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinJobSynchExecAtPassive((JOB_ROUTINE)vboxNetFltWinAttachToInterfaceWorker, &Info);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The OS specific interface definition
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncbool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* AttachToInterface true if disconnected */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if !defined(VBOXNETADP) && !defined(VBOX_NETFLT_ONDEMAND_BIND)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if(fDst & INTNETTRUNKDIR_WIRE || fDst & INTNETTRUNKDIR_HOST)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, pSG, NULL /*pBufToFree*/,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinLbPutSendPacket(pAdapt, pPacket, true /* bFromIntNet */);
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync NdisSend(&fStatus, pAdapt->hBindingHandle, pPacket);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the status is NOT pending, complete the packet */
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync bool bTmp = vboxNetFltWinLbRemoveSendPacket(pAdapt, pPacket);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* TODO: convert status to VERR_xxx */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* pending, dereference on packet complete */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PNDIS_PACKET pPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, pSG, NULL /*pBufToFree*/,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, &pPacket, 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncbool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis)
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bPromiscuous = (pAdapt->fUpperProtocolSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == NDIS_PACKET_TYPE_PROMISCUOUS;
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync /*vboxNetFltWinIsPromiscuous(pAdapt);*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncvoid vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncbool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* ASSUMES that the MAC address never changes. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncvoid vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we first wait for all pending ops to complete
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * this might include all packets queued for processing */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the packets put to ReceiveQueue Array are currently not holding the references,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * simply need to flush them */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinPtFlushReceiveQueue(pAdapt, false /*fReturn*/);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinQueryPhysicalMedium(pAdapt, &PhMedium);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DBGPRINT(("vboxNetFltWinQueryPhysicalMedium failed, Status (0x%x), setting medium to NdisPhysicalMediumUnspecified\n", Status));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogRel(("vboxNetFltWinQueryPhysicalMedium failed, Status (0x%x), setting medium to NdisPhysicalMediumUnspecified\n", Status));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DBGPRINT(("(SUCCESS) vboxNetFltWinQueryPhysicalMedium SUCCESS\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bPromiscSupported = (!(PhMedium == NdisPhysicalMediumWirelessWan
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*|| PhMedium == NdisPhysicalMediumWiMax */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(bPromiscSupported == VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinSetPromiscuous(pAdapt, fActive);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DBGPRINT(("vboxNetFltWinSetPromiscuous failed, Status (0x%x), fActive (%d)\n", Status, fActive));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogRel(("vboxNetFltWinSetPromiscuous failed, Status (0x%x), fActive (%d)\n", Status, fActive));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* indicate status change to make the ip settings be re-picked for dhcp */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync NDIS_STATUS Status = vboxNetFltWinDisconnectIt(pThis);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return Status == NDIS_STATUS_SUCCESS ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vboxNetFltWinConnectItWorker(PWORKER_INFO pInfo)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PADAPT pAdapt = PVBOXNETFLTINS_2_PADAPT(pInstance);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* this is not a rediscovery, initialize Mac cache */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinGetMacAddress(pAdapt, &pInstance->u.s.Mac);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = vboxNetFltWinQuInitPacketQueue(pInstance);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vboxNetFltWinConnectIt(PVBOXNETFLTINS pThis)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinJobSynchExecAtPassive(vboxNetFltWinConnectItWorker, &Info);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncvoid vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
1b7f3a92e42fb9cabf96cf31c20481da466edf76vboxsyncint vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
1b7f3a92e42fb9cabf96cf31c20481da466edf76vboxsync int rc = RTSemMutexCreate(&pThis->u.s.hAdaptMutex);
1b7f3a92e42fb9cabf96cf31c20481da466edf76vboxsync rc = vboxNetFltWinAttachToInterface(pThis, pvContext, false /*fRediscovery*/ );
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetAdaptState(pAdapt, kVBoxAdaptState_Disconnected);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);