VBoxNetFltPt-win.c revision 065adffee82ccc6f7d6f1dcc2815c03a098cff3e
/* $Id$ */
/** @file
* VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Protocol edge of ndis filter driver
*/
/*
* Copyright (C) 2008 Sun Microsystems, Inc.
*
* Sun Microsystems, Inc. confidential
* All rights reserved
*/
/*
* Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
* Copyright (c) 1993-1999, Microsoft Corporation
*/
#include "VBoxNetFltCommon-win.h"
#ifdef VBOXNETADP
# error "No protocol edge"
#endif
/** protocol handle */
/** medium array used while opening underlying adaprot
* we are actually binding to NdisMedium802_3 and NdisMediumWan
* as specified in VBoxNetFlt.inf:
* HKR, Ndi\Interfaces, FilterMediaTypes, , "ethernet, wan" */
static NDIS_MEDIUM g_aMediumArray[] =
{
/* Ethernet */
/* Wan */
};
/**
* performs binding to the given adapter
*/
#ifdef VBOX_NETFLT_ONDEMAND_BIND
#else
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoBinding(IN PADAPT pAdapt, IN PNDIS_STRING pOurDeviceName, IN PNDIS_STRING pBindToDeviceName)
#endif
{
do
{
// NDIS_STATUS TmpStatus;
/* copy the bind to dev name to our buffer */
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* most Rtlxx functions we are using here require this */
if(!NT_SUCCESS(Status))
{
Assert(0);
break;
}
#else
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
#endif
/*
* Now open the adapter below and complete the initialization
*/
&Sts,
sizeof(g_aMediumArray)/sizeof(NDIS_MEDIUM),
0,
NULL);
if (Status == NDIS_STATUS_PENDING)
{
}
if(Status != NDIS_STATUS_SUCCESS)
{
break;
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
if (Status != NDIS_STATUS_SUCCESS)
{
Log(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",
break;
}
#endif
} while(0);
return Status;
}
/**
* Called by NDIS to bind to a miniport below.
* @param Status - Return status of bind here.
* @param BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended.
* @param DeviceName - Device name to bind to. This is passed to NdisOpenAdapter.
* @param SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information
* @paran SystemSpecific2 - Unused
* @return NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter to complete.
* Anything else Completes this call synchronously */
static VOID
)
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* we initiate the binding ourselves by calling NdisOpenAdapter */
LogFlow(("==> Protocol BindAdapter\n"));
Assert(0);
LogFlow(("<== Protocol BindAdapter\n"));
return;
#else
LogFlow(("==> Protocol BindAdapter\n"));
do
{
/* Access the configuration section for our binding-specific
* parameters. */
if (*pStatus != NDIS_STATUS_SUCCESS)
{
break;
}
/* Read the "UpperBindings" reserved key that contains a list
* of device names representing our miniport instances corresponding
* to this lower binding. Since this is a 1:1 IM driver, this key
* contains exactly one name.
*
* If we want to implement a N:1 mux driver (N adapter instances
* over a single lower binding), then UpperBindings will be a
* MULTI_SZ containing a list of device names - we would loop through
* this list, calling NdisIMInitializeDeviceInstanceEx once for
* each name in it. */
&Param,
if (*pStatus != NDIS_STATUS_SUCCESS)
{
break;
}
if (*pStatus != NDIS_STATUS_SUCCESS)
{
break;
}
} while(FALSE);
/*
* Close the configuration handle now - see comments above with
* the call to NdisIMInitializeDeviceInstanceEx.
*/
if (ConfigHandle != NULL)
{
}
#endif
}
/**
* Completion routine for NdisOpenAdapter issued from within the vboxNetFltWinPtBindAdapter. Simply
* unblock the caller.
*
* @param ProtocolBindingContext Pointer to the adapter
* @param Status Status of the NdisOpenAdapter call
* @param OpenErrorStatus Secondary status(ignored by us).
* @return None
* */
static VOID
)
{
{
}
}
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
ULONG NumberOfPackets = 0, i;
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/*
* Set the flag that the miniport below is unbinding, so the request handlers will
* fail any request comming later
*/
// pAdapt->PTState.DeviceState = NdisDeviceStateD3;
// pAdapt->MPState.DeviceState = NdisDeviceStateD3;
if(!bOnUnbind)
{
}
{
}
if (pAdapt->cReceivedPacketCount > 0)
{
pAdapt->cReceivedPacketCount = 0;
}
if (CompleteRequest == TRUE)
{
}
if (ReturnPackets == TRUE)
{
for (i = 0; i < NumberOfPackets; i++)
{
}
}
{
/*
* sleep till outstanding requests complete
*/
}
#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */
{
/*
* We need to do some work here.
* Close the binding below us
* and release the memory allocated.
*/
if(!bOnUnbind)
{
}
else
{
}
}
else
{
}
return Status;
}
/**
* Called by NDIS when we are required to unbind to the adapter below.
* This functions shares functionality with the miniport's HaltHandler.
* The code should ensure that NdisCloseAdapter and NdisFreeMemory is called
* only once between the two functions
*
* @param Status Placeholder for return status
* @param ProtocolBindingContext Pointer to the adapter structure
* @param UnbindContext Context for NdisUnbindComplete() if this pends
* @return NONE */
static VOID
)
{
}
/**
* protocol unload handler
*/
static VOID
)
{
LogFlow(("vboxNetFltWinPtUnloadProtocol: done!\n"));
}
/**
* Completion for the CloseAdapter call.
*
* @param ProtocolBindingContext Pointer to the adapter structure
* @param Status Completion status
* @return None */
static VOID
)
{
{
}
}
/**
* Completion for the reset.
*
* @param ProtocolBindingContext Pointer to the adapter structure
* @param Status Completion status
* @return None */
static VOID
)
{
/*
* We never issue a reset, so we should not be here.
*/
Assert(0);
}
/**
* Completion handler for the previously posted request. All OIDS
* are completed by and sent to the same miniport that they were requested for.
* If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =
* NdisDeviceStateUnspecified
* @param ProtocolBindingContext Pointer to the adapter structure
* @param NdisRequest The posted request
* @param Status Completion status
* @return None
*
*/
)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
if(pSynchRequest == NdisRequest)
{
/* assynchronous completion of our synch request */
/*1.set the status */
/* 2. set event */
/* 3. return; */
return;
}
#ifdef VBOX_NETFLT_ONDEMAND_BIND
Assert(0);
return;
#else
/*
* Since our request is not outstanding anymore
*/
/*
* Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
*/
switch (NdisRequest->RequestType)
{
/*
* We never pass OID_PNP_QUERY_POWER down.
*/
{
}
{
/* save mac options for adaptor below us to use it with the NdisCopyLookaheadData when our ProtocolReceive is called */
/* we have to catch loopbacks from the underlying driver, so no duplications will occur,
* just indicate NDIS to handle loopbacks for the packets coming from the protocol */
}
{
if(Status == NDIS_STATUS_SUCCESS)
{
/* the filter request is issued below only in case netflt is not active,
* simply update the cache here */
/* cache the filter used by upper protocols */
pAdapt->bUpperProtSetFilterInitialized = true;
}
}
Status);
break;
{
{
if(Status == NDIS_STATUS_SUCCESS)
{
}
pAdapt->bProcessingPacketFilter = false;
}
else
{
if(Status == NDIS_STATUS_SUCCESS)
{
/* the request was issued when the netflt was not active, simply update the cache here */
pAdapt->fUpperProtocolSetFilter = *((PULONG)pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer);
pAdapt->bUpperProtSetFilterInitialized = true;
}
}
}
Status);
break;
default:
Assert(0);
break;
}
#endif
}
/**
* Status handler for the lower-edge(protocol).
*
* @param ProtocolBindingContext Pointer to the adapter structure
* @param GeneralStatus Status code
* @param StatusBuffer Status buffer
* @param StatusBufferSize Size of the status buffer
* @return None
*/
static VOID
)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/*
* Pass up this indication only if the upper edge miniport is initialized
* and powered on. Also ignore indications that might be sent by the lower
* miniport when it isn't at D0.
*/
{
if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) ||
{
}
}
/*
* Save the last indicated media status
*/
else
{
((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) ||
{
}
}
#endif
}
/**
* status complete handler
*/
static VOID
)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/*
* Pass up this indication only if the upper edge miniport is initialized
* and powered on. Also ignore indications that might be sent by the lower
* miniport when it isn't at D0.
*/
{
}
#endif
}
/**
* Called by NDIS when the miniport below had completed a send. We should
* complete the corresponding upper-edge send this represents.
*
* @param ProtocolBindingContext - Points to ADAPT structure
* @param Packet - Low level packet being completed
* @param Status - status of send
* @return None
*/
static VOID
)
{
{
#ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// PPACKET_INFO pInfo = vboxNetFltWinDoCompleteSend(pAdapt, Packet);
//
// if(pInfo)
// {
// vboxNetFltWinPpFreePacketInfo(pInfo);
// }
#endif
// Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
#ifndef VBOX_NETFLT_ONDEMAND_BIND
if(Pkt)
{
#ifndef WIN9X
#endif
/* the ptk was posted from the upperlying protocol */
Pkt,
Status);
}
else
#else
/* TODO: should change the PSEND_RSVD structure as we no nolnger need to handle original packets
* because all packets are originated by us */
#endif
{
* need to free packet buffers */
if(pBufToFree)
{
}
}
}
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/**
* removes searches for the packet in the list and removes it if found
* @return true if the packet was found and removed, false - otherwise
*/
{
true /* remove*/);
}
/**
* puts the packet to the tail of the list
*/
static void vboxNetFltWinPutPacketToList(PINTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket, PNDIS_BUFFER pOrigBuffer)
{
}
#endif
{
return false;
do
{
/* data transfer was initiated when the netFlt was active
* the netFlt is still retained by us
* 1. check if loopback
* 2. enqueue packet
* 3. release netFlt */
if(Status == NDIS_STATUS_SUCCESS)
{
#ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// /* 1. if loopback then quit with NDIS_STATUS_NOT_ACCEPTED */
//#ifdef VBOX_NETFLT_ONDEMAND_BIND
// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket))
//#else
// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket, true))
//#endif
#else
#endif
{
Assert(0);
}
else
{
/* 2. enqueue */
/* use the same packet info to put the packet in the processing packet queue */
#ifdef VBOX_NETFLT_ONDEMAND_BIND
#else
#endif
if(Status == NDIS_STATUS_SUCCESS)
{
break;
}
Assert(0);
}
}
else
{
Assert(0);
}
/* we are here because of error either in data transfer or in enqueueing the packet */
vboxNetFltWinFreeSGNdisPacket(pPacket, true);
} while(0);
return true;
}
/**
* Entry point called by NDIS to indicate completion of a call by us
* to NdisTransferData.
*
* See notes under SendComplete.
*/
static VOID
)
{
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
if(pAdapt->hMiniportHandle)
{
}
#else
/* we are here because we've failed to allocate packet info */
Assert(0);
#endif
}
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/**
* This is to queue the received packets and indicates them up if the given Packet
* status is NDIS_STATUS_RESOURCES, or the array is full.
*
* @param pAdapt - Pointer to the adpater structure.
* @param Packet - Pointer to the indicated packet.
* @param Indicate - Do the indication now.
* @return NONE
*/
static VOID
)
{
ULONG NumberOfPackets = 0, i;
bool bReturn = false;
do{
{
bReturn = true;
break;
}
/*
* pAdapt->ReceviePacketCount must be less than MAX_RECEIVE_PACKET_ARRAY_SIZE because
* the thread which held the pVElan->Lock before should already indicate the packet(s)
* up if pAdapt->ReceviePacketCount == MAX_RECEIVE_PACKET_ARRAY_SIZE.
*/
/*
* If our receive packet array is full, or the miniport below indicated the packets
* with resources, do the indicatin now.
*/
{
/*
* So other thread can queue the received packets
*/
pAdapt->cReceivedPacketCount = 0;
DoIndicate = TRUE;
}
} while(0);
if(!bReturn)
{
if(DoIndicate)
{
}
}
else
{
if (DoIndicate)
{
NumberOfPackets -= 1;
}
for (i = 0; i < NumberOfPackets; i++)
{
}
}
}
/**
* This routine process the queued the packet, if anything is fine, indicate the packet
* up, otherwise, return the packet to the underlying miniports.
*
* @param pAdapt - Pointer to the adpater structure.
* @param bReturn - if true the packets should be returned without indication to the upper protocol
* @return None. */
)
{
ULONG NumberOfPackets = 0, i;
do
{
if (pAdapt->cReceivedPacketCount > 0)
{
/*
* So other thread can queue the received packets
*/
pAdapt->cReceivedPacketCount = 0;
if(!bReturn)
{
if(NumberOfPackets > 0)
{
/* we are here because the NetFlt is NOT active,
* so no need for packet queueing here, simply indicate */
}
break;
}
/*
* We need return the packet here
*/
for (i = 0; i < NumberOfPackets; i ++)
{
}
/* break to ensure we do not call RTSpinlockRelease extra time */
break;
}
/* we are here only in case pAdapt->cReceivedPacketCount == 0 */
} while (FALSE);
}
/**
* ReceivePacket handler. Called by NDIS if the miniport below supports
* NDIS 4.0 style receives. Re-package the buffer chain in a new packet
* and indicate the new packet to protocols above us. Any context for
* packets indicated up must be kept in the MiniportReserved field.
*
* @param ProtocolBindingContext - Pointer to our adapter structure.
* @param Packet - Pointer to the packet
* @return INT == 0 -> We are done with the packet
* != 0 -> We will keep the packet and call NdisReturnPackets() this
* many times when done. */
static INT
)
{
{
if (fStatus == NDIS_STATUS_RESOURCES)
{
/*
* Our ReturnPackets handler will not be called for this packet.
* We should reclaim it right here.
*/
return 0;
}
return 1;
}
return 0;
}
/**
* process the packet receive in a "passthru" mode
*/
static NDIS_STATUS
{
/*
* The miniport below did indicate up a packet. Use information
* from that packet to construct a new packet to indicate up.
*/
/*
* Get a packet off the pool and indicate that up
*/
if (fStatus == NDIS_STATUS_SUCCESS)
{
/*
* Make our packet point to data from the original
* packet. NOTE: this works only because we are
* indicating a receive directly from the context of
* our receive indication. If we need to queue this
* packet and indicate it from another thread context,
* we will also have to allocate a new buffer and copy
* over the packet contents, OOB data and per-packet
* information. This is because the packet data
* is available only for the duration of this
* receive indication call.
*/
/*
* Get the original packet (it could be the same packet as the
* one received or a different one based on the number of layered
* miniports below) and set it on the indicated packet so the OOB
* data is visible correctly at protocols above.
*/
/*
* Copy packet flags.
*/
/*
* Force protocols above to make a copy if they want to hang
* on to data in this packet. This is because we are in our
* Receive handler (not ReceivePacket) and we can't return a
* ref count from here.
*/
/*
* By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
* this packet as soon as the call to NdisMIndicateReceivePacket
* returns.
*
* NOTE: we queue the packet and indicate this packet immediately with
* the already queued packets together. We have to the queue the packet
* first because some versions of NDIS might call protocols'
* ReceiveHandler(not ReceivePacketHandler) if the packet indicate status
* is NDIS_STATUS_RESOURCES. If the miniport below indicates an array of
* packets, some of them with status NDIS_STATUS_SUCCESS, some of them
* with status NDIS_STATUS_RESOURCES, vboxNetFltWinPtReceive might be called, by
* doing this way, we preserve the receive order of packets.
*/
/*
* Reclaim the indicated packet. Since we had set its status
* to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
* above are done with it.
*/
}
return fStatus;
}
#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */
/**
* process the ProtocolReceive in an "active" mode
*
* @return NDIS_STATUS_SUCCESS - the packet is processed
* NDIS_STATUS_PENDING - the packet is being processed, we are waiting for the ProtocolTransferDataComplete to be called
* NDIS_STATUS_NOT_ACCEPTED - the packet is not needed - typically this is because this is a loopback packet
* NDIS_STATUS_FAILURE - packet processing failed
*/
static NDIS_STATUS
)
{
do
{
if (cbHeaderBuffer != ETH_HEADER_SIZE)
{
break;
}
#ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
/* can check for loopback? check it*/
if (cbPacket == cbLookaheadBuffer)
{
#ifdef DEBUG_NETFLT_LOOPBACK
/* TODO: can we check for loopback here ?
* for now just get the complete SG and then decide if it is a loopback one */
/* if loopback then quit */
#endif
/* allocate SG buffer */
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
#ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// /* check if it is a loopback */
//# ifdef VBOX_NETFLT_ONDEMAND_BIND
// if(vboxNetFltWinIsLoopedBackPacketSG(pAdapt, pSG))
//# else
// if(vboxNetFltWinIsLoopedBackPacketSG(pAdapt, pSG, true))
//# endif
// {
// Assert(0);
// vboxNetFltWinMemFree(pSG);
// Status = NDIS_STATUS_NOT_ACCEPTED;
// break;
// }
#endif
/* enqueue SG */
#ifdef VBOX_NETFLT_ONDEMAND_BIND
{
}
#else
#endif
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
}
else
#endif /* #ifndef DEBUG_NETFLT_RECV_TRANSFERDATA */
{
// PPACKET_INFO pInfo;
/* TODO: can check for loopback here ? */
/* for now just get the complete complete packet and then decide if it is a looped back one */
/* if loopback then quit with NDIS_STATUS_NOT_ACCEPTED
* {
* Status = NDIS_STATUS_NOT_ACCEPTED;
* break;
* }
* */
/* allocate NDIS Packet buffer */
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* use the Send packet pool for packet allocation */
#else
#endif
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
/* set "don't loopback" flags */
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* use the Send buffer pool for buffer allocation */
NdisAllocateBuffer(&Status, &pTransferBuffer, pAdapt->hSendBufferPoolHandle, pMemBuf + cbHeaderBuffer, cbPacket);
#else
NdisAllocateBuffer(&Status, &pTransferBuffer, pAdapt->hRecvBufferPoolHandle, pMemBuf + cbHeaderBuffer, cbPacket);
#endif
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* use the Send buffer pool for buffer allocation */
#else
#endif
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
if(cbPacket == cbLookaheadBuffer)
{
}
else
#endif
{
&Status,
0, /* ByteOffset */
}
if(Status != NDIS_STATUS_PENDING)
{
}
}
} while(0);
return Status;
}
/**
* Handle receive data indicated up by the miniport below. We pass
* it along to the protocol above us.
*
* If the miniport below indicates packets, NDIS would more
* likely call us at our ReceivePacket handler. However we
* might be called here in certain situations even though
* the miniport below has indicated a receive packet, e.g.
* if the miniport had set packet status to NDIS_STATUS_RESOURCES.
*
* @param ProtocolBindingContext
* @param MacReceiveContext
* @param pHeaderBuffer
* @param cbHeaderBuffer
* @param pLookAheadBuffer
* @param cbLookAheadBuffer
* @param cbPacket
* @return NDIS_STATUS_SUCCESS if we processed the receive successfully,
* NDIS_STATUS_XXX error code if we discarded it. */
static NDIS_STATUS
)
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
#if 0
#endif
if(pNetFltIf)
{
do
{
#if 0
if(pPacket)
{
# ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket))
# else
# endif
{
// Assert(0);
/* nothing else to do here, just return the packet */
// NdisReturnPackets(&pPacket, 1);
// break;
}
if(Status == NDIS_STATUS_SUCCESS)
{
break;
}
}
#endif
if(NT_SUCCESS(Status))
{
if(Status != NDIS_STATUS_NOT_ACCEPTED)
{
}
else
{
/* this is a looopback packet, nothing to do here */
}
break;
}
} while(0);
if(pNetFltIf)
if(pAdapt)
#if 0
if(pPacket)
{
}
#endif
/* we are here because the vboxNetFltWinPtReceiveActive returned pending,
* which means our ProtocolDataTransferComplete we will called,
* so return SUCCESS instead of NOT_ACCEPTED ?? */
// return NDIS_STATUS_SUCCESS;
}
return NDIS_STATUS_NOT_ACCEPTED;
#else /* if NOT defined VBOX_NETFLT_ONDEMAND_BIND */
if(fAdaptActive)
{
do
{
#ifndef DEBUG_NETFLT_RECV_NOPACKET
/*
* Get at the packet, if any, indicated up by the miniport below.
*/
{
do
{
#ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket, true))
#else
#endif
{
Assert(0);
/* nothing else to do here, just return the packet */
//NdisReturnPackets(&pPacket, 1);
break;
}
if(pNetFltIf)
{
if(Status == NDIS_STATUS_SUCCESS)
{
//NdisReturnPackets(&pPacket, 1);
fAdaptActive = false;
break;
}
}
/* we are done with packet processing, and we will
* not receive packet return event for this packet,
* fAdaptActive should be true to ensure we release adapt*/
} while(FALSE);
{
break;
}
}
#endif /* todo: remove */
if(pNetFltIf)
{
if(NT_SUCCESS(Status))
{
if(Status != NDIS_STATUS_NOT_ACCEPTED)
{
fAdaptActive = false;
}
else
{
/* this is a loopback packet, nothing to do here */
}
break;
}
}
/* Fall through if the miniport below us has either not
* indicated a packet or we could not allocate one */
{
/*
* We are here because we failed to allocate packet
*/
vboxNetFltWinPtFlushReceiveQueue(pAdapt, false);
}
/* we are done with packet processing, and we will
* not receive packet return event for this packet,
* fAdaptActive should be true to ensure we release adapt*/
{
case NdisMedium802_3:
case NdisMediumWan:
cbPacket);
break;
default:
break;
}
} while(0);
if(pNetFltIf)
if(fAdaptActive)
}
else
{
}
return Status;
#endif
}
/**
* Called by the adapter below us when it is done indicating a batch of
* received packets.
*
* @param ProtocolBindingContext Pointer to our adapter structure.
* @return None */
static VOID
)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
ULONG NumberOfPackets = 0;
vboxNetFltWinPtFlushReceiveQueue(pAdapt, false);
/* && (pAdapt->MPDeviceState == NdisDeviceStateD0) */
{
{
case NdisMedium802_3:
case NdisMediumWan:
break;
default:
break;
}
}
#endif
}
/**
* ReceivePacket handler. Called by NDIS if the miniport below supports
* NDIS 4.0 style receives. Re-package the buffer chain in a new packet
* and indicate the new packet to protocols above us. Any context for
* packets indicated up must be kept in the MiniportReserved field.
*
* @param ProtocolBindingContext - Pointer to our adapter structure.
* @param Packet - Pointer to the packet
* @return == 0 -> We are done with the packet,
* != 0 -> We will keep the packet and call NdisReturnPackets() this many times when done.
*/
static INT
)
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
if(pNetFltIf)
{
bool bResources;
do
{
#ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket))
#else
#endif
{
Assert(0);
break;
}
if(!pBuffer)
{
Assert(0);
cRefCount = 0;
break;
}
{
Assert(0);
cRefCount = 0;
break;
}
Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, bResources ? fFlags | PACKET_COPY : fFlags);
if(Status == NDIS_STATUS_SUCCESS)
{
if(bResources)
{
cRefCount = 0;
}
else
{
cRefCount = 1;
}
break;
}
else
{
Assert(0);
cRefCount = 0;
break;
}
} while (0);
if(pNetFltIf)
if(pAdapt)
return cRefCount;
}
/* we are here because we are inactive, simply return the packet */
return 0;
#else
if(fAdaptActive)
{
do
{
#ifdef DEBUG_NETFLT_LOOPBACK
# error "implement (see comments in the sources below this #error:)"
/* @todo FIXME no need for the PPACKET_INFO mechanism here;
instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
similar to that used in TrasferData handling should be used;
*/
// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket, true))
#else
#endif
{
Assert(0);
Log(("lb_rp"));
/* nothing else to do here, just return the packet */
cRefCount = 0;
//NdisReturnPackets(&pPacket, 1);
break;
}
if(pNetFltIf)
{
/*TODO: remove this assert.
* this is a temporary assert for debugging purposes:
* we're probably doing something wrong with the packets if the miniport reports NDIS_STATUS_RESOURCES */
Assert(!bResources);
if(fStatus == NDIS_STATUS_SUCCESS)
{
fAdaptActive = false;
if(bResources)
{
cRefCount = 0;
//NdisReturnPackets(&pPacket, 1);
}
else
{
cRefCount = 1;
}
break;
}
else
{
Assert(0);
}
}
if(cRefCount)
{
fAdaptActive = false;
}
} while(FALSE);
if(pNetFltIf)
if(fAdaptActive)
}
else
{
cRefCount = 0;
//NdisReturnPackets(&pPacket, 1);
}
return cRefCount;
#endif
}
/**
* This routine is called from NDIS to notify our protocol edge of a
* reconfiguration of parameters for either a specific binding (pAdapt
* is not NULL), or global parameters if any (pAdapt is NULL).
*
* @param pAdapt - Pointer to our adapter structure.
* @param pNetPnPEvent - the reconfigure event
* @return NDIS_STATUS_SUCCESS */
static NDIS_STATUS
)
{
do
{
/*
* Is this is a global reconfiguration notification ?
*/
{
/*
* An important event that causes this notification to us is if
* one of our upper-edge miniport instances was enabled after being
* disabled earlier, e.g. from Device Manager in Win2000. Note that
* NDIS calls this because we had set up an association between our
* miniport and protocol entities by calling NdisIMAssociateMiniport.
*
* Since we would have torn down the lower binding for that miniport,
* we need NDIS' assistance to re-bind to the lower miniport. The
* call to NdisReEnumerateProtocolBindings does exactly that.
*/
break;
}
} while(FALSE);
return ReconfigStatus;
}
static NDIS_STATUS
)
{
return NDIS_STATUS_SUCCESS;
}
{
if(pAdapt->bClosingAdapter)
{
Assert(0);
return false;
}
{
Assert(0);
return false;
}
pAdapt->bClosingAdapter = true;
/*
* Close the binding below. and wait for it to complete
*/
if (*pStatus == NDIS_STATUS_PENDING)
{
}
return true;
}
/**
* This is a notification to our protocol edge of the power state
* of the lower miniport. If it is going to a low-power state, we must
* wait here for all outstanding sends and requests to complete.
*
* @param pAdapt - Pointer to the adpater structure
* @param pNetPnPEvent - The Net Pnp Event. this contains the new device state
* @return NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.
* */
static NDIS_STATUS
)
{
/*
* Set the Internal Device State, this blocks all new sends or receives
*/
/*
* Check if the miniport below is going to a low power state.
*/
{
/*
* If the miniport below is going to standby, fail all incoming requests
*/
if (PrevDeviceState == NdisDeviceStateD0)
{
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
vboxNetFltWinPtFlushReceiveQueue(pAdapt, false);
#endif
/*
* Wait for outstanding sends and requests to complete.
*/
#ifndef VBOX_NETFLT_ONDEMAND_BIND
{
/*
* sleep till outstanding requests complete
*/
}
/*
* If the below miniport is going to low power state, complete the queued request
*/
if (pAdapt->bQueuedRequest)
{
}
else
{
}
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
}
else
{
/*
* If the physical miniport is powering up (from Low power state to D0),
* clear the flag
*/
if (PrevDeviceState > NdisDeviceStateD0)
{
}
#ifdef VBOX_NETFLT_ONDEMAND_BIND
#else
/*
* The device below is being turned on. If we had a request
* pending, send it down now.
*/
{
if (Status != NDIS_STATUS_PENDING)
{
Status);
}
}
else
{
}
#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */
}
return ReturnStatus;
}
/**
* This is called by NDIS to notify us of a PNP event related to a lower
* binding. Based on the event, this dispatches to other helper routines.
*
* @param ProtocolBindingContext - Pointer to our adapter structure. Can be NULL
* for "global" notifications
* @param pNetPnPEvent - Pointer to the PNP event to be processed.
* @return NDIS_STATUS code indicating status of event processing.
* */
static NDIS_STATUS
)
{
switch (pNetPnPEvent->NetEvent)
{
case NetEventSetPower:
break;
case NetEventReconfigure:
break;
case NetEventBindsComplete:
DBGPRINT(("NetEventBindsComplete"));
break;
default:
break;
}
return Status;
}
#ifdef __cplusplus
#else
#endif
/**
* register the protocol edge
*/
)
{
/*
* Now register the protocol.
*/
/*
* Make sure the protocol-name matches the service-name
* (from the INF) under which this protocol is installed.
* This is needed to ensure that NDIS can correctly determine
* the binding and call us to bind to miniports below.
*/
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(DEBUG_NETFLT_RECV)
#else
#endif
&PChars,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
return Status;
}
/**
* deregister the protocol edge
*/
{
if (g_hProtHandle != NULL)
{
}
return Status;
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/**
* returns the protocol handle
*/
{
return g_hProtHandle;
}
#endif