VBoxNetFltRt-win.cpp revision 3331475701a5b12f98b3cfea07d5dca60072530f
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * VBoxNetFltRt-win.cpp - Bridged Networking Driver, Windows Specific Code.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * NetFlt Runtime
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Copyright (C) 2011 Oracle Corporation
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * available from http://www.virtualbox.org. This file is free software;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * General Public License (GPL) as published by the Free Software
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** represents the job element of the job queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * see comments for VBOXNETFLT_JOB_QUEUE */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** link in the job queue */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** job function to be executed */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** parameter to be passed to the job function */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** event that will be fired on job completion */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** true if the job manager should use the completion even for completion indication, false-otherwise*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * represents the queue of jobs processed by the worker thread
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * we use the thread to process tasks which are required to be done at passive level
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * our callbacks may be called at APC level by IntNet, there are some tasks that we can not create at APC,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * e.g. thread creation. This is why we schedule such jobs to the worker thread working at passive level
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we are using ExInterlocked..List functions to access the jobs list */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** this event is used to initiate a job worker thread kill */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** this event is used to notify a worker thread that jobs are added to the queue */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** worker thread */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync}CREATE_INSTANCE_CONTEXT, *PCREATE_INSTANCE_CONTEXT;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/*contexts used for our jobs */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* Attach context */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsynctypedef struct _ATTACH_INFO
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* general worker context */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsynctypedef struct _WORKER_INFO
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* idc initialization */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync volatile bool bStop;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync volatile int rc;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** globals */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** global job queue. some operations are required to be done at passive level, e.g. thread creation, adapter bind/unbind initiation,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * while IntNet typically calls us APC_LEVEL, so we just create a system thread in our DriverEntry and enqueue the jobs to that thread */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncvolatile static bool g_bVBoxIdcInitialized;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * The (common) global data.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* win-specific global data */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ( (PVBOXNETFLT_JOB)((uint8_t *)(pListEntry) - RT_OFFSETOF(VBOXNETFLT_JOB, ListEntry)) )
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int vboxNetFltWinAttachToInterface(PVBOXNETFLTINS pThis, void * pContext, bool fRediscovery);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int vboxNetFltWinConnectIt(PVBOXNETFLTINS pThis);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** makes the current thread to sleep for the given number of miliseconds */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** wait for the given device to be dereferenced */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(void) vboxNetFltWinWaitDereference(PVBOXNETFLT_WINIF_DEVICE pState)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync while (ASMAtomicUoReadU32((volatile uint32_t *)&pState->cReferences))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * mem functions
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* allocates and zeroes the nonpaged memory of a given size */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinMemAlloc(PVOID* ppMemBuf, UINT cbLength)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync *ppMemBuf = ExAllocatePoolWithTag(NonPagedPool, cbLength, VBOXNETFLT_MEM_TAG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_STATUS fStatus = NdisAllocateMemoryWithTag(ppMemBuf, cbLength, VBOXNETFLT_MEM_TAG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* frees memory allocated with vboxNetFltWinMemAlloc */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(void) vboxNetFltWinMemFree(PVOID pvMemBuf)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* initializes packet info pool and allocates the cSize packet infos for the pool */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinPpAllocatePacketInfoPool(PVBOXNETFLT_PACKET_INFO_POOL pPool, UINT cSize)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinMemAlloc((PVOID*)&pPacketInfos, cbBufSize);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync for (i = 0; i < cSize; i++)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinQuEnqueueTail(&pPool->Queue.Queue, pInfo);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* frees the packet info pool */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncVOID vboxNetFltWinPpFreePacketInfoPool(PVBOXNETFLT_PACKET_INFO_POOL pPool)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * copies one string to another. in case the destination string size is not enough to hold the complete source string
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * does nothing and returns NDIS_STATUS_RESOURCES .
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinCopyString(PNDIS_STRING pDst, PNDIS_STRING pSrc)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisMoveMemory(pDst->Buffer, pSrc->Buffer, pSrc->Length);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/************************************************************************************
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * PINTNETSG pSG manipulation functions
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ************************************************************************************/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* moves the contents of the given NDIS_BUFFER and all other buffers chained to it to the PINTNETSG
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the PINTNETSG is expected to contain one segment whose bugger is large enough to maintain
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the contents of the given NDIS_BUFFER and all other buffers chained to it */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinNdisBufferMoveToSG0(PNDIS_BUFFER pBuffer, PINTNETSG pSG)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer, &pVirtualAddress, &cbCurrentLength, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisMoveMemory(ptr, pVirtualAddress, cbCurrentLength);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* converts the PNDIS_BUFFER to PINTNETSG by making the PINTNETSG segments to point to the memory buffers the
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * ndis buffer(s) point to (as opposed to vboxNetFltWinNdisBufferMoveToSG0 which copies the memory from ndis buffers(s) to PINTNETSG) */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinNdisBuffersToSG(PNDIS_BUFFER pBuffer, PINTNETSG pSG)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer, &pVirtualAddress, &cbCurrentLength, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic PINTNETSG vboxNetFltWinCreateSG(uint32_t cSegs)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NTSTATUS Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/************************************************************************************
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * packet queue functions
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ************************************************************************************/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinQuPostPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, PINTNETSG pSG, uint32_t fFlags
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("posting packet back to driver stack..\n"));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* INTNETSG was in the packet queue, create a new NdisPacket from INTNETSG*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync false); /* bool bCopyMemory */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_SUCCESS);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("non-ndis packet info, packet created (%p)\n", pMyPacket));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NDIS_PACKET was in the packet queue */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the packet is the one that was passed to us in send/receive callback
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * According to the DDK, we can not post it further,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * instead we should allocate our own packet.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * So, allocate our own packet (pMyPacket) and copy the packet info there */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPrepareSendPacket(pNetFlt, pPacket, &pMyPacket/*, true*/);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("packet from wire, packet created (%p)\n", pMyPacket));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPrepareRecvPacket(pNetFlt, pPacket, &pMyPacket, false);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("packet from wire, packet created (%p)\n", pMyPacket));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the packet enqueued is ours, simply assign pMyPacket and zero pPacket */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we have successfully initialized our packet, post it to the host or to the wire */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinLbPutSendPacket(pNetFlt, pMyPacket, false /* bFromIntNet */);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisSend(&Status, pNetFlt->u.s.hBinding, pMyPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the status is NOT pending, complete the packet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bTmp = vboxNetFltWinLbRemoveSendPacket(pNetFlt, pMyPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("status is not pending, completing packet (%p)\n", pPacket));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisIMCopySendCompletePerPacketInfo (pPacket, pMyPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* should never be here since the PINTNETSG is stored only when the underlying miniport
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * indicates NDIS_STATUS_RESOURCES, we should never have this when processing
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the "from-host" packets */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("status is not pending, freeing myPacket (%p)\n", pMyPacket));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisMIndicateReceivePacket(pNetFlt->u.s.hMiniport, &pMyPacket, 1);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the packet receive completion is always indicated via MiniportReturnPacket */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /*we failed to create our packet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_WORKER pWorker, PVOID pvPacket, const UINT fFlags)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(bool) vboxNetFltWinPostIntnet(PVBOXNETFLTINS pNetFltIf, PVOID pvPacket, const UINT fFlags)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bDeleteSG = false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* packet used for matching */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bSrcHost = (fFlags & VBOXNETFLT_PACKET_SRC_HOST) != 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we first need to obtain the INTNETSG to be passed to intnet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the queue may contain two "types" of packets:
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the NDIS_PACKET and the INTNETSG.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * I.e. on send/receive we typically enqueue the NDIS_PACKET passed to us by ndis,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * however in case our ProtocolReceive is called or the packet's status is set to NDIS_STSTUS_RESOURCES
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * in ProtocolReceivePacket, we must return the packet immediately on ProtocolReceive*** exit
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * In this case we allocate the INTNETSG, copy the ndis packet data there and enqueue it.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * In this case the packet info flags has the VBOXNETFLT_PACKET_SG fag set
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Besides that the NDIS_PACKET contained in the queue could be either the one passed to us in our send/receive callback
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * or the one created by us. The latter is possible in case our ProtocolReceive callback is called and we call NdisTransferData
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * in this case we need to allocate the packet the data to be transferred to.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * If the enqueued packet is the one allocated by us the VBOXNETFLT_PACKET_MINE flag is set
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we have NDIS_PACKET enqueued, we need to convert it to INTNETSG to be passed to intnet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("ndis packet info, packet (%p)\n", pPacket));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryPacket(pPacket, NULL, &cBufferCount, &pCurrentBuffer, &cbPacketLength);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we can not allocate the INTNETSG on stack since in this case we may get stack overflow
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * somewhere outside of our driver (3 pages of system thread stack does not seem to be enough)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * since we have a "serialized" packet processing, i.e. all packets are being processed and passed
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * to intnet by this thread, we just use one previously allocated INTNETSG which is stored in PVBOXNETFLTINS */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* reinitialize */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, pSG->cSegsAlloc, 0 /*cSegsUsed*/);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* convert the ndis buffers to INTNETSG */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinNdisBuffersToSG(pCurrentBuffer, pSG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we have the INTNETSG enqueued. (see the above comment explaining why/when this may happen)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * just use the INTNETSG to pass it to intnet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the PINTNETSG is stored only when the underlying miniport
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * indicates NDIS_STATUS_RESOURCES, we should never have this when processing
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the "from-host" packedts */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("not ndis packet info, pSG (%p)\n", pSG));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* create tmp packet that woud be used for matching */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pTmpPacket = vboxNetFltWinNdisPacketFromSG(pNetFltIf,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync true); /* bool bCopyMemory */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_SET_PACKET_STATUS(pTmpPacket, NDIS_STATUS_SUCCESS);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the pSG was successfully initialized, post it to the netFlt*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bDropIt = pSG ? pNetFltIf->pSwitchPort->pfnRecv(pNetFltIf->pSwitchPort, NULL /* pvIf */, pSG,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bSrcHost ? INTNETTRUNKDIR_HOST : INTNETTRUNKDIR_WIRE
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pNetFltIf->pSwitchPort->pfnRecv(pNetFltIf->pSwitchPort, NULL /* pvIf */, pSG, INTNETTRUNKDIR_HOST);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync STATISTIC_INCREASE(pNetFltIf->u.s.WinIf.cTxSuccess);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if !defined(VBOXNETADP)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinQuPostPacket(pNetFltIf, pPacket, pSG, fFlags
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we will process packet completion in the completion routine */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* drop it */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if !defined(VBOXNETADP)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* complete the packets */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* NDIS_SET_PACKET_STATUS(pPacket, Status); */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisMSendComplete(pNetFltIf->u.s.hMiniport, pPacket, Status);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if !defined(VBOXNETADP)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if !defined(VBOXNETADP)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#else /* #ifdef VBOXNETFLT_NO_PACKET_QUEUE */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * thread start function for the thread which processes the packets enqueued in our send and receive callbacks called by ndis
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * ndis calls us at DISPATCH_LEVEL, while IntNet is using kernel functions which require Irql<DISPATCH_LEVEL
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * this is why we can not immediately post packets to IntNet from our sen/receive callbacks
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * instead we put the incoming packets to the queue and maintain the system thread running at passive level
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * which processes the queue and posts the packets to IntNet, and further to the host or to the wire.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic VOID vboxNetFltWinQuPacketQueueWorkerThreadProc(PVBOXNETFLTINS pNetFltIf)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool fResume = true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PPACKET_QUEUE_WORKER pWorker = &pNetFltIf->u.s.PacketQueueWorker;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = KeWaitForMultipleObjects(RT_ELEMENTS(apEvents), apEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (!NT_SUCCESS(fStatus) || fStatus == STATUS_WAIT_0)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* "kill" event was set
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * will process queued packets and exit */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("processing vboxNetFltWinQuPacketQueueWorkerThreadProc\n"));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* packet used for matching */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /*TODO: FIXME: !!! the better approach for performance would be to dequeue all packets at once
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * and then go through all dequeued packets
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the same should be done for enqueue !!! */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pInfo = vboxNetFltWinQuInterlockedDequeueHead(&pWorker->PacketQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (vboxNetFltWinQuProcessInfo(pNetFltIf, pWorker, pInfo->pPacket, pInfo->fFlags))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinDecReferenceNetFlt(pNetFltIf, cNumProcessed);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinDecReferenceWinIf(pNetFltIf, cNumProcessed - cNumPostedToHostWire);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * thread start function for the job processing thread
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * see comments for PVBOXNETFLT_JOB_QUEUE
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic VOID vboxNetFltWinJobWorkerThreadProc(PVBOXNETFLT_JOB_QUEUE pQueue)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool fResume = true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = KeWaitForMultipleObjects(RT_ELEMENTS(apEvents), apEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (!NT_SUCCESS(Status) || Status == STATUS_WAIT_0)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* will process queued jobs and exit */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PLIST_ENTRY pJobEntry = ExInterlockedRemoveHeadList(&pQueue->Jobs, &pQueue->Lock);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * enqueues the job to the job queue to be processed by the job worker thread
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * see comments for PVBOXNETFLT_JOB_QUEUE
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic VOID vboxNetFltWinJobEnqueueJob(PVBOXNETFLT_JOB_QUEUE pQueue, PVBOXNETFLT_JOB pJob, bool bEnqueueHead)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ExInterlockedInsertHeadList(&pQueue->Jobs, &pJob->ListEntry, &pQueue->Lock);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ExInterlockedInsertTailList(&pQueue->Jobs, &pJob->ListEntry, &pQueue->Lock);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLINLINE(VOID) vboxNetFltWinJobInit(PVBOXNETFLT_JOB pJob, PFNVBOXNETFLT_JOB_ROUTINE pfnRoutine, PVOID pContext, bool bUseEvent)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&pJob->CompletionEvent, NotificationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * enqueues the job to the job queue to be processed by the job worker thread and
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * blocks until the job is done
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * see comments for PVBOXNETFLT_JOB_QUEUE
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic VOID vboxNetFltWinJobSynchExec(PVBOXNETFLT_JOB_QUEUE pQueue, PFNVBOXNETFLT_JOB_ROUTINE pfnRoutine, PVOID pContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinJobInit(&Job, pfnRoutine, pContext, true);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeWaitForSingleObject(&Job.CompletionEvent, Executive, KernelMode, FALSE, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * enqueues the job to be processed by the job worker thread at passive level and
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * blocks until the job is done
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(VOID) vboxNetFltWinJobSynchExecAtPassive(PFNVBOXNETFLT_JOB_ROUTINE pfnRoutine, PVOID pContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinJobSynchExec(&g_VBoxJobQueue, pfnRoutine, pContext);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * helper function used for system thread creation
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NTSTATUS vboxNetFltWinQuCreateSystemThread(PKTHREAD *ppThread, PKSTART_ROUTINE pfnStartRoutine, PVOID pvStartContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NTSTATUS Status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, (PKSTART_ROUTINE)pfnStartRoutine, pvStartContext);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)ppThread, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* @todo: how would we fail in this case ?*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * initialize the job queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * see comments for PVBOXNETFLT_JOB_QUEUE
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NTSTATUS vboxNetFltWinJobInitQueue(PVBOXNETFLT_JOB_QUEUE pQueue)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisZeroMemory(pQueue, sizeof(VBOXNETFLT_JOB_QUEUE));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&pQueue->KillEvent, NotificationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&pQueue->NotifyEvent, SynchronizationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinQuCreateSystemThread(&pQueue->pThread, (PKSTART_ROUTINE)vboxNetFltWinJobWorkerThreadProc, pQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * deinitialize the job queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * see comments for PVBOXNETFLT_JOB_QUEUE
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic void vboxNetFltWinJobFiniQueue(PVBOXNETFLT_JOB_QUEUE pQueue)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * initializes the packet queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NTSTATUS) vboxNetFltWinQuInitPacketQueue(PVBOXNETFLTINS pInstance)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PPACKET_QUEUE_WORKER pWorker = &pInstance->u.s.PacketQueueWorker;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&pWorker->KillEvent, NotificationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&pWorker->NotifyEvent, SynchronizationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync INIT_INTERLOCKED_PACKET_QUEUE(&pWorker->PacketQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPpAllocatePacketInfoPool(&pWorker->PacketInfoPool, VBOXNETFLT_PACKET_INFO_POOL_SIZE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pWorker->pSG = vboxNetFltWinCreateSG(PACKET_QUEUE_SG_SEGS_ALLOC);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinQuCreateSystemThread(&pWorker->pThread, (PKSTART_ROUTINE)vboxNetFltWinQuPacketQueueWorkerThreadProc, pInstance);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinPpFreePacketInfoPool(&pWorker->PacketInfoPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * deletes the packet queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(void) vboxNetFltWinQuFiniPacketQueue(PVBOXNETFLTINS pInstance)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PPACKET_QUEUE_WORKER pWorker = &pInstance->u.s.PacketQueueWorker;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* using the pPacketQueueSG as an indicator that the packet queue is initialized */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync RTSpinlockAcquireNoInts((pInstance)->hSpinlock, &Tmp);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync RTSpinlockReleaseNoInts((pInstance)->hSpinlock, &Tmp);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinPpFreePacketInfoPool(&pWorker->PacketInfoPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync FINI_INTERLOCKED_PACKET_QUEUE(&pWorker->PacketQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync RTSpinlockReleaseNoInts((pInstance)->hSpinlock, &Tmp);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * creates the INTNETSG containing one segment pointing to the buffer of size cbBufSize
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the INTNETSG created should be cleaned with vboxNetFltWinMemFree
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinAllocSG(UINT cbPacket, PINTNETSG *ppSG)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* allocation:
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * 1. SG_PACKET - with one aSegs pointing to
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * 2. buffer of cbPacket containing the entire packet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AssertCompileSizeAlignment(INTNETSG, sizeof(PVOID));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, cbPacket + sizeof(INTNETSG));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * put the packet info to the queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLINLINE(void) vboxNetFltWinQuEnqueueInfo(PVBOXNETFLTPACKET_QUEUE_WORKER pWorker, PVBOXNETFLTPACKET_INFO pInfo)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinQuInterlockedEnqueueTail(&pWorker->PacketQueue, pInfo);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeSetEvent(&pWorker->NotifyEvent, IO_NETWORK_INCREMENT, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * puts the packet to the queue
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @return NDIST_STATUS_SUCCESS iff the packet was enqueued successfully
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * and error status otherwise.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * NOTE: that the success status does NOT mean that the packet processing is completed, but only that it was enqueued successfully
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * 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)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * or if vboxNetFltWinQuEnqueuePacket failed, i.e. the packet was NOT enqueued
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, PVOID pPacket, const UINT fPacketFlags)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PVBOXNETFLT_PACKET_QUEUE_WORKER pWorker = &pInstance->u.s.PacketQueueWorker;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the packet is Ndis packet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinAllocSG(cbPacketLength, &pSG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pInfo = vboxNetFltWinPpAllocPacketInfo(&pWorker->PacketInfoPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* TODO: what status to set? */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the packet we are queueing is SG, add PACKET_SG to flags */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync SET_FLAGS_TO_INFO(pInfo, fPacketFlags | PACKET_SG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinNdisBufferMoveToSG0(pBuffer, pSG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync DBG_CHECK_PACKET_AND_SG((PNDIS_PACKET)pPacket, pSG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pInfo = vboxNetFltWinPpAllocPacketInfo(&pWorker->PacketInfoPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* TODO: what status to set? */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinSynchNdisRequest(PVBOXNETFLTINS pNetFlt, PNDIS_REQUEST pRequest)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 1. serialize */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = RTSemFastMutexRequest(pNetFlt->u.s.WinIf.hSynchRequestMutex); AssertRC(rc);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 2. set pNetFlt->u.s.pSynchRequest */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 3. call NdisRequest */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisRequest(&fRequestStatus, pNetFlt->u.s.WinIf.hBinding, pRequest);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 3.1 if pending wait and assign the resulting status */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeWaitForSingleObject(&pNetFlt->u.s.WinIf.hSynchCompletionEvent, Executive,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fRequestStatus = pNetFlt->u.s.WinIf.SynchCompletionStatus;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 4. clear the pNetFlt->u.s.pSynchRequest */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync RTSemFastMutexRelease(pNetFlt->u.s.WinIf.hSynchRequestMutex); AssertRC(rc);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinGetMacAddress(PVBOXNETFLTINS pNetFlt, PRTMAC pMac)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync request.DATA.QUERY_INFORMATION.InformationBuffer = pMac;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(RTMAC);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync request.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync status = vboxNetFltWinSynchNdisRequest(pNetFlt, &request);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinQueryPhysicalMedium(PVBOXNETFLTINS pNetFlt, NDIS_PHYSICAL_MEDIUM * pMedium)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.QUERY_INFORMATION.InformationBuffer = pMedium;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_PHYSICAL_MEDIUM);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_PHYSICAL_MEDIUM;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinSynchNdisRequest(pNetFlt, &Request);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (Status == NDIS_STATUS_NOT_SUPPORTED || Status == NDIS_STATUS_NOT_RECOGNIZED || Status == NDIS_STATUS_INVALID_OID)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogRel(("OID_GEN_PHYSICAL_MEDIUM failed: Status (0x%x)", Status));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(bool) vboxNetFltWinIsPromiscuous(PVBOXNETFLTINS pNetFlt)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** @todo r=bird: This is too slow and is probably returning the wrong
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * information. What we're interested in is whether someone besides us
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * has put the interface into promiscuous mode. */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync request.DATA.QUERY_INFORMATION.InformationBuffer = &filter;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(filter);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync status = vboxNetFltWinSynchNdisRequest(pNetFlt, &request);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return (filter & NDIS_PACKET_TYPE_PROMISCUOUS) != 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinSetPromiscuous(PVBOXNETFLTINS pNetFlt, bool bYes)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** @todo Need to report changes to the switch via:
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, fPromisc);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.QUERY_INFORMATION.InformationBuffer = &fFilter;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(fFilter);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinSynchNdisRequest(pNetFlt, &Request);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* TODO: */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (!pNetFlt->u.s.WinIf.StateFlags.fUpperProtSetFilterInitialized)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the cache was not initialized yet, initiate it with the current filter value */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pNetFlt->u.s.WinIf.fUpperProtocolSetFilter = fFilter;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pNetFlt->u.s.WinIf.StateFlags.fUpperProtSetFilterInitialized = TRUE;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fExpectedFilter = pNetFlt->u.s.WinIf.fUpperProtocolSetFilter;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.SET_INFORMATION.InformationBuffer = &fExpectedFilter;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.SET_INFORMATION.InformationBufferLength = sizeof(fExpectedFilter);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinSynchNdisRequest(pNetFlt, &Request);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#else /* if defined VBOXNETADP */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Generates a new unique MAC address based on our vendor ID
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(void) vboxNetFltWinGenerateMACAddress(RTMAC *pMac)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* temporary use a time info */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pMac->au8[0] = (uint8_t)((VBOXNETADP_VENDOR_ID >> 16) & 0xff);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pMac->au8[1] = (uint8_t)((VBOXNETADP_VENDOR_ID >> 8) & 0xff);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pMac->au8[2] = (uint8_t)(VBOXNETADP_VENDOR_ID & 0xff);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(int) vboxNetFltWinMAC2NdisString(RTMAC *pMac, PNDIS_STRING pNdisString)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync static const char s_achDigits[17] = "0123456789abcdef";
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* validate parameters */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AssertPtrReturn(pNdisString, VERR_INVALID_PARAMETER);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AssertReturn(pNdisString->MaximumLength >= 13*sizeof(pNdisString->Buffer[0]), VERR_INVALID_PARAMETER);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync for (int i = 0; i < 6; i++)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pNdisString->Length = 12*sizeof(pNdisString->Buffer[0]);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int vboxNetFltWinWchar2Int(WCHAR c, uint8_t * pv)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(int) vboxNetFltWinMACFromNdisString(RTMAC *pMac, PNDIS_STRING pNdisString)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* validate parameters */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AssertPtrReturn(pNdisString, VERR_INVALID_PARAMETER);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AssertReturn(pNdisString->Length >= 12*sizeof(pNdisString->Buffer[0]), VERR_INVALID_PARAMETER);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync for (i = 0; i < 6; i++)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * creates a NDIS_PACKET from the PINTNETSG
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PVBOXNETFLTINS pNetFlt, PINTNETSG pSG, PVOID pBufToFree, bool bToWire, bool bCopyMemory)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(pSG->cbTotal >= sizeof(VBOXNETFLT_PACKET_ETHEADER_SIZE));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/** @todo Hrmpf, how can we fix this assumption? I fear this'll cause data
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * corruption and maybe even BSODs ... */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AssertReturn(pSG->cSegsUsed == 1 || bCopyMemory, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocatePacket(&fStatus, &pPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocatePacket(&fStatus, &pPacket, bToWire ? pNetFlt->u.s.WinIf.hSendPacketPool : pNetFlt->u.s.WinIf.hRecvPacketPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* @todo: generally we do not always need to zero-initialize the complete OOB data here, reinitialize only when/what we need,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * however we DO need to reset the status for the packets we indicate via NdisMIndicateReceivePacket to avoid packet loss
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * in case the status contains NDIS_STATUS_RESOURCES */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync fStatus = vboxNetFltWinMemAlloc(&pvMemBuf, pSG->cbTotal);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bToWire ? pNetFlt->u.s.WinIf.hSendBufferPool : pNetFlt->u.s.WinIf.hRecvBufferPool,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PVBOXNETFLT_PKTRSVD_PT pSendInfo = (PVBOXNETFLT_PKTRSVD_PT)pPacket->ProtocolReserved;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* set "don't loopback" flags */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisGetPacketFlags(pPacket) = g_VBoxNetFltGlobalsWin.fPacketDontLoopBack;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PVBOXNETFLT_PKTRSVD_MP pRecvInfo = (PVBOXNETFLT_PKTRSVD_MP)pPacket->MiniportReserved;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we must set the header size on receive */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_SET_PACKET_HEADER_SIZE(pPacket, VBOXNETFLT_PACKET_ETHEADER_SIZE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NdisAllocatePacket zero-initializes the OOB data,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * but keeps the packet flags, clean them here */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* TODO: set out of bound data */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * frees NDIS_PACKET created with vboxNetFltWinNdisPacketFromSG
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(void) vboxNetFltWinFreeSGNdisPacket(PNDIS_PACKET pPacket, bool bFreeMem)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryPacket(pPacket, NULL, &cBufCount, &pFirstBuffer, &uTotalPacketLength);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer, &pvMemBuf, &cbLength, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (true);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic void vboxNetFltWinAssociateMiniportProtocol(PVBOXNETFLTGLOBALS_WIN pGlobalsWin)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisIMAssociateMiniport(pGlobalsWin->Mp.hMiniport, pGlobalsWin->Pt.hProtocol);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * NetFlt driver unload function
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(VOID) vboxNetFltWinUnload(IN PDRIVER_OBJECT DriverObject)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow((__FUNCTION__" ==> DO (0x%x)\n", DriverObject));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* TODO: we can not prevent driver unload here */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Log((__FUNCTION__": vboxNetFltWinTryFiniIdc - failed, busy.\n"));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinPtDeregister(&g_VBoxNetFltGlobalsWin.Pt);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinMpDeregister(&g_VBoxNetFltGlobalsWin.Mp);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* don't use logging or any RT after de-init */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow((__FUNCTION__" <== DO (0x%x)\n", DriverObject));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncNTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncNTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the idc registration is initiated via IOCTL since our driver
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * can be loaded when the VBoxDrv is not in case we are a Ndis IM driver */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinJobInitQueue(&g_VBoxJobQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* note: we do it after we initialize the Job Queue */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisZeroMemory(&g_VBoxNetFltGlobalsWin, sizeof (g_VBoxNetFltGlobalsWin));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&g_VBoxNetFltGlobalsWin.SynchEvent, SynchronizationEvent, TRUE /* signalled*/);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync g_VBoxNetFltGlobalsWin.fPacketDontLoopBack = NDIS_FLAGS_DONT_LOOPBACK;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* this is Win2k, we don't support it actually, but just in case */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync g_VBoxNetFltGlobalsWin.fPacketDontLoopBack |= NDIS_FLAGS_SKIP_LOOPBACK_W2K;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync g_VBoxNetFltGlobalsWin.fPacketIsLoopedBack = NDIS_FLAGS_IS_LOOPBACK_PACKET;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinMpRegister(&g_VBoxNetFltGlobalsWin.Mp, DriverObject, RegistryPath);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPtRegister(&g_VBoxNetFltGlobalsWin.Pt, DriverObject, RegistryPath);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinAssociateMiniportProtocol(&g_VBoxNetFltGlobalsWin);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync//#ifndef VBOXNETADP
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync// vboxNetFltWinPtDeregister(&g_VBoxNetFltGlobalsWin.Pt);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinMpDeregister(&g_VBoxNetFltGlobalsWin.Mp);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * creates and initializes the packet to be sent to the underlying miniport given a packet posted to our miniport edge
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * according to DDK docs we must create our own packet rather than posting the one passed to us
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPrepareSendPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, PNDIS_PACKET *ppMyPacket)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocatePacket(&Status, ppMyPacket, pNetFlt->u.s.WinIf.hSendPacketPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PVBOXNETFLT_PKTRSVD_PT pSendInfo = (PVBOXNETFLT_PKTRSVD_PT)((*ppMyPacket)->ProtocolReserved);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the rest will be filled on send */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinCopyPacketInfoOnSend(*ppMyPacket, pPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisGetPacketFlags(*ppMyPacket) |= g_VBoxNetFltGlobalsWin.fPacketDontLoopBack;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * creates and initializes the packet to be sent to the upperlying protocol given a packet indicated to our protocol edge
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * according to DDK docs we must create our own packet rather than posting the one passed to us
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPrepareRecvPacket(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, PNDIS_PACKET *ppMyPacket, bool bDpr)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisDprAllocatePacket(&Status, ppMyPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocatePacket(&Status, ppMyPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PVBOXNETFLT_PKTRSVD_MP pRecvInfo = (PVBOXNETFLT_PKTRSVD_MP)((*ppMyPacket)->MiniportReserved);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinCopyPacketInfoOnRecv(*ppMyPacket, pPacket, false);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * initializes the VBOXNETFLTINS (our context structure) and binds to the given adapter
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PVBOXNETFLTINS *ppNetFlt, NDIS_HANDLE hMiniportAdapter, PNDIS_STRING pBindToMiniportName /* actually this is our miniport name*/, NDIS_HANDLE hWrapperConfigurationContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PVBOXNETFLTINS *ppNetFlt, PNDIS_STRING pOurMiniportName, PNDIS_STRING pBindToMiniportName)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync USHORT cbAnsiName = pBindToMiniportName->Length;/* the length is is bytes ; *2 ;RtlUnicodeStringToAnsiSize(pBindToMiniportName)*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Context.hWrapperConfigurationContext = hWrapperConfigurationContext;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync AnsiString.Buffer = 0; /* will be allocated by RtlUnicodeStringToAnsiString */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = RtlUnicodeStringToAnsiString(&AnsiString, pBindToMiniportName, true);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = vboxNetFltSearchCreateInstance(&g_VBoxNetFltGlobals, AnsiString.Buffer, &pInstance, &Context);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the case when our adapter was unbound while IntNet was connected to it */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the instance remains valid until IntNet disconnects from it, we simply search and re-use it*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = vboxNetFltWinAttachToInterface(pInstance, &Context, true);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = Context.Status != NDIS_STATUS_SUCCESS ? Context.Status : NDIS_STATUS_FAILURE;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* release netflt */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * deinitializes the VBOXNETFLTWIN
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(VOID) vboxNetFltWinPtFiniWinIf(PVBOXNETFLTWIN pWinIf)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("==>"__FUNCTION__" : pWinIf 0x%p\n", pWinIf));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync FINI_INTERLOCKED_SINGLE_LIST(&pWinIf->TransferDataList);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync FINI_INTERLOCKED_SINGLE_LIST(&pWinIf->SendPacketQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = RTSemFastMutexDestroy(pWinIf->hSynchRequestMutex); AssertRC(rc);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NOTE: NULL is a valid handle */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("<=="__FUNCTION__" : pWinIf 0x%p\n", pWinIf));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitWinIf(PVBOXNETFLTWIN pWinIf, IN PNDIS_STRING pOurDeviceName)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitWinIf(PVBOXNETFLTWIN pWinIf)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("==>"__FUNCTION__": pWinIf 0x%p\n", pWinIf));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocatePacketPoolEx(&Status, &pWinIf->hRecvPacketPool,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NOTE: NULL is a valid handle !!! */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocateBufferPool(&Status, &pWinIf->hRecvBufferPool, VBOXNETFLT_BUFFER_POOL_SIZE_RX);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetOpState(&pWinIf->MpState, kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetOpState(&pWinIf->PtState, kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync INIT_INTERLOCKED_SINGLE_LIST(&pWinIf->TransferDataList);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync INIT_INTERLOCKED_SINGLE_LIST(&pWinIf->SendPacketQueue);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&pWinIf->hSynchCompletionEvent, SynchronizationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisAllocatePacketPoolEx(&Status, &pWinIf->hSendPacketPool,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = RTSemFastMutexCreate(&pWinIf->hSynchRequestMutex);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinMemAlloc((PVOID*)&pWinIf->MpDeviceName.Buffer, pOurDeviceName->Length);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pWinIf->MpDeviceName.MaximumLength = pOurDeviceName->Length;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinCopyString(&pWinIf->MpDeviceName, pOurDeviceName);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("<=="__FUNCTION__": pWinIf 0x%p, Status 0x%x\n", pWinIf, Status));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * match packets
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncRTMAC g_vboxNetFltWinVerifyMACBroadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncRTMAC g_vboxNetFltWinVerifyMACGuest = {0x08, 0x00, 0x27, 0x01, 0x02, 0x03};
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(PRTNETETHERHDR) vboxNetFltWinGetEthHdr(PNDIS_PACKET pPacket)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryPacket(pPacket, NULL, &cBufCount1, &pBuffer1, &uTotalPacketLength1);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(uTotalPacketLength1 >= VBOXNETFLT_PACKET_ETHEADER_SIZE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (uTotalPacketLength1 < VBOXNETFLT_PACKET_ETHEADER_SIZE)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer1, &pEth, &cbLength1, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(cbLength1 >= VBOXNETFLT_PACKET_ETHEADER_SIZE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(PRTNETETHERHDR) vboxNetFltWinGetEthHdrSG(PINTNETSG pSG)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(pSG->aSegs[0].cb >= VBOXNETFLT_PACKET_ETHEADER_SIZE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (pSG->aSegs[0].cb < VBOXNETFLT_PACKET_ETHEADER_SIZE)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(bool) vboxNetFltWinCheckMACs(PNDIS_PACKET pPacket, PRTMAC pDst, PRTMAC pSrc)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PRTNETETHERHDR pHdr = vboxNetFltWinGetEthHdr(pPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (pDst && memcmp(pDst, &pHdr->DstMac, sizeof(RTMAC)))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (pSrc && memcmp(pSrc, &pHdr->SrcMac, sizeof(RTMAC)))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(bool) vboxNetFltWinCheckMACsSG(PINTNETSG pSG, PRTMAC pDst, PRTMAC pSrc)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PRTNETETHERHDR pHdr = vboxNetFltWinGetEthHdrSG(pSG);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (pDst && memcmp(pDst, &pHdr->DstMac, sizeof(RTMAC)))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (pSrc && memcmp(pSrc, &pHdr->SrcMac, sizeof(RTMAC)))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync# if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * answers whether the two given packets match based on the packet length and the first cbMatch bytes of the packets
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * if cbMatch < 0 matches complete packets.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(bool) vboxNetFltWinMatchPackets(PNDIS_PACKET pPacket1, PNDIS_PACKET pPacket2, const INT cbMatch)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bMatch = true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryPacket(pPacket1, NULL, &cBufCount1, &pBuffer1, &uTotalPacketLength1);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryPacket(pPacket2, NULL, &cBufCount2, &pBuffer2, &uTotalPacketLength2);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (cbMatch < 0 || (UINT)cbMatch > uTotalPacketLength1)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer1, &pMemBuf1, &cbLength1, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer2, &pMemBuf2, &cbLength2, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (memcmp((PVOID*)pMemBuf1, (PVOID*)pMemBuf2, ucbLength2Match))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* check that the packets fully match */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * answers whether the ndis packet and PINTNETSG match based on the packet length and the first cbMatch bytes of the packet and PINTNETSG
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * if cbMatch < 0 matches complete packets.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(bool) vboxNetFltWinMatchPacketAndSG(PNDIS_PACKET pPacket, PINTNETSG pSG, const INT cbMatch)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bMatch = true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryPacket(pPacket, NULL, &cBufCount1, &pBuffer1, &uTotalPacketLength1);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (cbMatch < 0 || (UINT)cbMatch > uTotalPacketLength1)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisQueryBufferSafe(pBuffer1, &pMemBuf1, &cbLength1, NormalPagePriority);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (memcmp((PVOID*)pMemBuf1, (PVOID*)pMemBuf2, ucbLength2Match))
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* check that the packets fully match */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * answers whether the two PINTNETSGs match based on the packet length and the first cbMatch bytes of the PINTNETSG
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * if cbMatch < 0 matches complete packets.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic bool vboxNetFltWinMatchSGs(PINTNETSG pSG1, PINTNETSG pSG2, const INT cbMatch)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bMatch = true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (cbMatch < 0 || (UINT)cbMatch > uTotalPacketLength1)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* check that the packets fully match */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Undo the work done during start (in reverse order).
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync memset(&g_VBoxNetFltGlobals, 0, sizeof(g_VBoxNetFltGlobals));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * base netflt initialization
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync memset(&g_VBoxNetFltGlobals, 0, sizeof(g_VBoxNetFltGlobals));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync }while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * initialize IDC
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * connect to the support driver.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * for establishing the connect to the support driver.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic VOID vboxNetFltWinInitIdcProbingWorker(PVOID pvContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PINIT_IDC_INFO pInitIdcInfo = (PINIT_IDC_INFO)pvContext;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bInterupted = ASMAtomicUoReadBool(&pInitIdcInfo->bStop);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bInterupted = ASMAtomicUoReadBool(&pInitIdcInfo->bStop);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinJobEnqueueJob(&g_VBoxJobQueue, &pInitIdcInfo->Job, false);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* it's interrupted */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeSetEvent(&pInitIdcInfo->hCompletionEvent, 0, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ASMAtomicUoWriteBool(&g_VBoxInitIdcInfo.bStop, true);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeWaitForSingleObject(&g_VBoxInitIdcInfo.hCompletionEvent, Executive, KernelMode, FALSE, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync KeInitializeEvent(&g_VBoxInitIdcInfo.hCompletionEvent, NotificationEvent, FALSE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinJobInit(&g_VBoxInitIdcInfo.Job, vboxNetFltWinInitIdcProbingWorker, &g_VBoxInitIdcInfo, false);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinJobEnqueueJob(&g_VBoxJobQueue, &g_VBoxInitIdcInfo.Job, false);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * connect to the support driver.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * for establishing the connect to the support driver.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync } while (0);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int vboxNetFltWinDeleteInstance(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogFlow(("vboxNetFltWinDeleteInstance: pThis=0x%p \n", pThis));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(pThis->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(pThis->u.s.WinIf.PtState.OpState == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(pThis->u.s.WinIf.MpState.OpState == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinDisconnectIt(PVBOXNETFLTINS pInstance)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncDECLHIDDEN(NDIS_STATUS) vboxNetFltWinDetachFromInterface(PVBOXNETFLTINS pNetFlt, bool bOnUnbind)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* paranoia to ensure the instance is not removed while we're waiting on the mutex
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * in case ndis does something unpredictable, e.g. calls our miniport halt independently
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * from protocol unbind and concurrently with it*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = RTSemMutexRequest(pNetFlt->u.s.hWinIfMutex, RT_INDEFINITE_WAIT);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetWinIfState(pNetFlt) == kVBoxWinIfState_Connected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Initialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.PtState) == kVBoxNetDevOpState_Initialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (vboxNetFltWinGetWinIfState(pNetFlt) == kVBoxWinIfState_Connected)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetWinIfState(pNetFlt, kVBoxWinIfState_Disconnecting);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPtDoUnbinding(pNetFlt, bOnUnbind);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinMpDoDeinitialization(pNetFlt);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetWinIfState(pNetFlt, kVBoxWinIfState_Disconnected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.PtState) == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we're unbinding, make an unbind-related release */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pNetFlt->u.s.WinIf.OpenCloseStatus = NDIS_STATUS_FAILURE;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.MpState, kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* release for the retain we made before waining on the mutex */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Checks if the host (not us) has put the adapter in promiscuous mode.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @returns true if promiscuous, false if not.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @param pThis The instance.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic bool vboxNetFltWinIsPromiscuous2(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bPromiscuous = (pThis->u.s.WinIf.fUpperProtocolSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == NDIS_PACKET_TYPE_PROMISCUOUS;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /*vboxNetFltWinIsPromiscuous(pAdapt);*/
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return false;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return true;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Report the MAC address, promiscuous mode setting, GSO capabilities and
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * no-preempt destinations to the internal network.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Does nothing if we're not currently connected to an internal network.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @param pThis The instance data.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic void vboxNetFltWinReportStuff(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** @todo Keep these up to date, esp. the promiscuous mode bit. */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /** @todo We should be able to do pfnXmit at DISPATCH_LEVEL... */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Worker for vboxNetFltWinAttachToInterface.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @param pAttachInfo Structure for communicating with
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * vboxNetFltWinAttachToInterface.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic void vboxNetFltWinAttachToInterfaceWorker(PATTACH_INFO pAttachInfo)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* to ensure we're not removed while we're here */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = RTSemMutexRequest(pThis->u.s.hWinIfMutex, RT_INDEFINITE_WAIT);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetWinIfState(pThis) == kVBoxWinIfState_Disconnected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pThis->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pThis->u.s.WinIf.PtState) == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (vboxNetFltWinGetWinIfState(pThis) == kVBoxWinIfState_Disconnected)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* rediscovery means adaptor bind is performed while intnet is already using it
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * i.e. adaptor was unbound while being used by intnet and now being bound back again */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(((VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState)) == kVBoxNetFltInsState_Connected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPtInitWinIf(&pThis->u.s.WinIf, pAttachInfo->pCreateContext->pOurName);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPtInitWinIf(&pThis->u.s.WinIf);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetWinIfState(pThis, kVBoxWinIfState_Connecting);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinPtDoBinding(pThis, pAttachInfo->pCreateContext->pOurName, pAttachInfo->pCreateContext->pBindToName);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinMpDoInitialization(pThis, pAttachInfo->pCreateContext->hMiniportAdapter, pAttachInfo->pCreateContext->hWrapperConfigurationContext);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (pThis->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetWinIfState(pThis, kVBoxWinIfState_Connected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pThis->u.s.WinIf.PtState) == kVBoxNetDevOpState_Initialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 4. mark as connected */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pAttachInfo->pCreateContext->Status = NDIS_STATUS_SUCCESS;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* 5. Report MAC address, promiscuousness and GSO capabilities. */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetWinIfState(pThis, kVBoxWinIfState_Disconnected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pThis->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(vboxNetFltWinGetOpState(&pThis->u.s.WinIf.PtState) == kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Common code for vboxNetFltOsInitInstance and
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * vboxNetFltOsMaybeRediscovered.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @returns IPRT status code.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @param pThis The instance.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * @param fRediscovery True if vboxNetFltOsMaybeRediscovered is calling,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * false if it's vboxNetFltOsInitInstance.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int vboxNetFltWinAttachToInterface(PVBOXNETFLTINS pThis, void * pContext, bool fRediscovery)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Info.pCreateContext = (PCREATE_INSTANCE_CONTEXT)pContext;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NTSTATUS vboxNetFltWinPtDevDispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PIO_STACK_LOCATION pIrpSl = IoGetCurrentIrpStackLocation(pIrp);;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinDevCreate(PVBOXNETFLTGLOBALS_WIN pGlobals)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PDRIVER_DISPATCH aMajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisInitUnicodeString(&DevName, VBOXNETFLT_NAME_DEVICE);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisInitUnicodeString(&LinkName, VBOXNETFLT_NAME_LINK);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisZeroMemory(aMajorFunctions, sizeof (aMajorFunctions));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync aMajorFunctions[IRP_MJ_CREATE] = vboxNetFltWinPtDevDispatch;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync aMajorFunctions[IRP_MJ_CLEANUP] = vboxNetFltWinPtDevDispatch;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync aMajorFunctions[IRP_MJ_CLOSE] = vboxNetFltWinPtDevDispatch;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync aMajorFunctions[IRP_MJ_DEVICE_CONTROL] = vboxNetFltWinPtDevDispatch;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_STATUS Status = NdisMRegisterDevice(pGlobals->Mp.hNdisWrapper,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinDevDestroy(PVBOXNETFLTGLOBALS_WIN pGlobals)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_STATUS Status = NdisMDeregisterDevice(pGlobals->hDevice);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinDevCreateReference(PVBOXNETFLTGLOBALS_WIN pGlobals)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_STATUS Status = KeWaitForSingleObject(&pGlobals->SynchEvent, Executive, KernelMode, FALSE, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* should never happen actually */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic NDIS_STATUS vboxNetFltWinDevDereference(PVBOXNETFLTGLOBALS_WIN pGlobals)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_STATUS Status = KeWaitForSingleObject(&pGlobals->SynchEvent, Executive, KernelMode, FALSE, NULL);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* should never happen actually */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* reference the driver module to prevent driver unload */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinDevCreateReference(&g_VBoxNetFltGlobalsWin);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* dereference the driver module to prevent driver unload */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinDevDereference(&g_VBoxNetFltGlobalsWin);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * The OS specific interface definition
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncbool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* AttachToInterface true if disconnected */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncint vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync if (fDst & INTNETTRUNKDIR_WIRE || fDst & INTNETTRUNKDIR_HOST)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pPacket = vboxNetFltWinNdisPacketFromSG(pThis, pSG, NULL /*pBufToFree*/,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* force "don't loopback" flags to prevent loopback branch invocation in any case
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * to avoid ndis misbehave */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisGetPacketFlags(pPacket) |= g_VBoxNetFltGlobalsWin.fPacketDontLoopBack;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* this is done by default in vboxNetFltWinNdisPacketFromSG */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinLbPutSendPacket(pThis, pPacket, true /* bFromIntNet */);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisSend(&fStatus, pThis->u.s.WinIf.hBinding, pPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* the status is NOT pending, complete the packet */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bool bTmp = vboxNetFltWinLbRemoveSendPacket(pThis, pPacket);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* TODO: convert status to VERR_xxx */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* pending, dereference on packet complete */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync PNDIS_PACKET pPacket = vboxNetFltWinNdisPacketFromSG(pThis, pSG, NULL /*pBufToFree*/,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NdisMIndicateReceivePacket(pThis->u.s.WinIf.hMiniport, &pPacket, 1);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncvoid vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* we first wait for all pending ops to complete
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * this might include all packets queued for processing */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinQueryPhysicalMedium(pThis, &PhMedium);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogRel(("vboxNetFltWinQueryPhysicalMedium failed, Status (0x%x), setting medium to NdisPhysicalMediumUnspecified\n", Status));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogRel(("vboxNetFltWinQueryPhysicalMedium failed, Status (0x%x), setting medium to NdisPhysicalMediumUnspecified\n", Status));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogRel(("(SUCCESS) vboxNetFltWinQueryPhysicalMedium SUCCESS\n"));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync bPromiscSupported = (!(PhMedium == NdisPhysicalMediumWirelessWan
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /*|| PhMedium == NdisPhysicalMediumWiMax */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Assert(bPromiscSupported == VBOXNETFLT_PROMISCUOUS_SUPPORTED(pThis));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinSetPromiscuous(pThis, fActive);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync LogRel(("vboxNetFltWinSetPromiscuous failed, Status (0x%x), fActive (%d)\n", Status, fActive));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* indicate status change to make the ip settings be re-picked for dhcp */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync NDIS_STATUS Status = vboxNetFltWinDisconnectIt(pThis);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return Status == NDIS_STATUS_SUCCESS ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic void vboxNetFltWinConnectItWorker(PVOID pvContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#if !defined(VBOXNETADP) || !defined(VBOXNETFLT_NO_PACKET_QUEUE)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* this is not a rediscovery, initialize Mac cache */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinGetMacAddress(pInstance, &pInstance->u.s.MacAddr);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Status = vboxNetFltWinQuInitPacketQueue(pInstance);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic int vboxNetFltWinConnectIt(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinJobSynchExecAtPassive(vboxNetFltWinConnectItWorker, &Info);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncvoid vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncint vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync int rc = RTSemMutexCreate(&pThis->u.s.hWinIfMutex);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync rc = vboxNetFltWinAttachToInterface(pThis, pvContext, false /*fRediscovery*/ );
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncint vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetWinIfState(pThis, kVBoxWinIfState_Disconnected);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetOpState(&pThis->u.s.WinIf.MpState, kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncvoid vboxNetFltPortOsNotifyMacAddress(PVBOXNETFLTINS pThis, void *pvIfData, PCRTMAC pMac)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncint vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **ppvIfData)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* Nothing to do */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncint vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync /* Nothing to do */