Beispiel #1
0
NDIS_STATUS
MiniportTransferData5(
    OUT PNDIS_PACKET            Packet,
    OUT PUINT                   BytesTransferred,
    IN NDIS_HANDLE              MiniportAdapterContext,
    IN NDIS_HANDLE              MiniportReceiveContext,
    IN UINT                     ByteOffset,
    IN UINT                     BytesToTransfer
    )
{
    PADAPTER      pAdapt = (PADAPTER)MiniportAdapterContext;
    NDIS_STATUS   Status;

    //
    // Return, if the device is OFF
    //

    if (IsIMDeviceStateOn(pAdapt) == FALSE)
    {
        return NDIS_STATUS_FAILURE;
    }

    NdisTransferData(&Status,
                     pAdapt->BindingHandle,
                     MiniportReceiveContext,
                     ByteOffset,
                     BytesToTransfer,
                     Packet,
                     BytesTransferred);

    return(Status);
}
Beispiel #2
0
NDIS_STATUS NDIS_API PacketReceiveIndicate(IN NDIS_HANDLE ProtocolBindingContext,
                                           IN NDIS_HANDLE MacReceiveContext,
                                           IN PVOID       HeaderBuffer,
                                           IN UINT        HeaderBufferSize,
                                           IN PVOID       LookaheadBuffer,
                                           IN UINT        LookaheadBufferSize,
                                           IN UINT        PacketSize)
{
  // upcall on packet arrival

  POPEN_INSTANCE      Open;
  PLIST_ENTRY         PacketListEntry;
  PNDIS_PACKET        pPacket;
  NDIS_STATUS         Status;
  UINT                BytesTransfered = 0;
  PPACKET_RESERVED    pReserved;


  if (HeaderBufferSize != ETHERNET_HEADER_LENGTH)
    return NDIS_STATUS_NOT_ACCEPTED;
  
  Open = (POPEN_INSTANCE) ProtocolBindingContext;
  
  //  See if there are any pending reads that we can satisfy
  NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 5.11.97
  
  if (IsListEmpty(&Open->RcvList)) { 
    NdisReleaseSpinLock(&Open->RcvQSpinLock);
    return NDIS_STATUS_NOT_ACCEPTED;
  }

  PacketListEntry = RemoveHeadList(&Open->RcvList);
  NdisReleaseSpinLock(&Open->RcvQSpinLock);
  
  pReserved = CONTAINING_RECORD(PacketListEntry, PACKET_RESERVED, ListElement);
  pPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved);
  
  // Copy the MAC header
  NdisMoveMemory(RESERVED(pPacket)->lpBuffer, HeaderBuffer, HeaderBufferSize);

  //  Call the Mac to transfer the data portion of the packet
  NdisTransferData(&Status, Open->AdapterHandle, MacReceiveContext, 0, PacketSize, pPacket, &BytesTransfered);
  if (Status == NDIS_STATUS_PENDING)
    return NDIS_STATUS_PENDING;

  if (Status == NDIS_STATUS_SUCCESS) {
    PacketTransferDataComplete(Open, pPacket, Status, BytesTransfered);
    return NDIS_STATUS_SUCCESS;
  }

  PacketTransferDataComplete(Open, pPacket, Status, 0);
  return NDIS_STATUS_SUCCESS;
}
Beispiel #3
0
NDIS_STATUS
MPTransferData(
    OUT PNDIS_PACKET            Packet,
    OUT PUINT                   BytesTransferred,
    IN NDIS_HANDLE              MiniportAdapterContext,
    IN NDIS_HANDLE              MiniportReceiveContext,
    IN UINT                     ByteOffset,
    IN UINT                     BytesToTransfer
    )
/*++

Routine Description:

    Miniport's transfer data handler.

Arguments:

    Packet                    Destination packet
    BytesTransferred          Place-holder for how much data was copied
    MiniportAdapterContext    Pointer to the adapter structure
    MiniportReceiveContext    Context
    ByteOffset                Offset into the packet for copying data
    BytesToTransfer           How much to copy.

Return Value:

    Status of transfer

--*/
{
    PADAPT        pAdapt = (PADAPT)MiniportAdapterContext;
    NDIS_STATUS   Status;

    //
    // Return, if the device is OFF
    //

    if (IsIMDeviceStateOn(pAdapt) == FALSE)
    {
        return NDIS_STATUS_FAILURE;
    }

    NdisTransferData(&Status,
                     pAdapt->BindingHandle,
                     MiniportReceiveContext,
                     ByteOffset,
                     BytesToTransfer,
                     Packet,
                     BytesTransferred);

    return(Status);
}
Beispiel #4
0
NDIS_STATUS
PacketReceiveIndicate (
    IN NDIS_HANDLE ProtocolBindingContext,
    IN NDIS_HANDLE MacReceiveContext,
    IN PVOID       HeaderBuffer,
    IN UINT        HeaderBufferSize,
    IN PVOID       LookAheadBuffer,
    IN UINT        LookaheadBufferSize,
    IN UINT        PacketSize
)
{
	POPEN_INSTANCE      open;
	PIO_STACK_LOCATION  irpSp;
	PIRP                irp;
	PLIST_ENTRY         packetListEntry;
	PNDIS_PACKET        pPacket;
	ULONG               sizeToTransfer;
	NDIS_STATUS         status;
	UINT                bytesTransfered = 0;
	ULONG               bufferLength;
	PPACKET_RESERVED    reserved;
	PMDL                pMdl;

	// DebugPrint(("ReceiveIndicate\n"));

	open= (POPEN_INSTANCE)ProtocolBindingContext;

	if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) {
			return NDIS_STATUS_SUCCESS;
	}

	//  See if there are any pending read that we can satisfy
	packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock );

	if (packetListEntry == NULL) {
		// DebugPrint(("No pending read, dropping packets\n"));
		return NDIS_STATUS_NOT_ACCEPTED;
	}

	reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement);
	pPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

	irp = RESERVED(pPacket)->Irp;
	irpSp = IoGetCurrentIrpStackLocation(irp);

	// We don't have to worry about the situation where the IRP is cancelled
	// after we remove it from the queue and before we reset the cancel
	// routine because the cancel routine has been coded to cancel an IRP
	// only if it's in the queue.

	IoSetCancelRoutine(irp, NULL);

	bufferLength = irpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH;

		sizeToTransfer = (PacketSize < bufferLength) ? PacketSize : bufferLength;

	NdisMoveMappedMemory(
			MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority),
			HeaderBuffer,
			HeaderBufferSize
			);

	pMdl=IoAllocateMdl(
						MmGetMdlVirtualAddress(irp->MdlAddress),
						MmGetMdlByteCount(irp->MdlAddress),
						FALSE,
						FALSE,
						NULL
						);

	if (pMdl == NULL) {
		// DebugPrint(("Packet: Read-Failed to allocate Mdl\n"));
		status = NDIS_STATUS_RESOURCES;
		goto ERROR;
	}

	IoBuildPartialMdl(
			irp->MdlAddress,
			pMdl,
			((PUCHAR)MmGetMdlVirtualAddress(irp->MdlAddress))+ETHERNET_HEADER_LENGTH,
			0
			);

	pMdl->Next = NULL;

	RESERVED(pPacket)->pMdl=pMdl;

	NdisChainBufferAtFront(pPacket,pMdl);

	NdisTransferData(
			&status,
			open->AdapterHandle,
			MacReceiveContext,
			0,
			sizeToTransfer,
			pPacket,
			&bytesTransfered
	);

	if (status == NDIS_STATUS_PENDING) {
		return NDIS_STATUS_SUCCESS;
	}

ERROR:
	PacketTransferDataComplete( open, pPacket, status, bytesTransfered );
	return NDIS_STATUS_SUCCESS;
}
Beispiel #5
0
int divert_filter(
   IN PADAPT         pAdapt,
   IN NDIS_HANDLE    MacReceiveContext,
   IN PVOID          HeaderBuffer,
   IN UINT           HeaderBufferSize,
   IN PVOID          LookAheadBuffer,
   IN UINT           LookAheadBufferSize,
   IN UINT           PacketSize
   )
{
#define MAC_SIZE 14
	USHORT               EtherType;
	ULONG                NumberOfBytesRead;
	struct ether_header  *pEthHdr;      // See ../B2Winet/ethernet.h
	struct ip            *pIPHeader;
	struct tcphdr	     *tcp;
	int rc = 0;
	struct divert_packet *dp, *cur;
	NDISPROT_ETH_HEADER UNALIGNED *pEthHeader;

	NdisDprAcquireSpinLock(&pAdapt->Lock);

	pEthHdr = (struct ether_header * )HeaderBuffer;
	pEthHeader = pEthHdr;

	if (ntohs( pEthHdr->ether_type ) != ETHERTYPE_IP)
		goto Out;

	if (get_pa(pEthHeader->SrcAddr))
		goto Out;

	pIPHeader = (struct ip * )LookAheadBuffer;

	if (LookAheadBufferSize < 40)
		goto Out;

	if (pIPHeader->ip_p != IPPROTO_TCP)
		goto Out;

	tcp = (struct tcphr*) (pIPHeader + 1);

#if 0
	if (ntohs(tcp->th_dport) == 666)
		rc = 1;
#endif

	lock();

	if (!_open)
		goto Outl;

	dp = get_packet();
	if (!dp) {
		DbgPrint("Out of queue - shit\n");
		goto Outl;
	}

	if (LookAheadBufferSize != PacketSize) {
		NDIS_STATUS status;
		PNDIS_PACKET pkt;
		PNDIS_BUFFER buf;
		int len;

		if ((PacketSize + MAC_SIZE) > sizeof(dp->dp_packet)) {
			DbgPrint("cAZZOOOOOOOOOOOOOOOOOOOOOOOOOOo\n");
			goto Fanculo;
		}

		NdisAllocatePacket(&status, &pkt, _packet_pool);
		NdisAllocateBuffer(&status, &buf, _buf_pool,
				   dp->dp_packet + MAC_SIZE,
				   sizeof(dp->dp_packet) - MAC_SIZE);
		NdisChainBufferAtFront(pkt, buf);
		NdisTransferData(&status, pAdapt->BindingHandle,
				 MacReceiveContext, 0,
				 PacketSize, pkt, &len);
		NdisFreeBuffer(buf);
		NdisFreePacket(pkt);
	} else {
		NdisCopyLookaheadData(dp->dp_packet + MAC_SIZE,
				      LookAheadBuffer,
				      LookAheadBufferSize,
				      0);
	}

Fanculo:
	rc = 1;

	memcpy(dp->dp_packet, pEthHdr, MAC_SIZE);

	dp->dp_len   = PacketSize + MAC_SIZE;
	dp->dp_flags = 1;

	kick_pending();

Outl:
	unlock();
Out:
	NdisDprReleaseSpinLock(&pAdapt->Lock);

	return rc;
#undef MAC_SIZE
}
Beispiel #6
0
NDIS_STATUS
LpxReceiveIndication (
	IN NDIS_HANDLE	ProtocolBindingContext,
	IN NDIS_HANDLE	MacReceiveContext,
	IN PVOID		HeaderBuffer,
	IN UINT		    HeaderBufferSize,
	IN PVOID		LookAheadBuffer,
	IN UINT		    LookAheadBufferSize,
	IN UINT		    PacketSize
	)
/*++

Routine Description:

	This routine receives control from the physical provider as an
	indication that a frame has been received on the physical link.
	This routine is time critical, so we only allocate a
	buffer and copy the packet into it. We also perform minimal
	validation on this packet. It gets queued to the device context
	to allow for processing later.

Arguments:

	BindingContext - The Adapter Binding specified at initialization time.

	ReceiveContext - A magic cookie for the MAC.

	HeaderBuffer - pointer to a buffer containing the packet header.

	HeaderBufferSize - the size of the header.

	LookaheadBuffer - pointer to a buffer containing the negotiated minimum
		amount of buffer I get to look at (not including header).

	LookaheadBufferSize - the size of the above. May be less than asked
		for, if that's all there is.

	PacketSize - Overall size of the packet (not including header).

Return Value:

	NDIS_STATUS - status of operation, one of:

			     NDIS_STATUS_SUCCESS if packet accepted,
			     NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
			     NDIS_any_other_thing if I understand, but can't handle.

--*/
{
	PDEVICE_CONTEXT	deviceContext;
	USHORT		    protocol;
	PNDIS_PACKET	packet;
	NDIS_STATUS		status;
	UINT		    bytesTransfered = 0;
	UINT		    startOffset = 0;


	DebugPrint( 4, ("LpxReceiveIndication, Entered\n") );
	
	deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	//
	//	validation
	//

	if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) {

		DebugPrint( 4, ("HeaderBufferSize = %x\n", HeaderBufferSize) );
		return NDIS_STATUS_NOT_RECOGNIZED;
	}
	
	RtlCopyMemory( (PUCHAR)&protocol, &((PUCHAR)HeaderBuffer)[12], sizeof(USHORT) );

	//
	//	Discard 802.2 LLC SNAP field.
	//
	// if Ether Type less than 0x0600 ( 1536 )
	//

	if (NTOHS(protocol) < 0x0600  && 
	    protocol != HTONS(0x0060) && // LOOP: Ethernet Loopback
		protocol != HTONS(0x0200) && // PUP : Xerox PUP packet
		protocol != HTONS(0x0201)) { // PUPAP: Xerox PUP address trans packet 

#if __LPX__
		NdisCopyLookaheadData( (PUCHAR)&protocol,
								&((PUCHAR)LookAheadBuffer)[LENGTH_8022LLCSNAP - 2],
								sizeof(USHORT),
								deviceContext->MacOptions );
#endif
		PacketSize -= LENGTH_8022LLCSNAP;
		LookAheadBufferSize -= LENGTH_8022LLCSNAP;
		startOffset = LENGTH_8022LLCSNAP;
	}

	if (protocol != HTONS(ETH_P_LPX)) {
	
		DebugPrint( 4, ("Type = %x\n", protocol) );
		return NDIS_STATUS_NOT_RECOGNIZED;
	}


	//
	//	Check to see if the device context is initialized.
	//

	//ACQUIRE_DPC_SPIN_LOCK( &deviceContext->SpinLock );

	if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) {
	
		//RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );
		DebugPrint( 4,("Device is not initialized. Drop packet\n") );

		return NDIS_STATUS_NOT_RECOGNIZED;
	}

	ASSERT( deviceContext->NdisBindingHandle );

	//RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock );

	//
	// DROP PACKET for DEBUGGING!!!!
	//

#if 1 //DBG // Enabled for testing

	if (PacketRxDropRate) {

		PacketRxCountForDrop++;
				
		if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) {
			PLPX_HEADER        lpxHeader = (PLPX_HEADER)LookAheadBuffer;
#if 0
			if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) 
				DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", 
								 NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) );
#endif			
			DebugPrint( 1, ("D") );

			return NDIS_STATUS_NOT_RECOGNIZED;
		}
	}

#endif

	ASSERT( startOffset == 0 );

	DebugPrint( 4, ("LpxReceiveIndication, PacketSize = %d, LookAheadBufferSize = %d, LPX_HEADER size = %d\n",
					 PacketSize, LookAheadBufferSize, sizeof(LPX_HEADER)) );

	if (LookAheadBufferSize >= sizeof(LPX_HEADER)) {

		PNDIS_BUFFER	firstBuffer;    
		PUCHAR		    packetData;
		PLPX_HEADER		lpxHeader;
		USHORT			lpxHeaderSize;

		
		lpxHeader = (PLPX_HEADER)((PBYTE)LookAheadBuffer + startOffset);
		
		lpxHeaderSize = sizeof(LPX_HEADER);

#if __LPX_OPTION_ADDRESSS__

		if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {

			lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
		}

		if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) {

			lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
		}

#endif

		if (NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) == lpxHeaderSize) {

			status = RcvPacketAlloc( deviceContext,
									 0,
									 &packet );

			if (status == STATUS_SUCCESS) {

				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();
			
				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = 0;
				RESERVED(packet)->PacketRawDataOffset = 0;

				LpxTransferDataComplete( deviceContext,
					                     packet,
					                     NDIS_STATUS_SUCCESS,
					                     LookAheadBufferSize );

				return NDIS_STATUS_SUCCESS;
			}

		} else if (LookAheadBufferSize >= NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) {
				
			status = RcvPacketAlloc( deviceContext,
									 NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize,
									 &packet );

			if (status == STATUS_SUCCESS) {
			
				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();

				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize;
				RESERVED(packet)->PacketRawDataOffset = 0;

				NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL );
				packetData = MmGetMdlVirtualAddress( firstBuffer );

				NdisCopyLookaheadData( packetData,
									   (PBYTE)LookAheadBuffer + startOffset + lpxHeaderSize,
									   RESERVED(packet)->PacketRawDataLength,
									   deviceContext->MacOptions );

				LpxTransferDataComplete( deviceContext,
					                     packet,
					                     NDIS_STATUS_SUCCESS,
					                     LookAheadBufferSize );

				return NDIS_STATUS_SUCCESS;
			}

		} else {

			status = RcvPacketAlloc( deviceContext,
									 startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK),
									 &packet );
			
			if (status == STATUS_SUCCESS) {
			
				NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader,
										HeaderBuffer,
										ETHERNET_HEADER_LENGTH,
										deviceContext->MacOptions );

				RESERVED(packet)->EthernetHeader.Type = protocol;
				RESERVED(packet)->RecvTime = CurrentTime();

				RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize );
				RESERVED(packet)->HeaderCopied = TRUE;

				RESERVED(packet)->PacketRawDataLength = startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK);
				RESERVED(packet)->PacketRawDataOffset = startOffset + lpxHeaderSize;
			}
		}

	} else {

		PLPX_HEADER		lpxHeader;
		PNDIS_BUFFER	firstBuffer;	
		PUCHAR			packetData;
		UINT			packetDataLength;

		ASSERT( FALSE );

		status = RcvPacketAlloc( deviceContext, PacketSize, &packet );
		
		if (status == STATUS_SUCCESS) {
		
			RtlCopyMemory( &RESERVED(packet)->EthernetHeader,
						   HeaderBuffer,
						   ETHERNET_HEADER_LENGTH );

			RESERVED(packet)->EthernetHeader.Type = protocol;
			RESERVED(packet)->RecvTime = CurrentTime();

			RESERVED(packet)->PacketRawDataLength = PacketSize;
			RESERVED(packet)->PacketRawDataOffset = startOffset;

			NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL );
			NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority );

			lpxHeader = (PLPX_HEADER)(packetData + RESERVED(packet)->PacketRawDataOffset);
			RtlZeroMemory( lpxHeader, sizeof(LPX_HEADER) );

			RESERVED(packet)->HeaderCopied = FALSE;
		}
	}

	if (status != NDIS_STATUS_SUCCESS) {
	
		return NDIS_STATUS_NOT_RECOGNIZED;
	}

	ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
			
	if (deviceContext->NdisBindingHandle) {

		//ASSERT( FALSE );

		NdisTransferData( &status,
						  deviceContext->NdisBindingHandle,
						  MacReceiveContext,
						  0, //RESERVED(packet)->PacketRawDataOffset,
						  RESERVED(packet)->PacketRawDataLength,
						  packet,
						  &bytesTransfered );

			
		if (status == NDIS_STATUS_PENDING) {

			LPX_ASSERT( FALSE );
		    status = NDIS_STATUS_SUCCESS;
		
		} else if (status == NDIS_STATUS_SUCCESS) {
		
			LpxTransferDataComplete( deviceContext,
									 packet,
									 status,
									 bytesTransfered );

		} else {
	
			LPX_ASSERT( FALSE );
			DebugPrint( 1, ("NdisTransferData() failed. STATUS=%08lx\n", status) );
		}

	} else {
			
		status = NDIS_STATUS_NOT_RECOGNIZED;
		DebugPrint( 1, ("Invalid device status. STATUS=%08lx\n", status) );
	}

	return status;
}
Beispiel #7
0
NDIS_STATUS
NTAPI
NduReceive(NDIS_HANDLE ProtocolBindingContext,
           NDIS_HANDLE MacReceiveContext,
           PVOID HeaderBuffer,
           UINT HeaderBufferSize,
           PVOID LookAheadBuffer,
           UINT LookaheadBufferSize,
           UINT PacketSize)
{
    PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
    PNDISUIO_PACKET_ENTRY PacketEntry;
    PVOID PacketBuffer;
    PNDIS_PACKET Packet;
    NDIS_STATUS Status;
    UINT BytesTransferred;
    
    DPRINT("Received a %d byte packet\n", PacketSize);

    /* Discard if nobody is waiting for it */
    if (AdapterContext->OpenCount == 0)
        return NDIS_STATUS_NOT_ACCEPTED;
    
    /* Allocate a buffer to hold the packet data and header */
    PacketBuffer = ExAllocatePool(NonPagedPool, PacketSize + HeaderBufferSize);
    if (!PacketBuffer)
        return NDIS_STATUS_NOT_ACCEPTED;

    /* Allocate the packet descriptor and buffer */
    Packet = CreatePacketFromPoolBuffer(AdapterContext,
                                        (PUCHAR)PacketBuffer + HeaderBufferSize,
                                        PacketSize);
    if (!Packet)
    {
        ExFreePool(PacketBuffer);
        return NDIS_STATUS_NOT_ACCEPTED;
    }

    /* Transfer the packet data into our data buffer */
    if (LookaheadBufferSize == PacketSize)
    {
        NdisCopyLookaheadData((PVOID)((PUCHAR)PacketBuffer + HeaderBufferSize),
                              LookAheadBuffer,
                              PacketSize,
                              AdapterContext->MacOptions);
        BytesTransferred = PacketSize;
    }
    else
    {
        NdisTransferData(&Status,
                         AdapterContext->BindingHandle,
                         MacReceiveContext,
                         0,
                         PacketSize,
                         Packet,
                         &BytesTransferred);
        if (Status == NDIS_STATUS_PENDING)
        {
            KeWaitForSingleObject(&AdapterContext->AsyncEvent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = AdapterContext->AsyncStatus;
        }
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DPRINT1("Failed to transfer data with status 0x%x\n", Status);
            CleanupAndFreePacket(Packet, TRUE);
            return NDIS_STATUS_NOT_ACCEPTED;
        }
    }
    
    /* Copy the header data */
    RtlCopyMemory(PacketBuffer, HeaderBuffer, HeaderBufferSize);
    
    /* Free the packet descriptor and buffers 
       but not the pool because we still need it */
    CleanupAndFreePacket(Packet, FALSE);

    /* Allocate a packet entry from pool */
    PacketEntry = ExAllocatePool(NonPagedPool, sizeof(NDISUIO_PACKET_ENTRY) + BytesTransferred + HeaderBufferSize - 1);
    if (!PacketEntry)
    {
        ExFreePool(PacketBuffer);
        return NDIS_STATUS_RESOURCES;
    }

    /* Initialize the packet entry and copy in packet data */
    PacketEntry->PacketLength = BytesTransferred + HeaderBufferSize;
    RtlCopyMemory(PacketEntry->PacketData, PacketBuffer, PacketEntry->PacketLength);
    
    /* Free the old buffer */
    ExFreePool(PacketBuffer);

    /* Insert the packet on the adapter's packet list */
    ExInterlockedInsertTailList(&AdapterContext->PacketList,
                                &PacketEntry->ListEntry,
                                &AdapterContext->Spinlock);
    
    /* Signal the read event */
    KeSetEvent(&AdapterContext->PacketReadEvent,
               IO_NETWORK_INCREMENT,
               FALSE);

    return NDIS_STATUS_SUCCESS;
}
Beispiel #8
0
NDIS_STATUS
FakeNDISReceiveHandler (
	NDIS_HANDLE ProtocolBindingContext,
	NDIS_HANDLE MacReceiveContext,
	PUCHAR pHeaderBuffer,
	UINT HeaderBufferSize,
	PUCHAR pLookaheadBuffer,
	UINT LookaheadBufferSize,
	UINT PacketSize
	)
/*++

Routine Description:

	Filters network packets received.


Arguments:

	ProtocolBindingContext - ...

	MacReceiveContext - ...

	pHeaderBuffer - packet header

	HeaderBufferSize - packet header length

	pLookaheadBuffer - look ahead buffer after packet header

	LookaheadBufferSize - length of look ahead buffer

	PacketSize - length of packet, exclude packet header


Return Value:

	...


Author:

	xiaonie

	2012/07/12


--*/
{
	PLIST_ENTRY pEntry;
	PNDIS_HOOK_LIST_NODE pNode;
	KIRQL irql;
	ULONG ulFunAddr = 0;
	// PVOID MacHandle = NULL;
	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
	PNDIS_PACKET pNdisPacket = NULL;
	PNDIS_BUFFER pNdisBuffer = NULL;
	PUCHAR pBuffer = NULL;
	ULONG ulLen;
	KEVENT evt;

	KeAcquireSpinLock(&g_lock, &irql);
	for (pEntry = g_linkListHead.Flink; pEntry != &g_linkListHead; pEntry = pEntry->Flink) {
		pNode = CONTAINING_RECORD(pEntry, NDIS_HOOK_LIST_NODE, ListEntry);
		if (pNode->ProtocolBindingContext == ProtocolBindingContext) {
			ulFunAddr = pNode->ulRealReceiveHandler;
			// MacHandle = pNode->MacHandle;
			break;
		}
	}
	KeReleaseSpinLock(&g_lock, irql);

	if (ulFunAddr == 0) {
		DbgPrint("\r\n Attention: FunAddr == 0(0: FakeNDISReceiveHandler)\r\n");
		// return NDIS_STATUS_SUCCESS;
		return NDIS_STATUS_NOT_ACCEPTED;
	}


	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	if (PacketSize + HeaderBufferSize < PacketSize || PacketSize < LookaheadBufferSize) {	// PacketSize not valid
		DbgPrint("\r\n Attention: PacketSize not valid!(0: FakeNDISReceiveHandler)\r\n");
		return NDIS_STATUS_NOT_ACCEPTED;
	}

	// allocate buffer to hold network packet
	status = NdisAllocateMemoryWithTag(&pBuffer, HeaderBufferSize + PacketSize, '!nmN');
	if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL*/)
		return NDIS_STATUS_NOT_ACCEPTED;

	// copy packet header to buffer
	NdisMoveMemory(pBuffer, pHeaderBuffer, HeaderBufferSize);

	if (PacketSize == LookaheadBufferSize)		// Lookahead buffer contains a complete packet
	{
		//
		//	path 1 of 3, tested ok!
		//
		NdisMoveMemory(pBuffer + HeaderBufferSize, pLookaheadBuffer, PacketSize);

		// do the filtering work
		if (TRUE == RabbitHole(pBuffer, HeaderBufferSize + PacketSize)) {
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		NdisFreeMemory(pBuffer, 0, 0);

	}
	else										// Lookahead buffer contains an incomplete packet
	{
		//
		// get the full packet
		//
		// DbgPrint("Get Full Packet!\r\n");

		//if (MacHandle == NULL) {
		//	DbgPrint("MacHandle == NULL!(0: FakeNDISReceiveHandler)\r\n");
		//	NdisFreeMemory(pBuffer, 0, 0);
		//	return NDIS_STATUS_NOT_ACCEPTED;
		//}

		// make pBuffer a NDIS buffer to hold data
		NdisAllocateBuffer(&status, &pNdisBuffer, g_BufferPool, pBuffer + HeaderBufferSize, PacketSize);
		if (status != NDIS_STATUS_SUCCESS/* || pNdisBuffer == NULL*/) {
			DbgPrint("allocate pNdisBuffer(size = %d) failed in FakeNDISReceiveHandler!\r\n", PacketSize);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		// allocate a NIDS packet to chain buffer in.
		NdisAllocatePacket(&status, &pNdisPacket, g_PacketPool);
		if (status != NDIS_STATUS_SUCCESS/* || pNdisPacket == NULL*/) {
			DbgPrint("allocate pNdisPacket failed in FakeNDISReceiveHandler!\r\n");
			NdisFreeBuffer(pNdisBuffer);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		NDIS_SET_PACKET_STATUS(pNdisPacket, STATUS_SUCCESS);

		// Bring explosives.
		KeInitializeEvent(&evt, NotificationEvent, FALSE);
		*(PKEVENT *)(pNdisPacket->ProtocolReserved) = &evt;

		NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);

		// try to get complete packet
		NdisTransferData(&status, pNode->pOpenBlock, MacReceiveContext, 0, PacketSize, pNdisPacket, &ulLen);

		if (status == NDIS_STATUS_PENDING) {			// wait for the right time
			//
			// Path 2 of 3, not tested yet! Warning: An Error may occur!
			//
			DbgPrint("NdisTransferData is pending in FakeNDISReceiveHandler!\r\n", status);
			KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL);
		} else if (status != NDIS_STATUS_SUCCESS) {
			DbgPrint("NdisTransferData failed(status == 0x%08x) in FakeNDISReceiveHandler!\r\n", status);
			NdisFreePacket(pNdisPacket);
			NdisFreeBuffer(pNdisBuffer);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		//
		// Path 3 of 3, Filtering doesn't seem to work properly.
		//
		// do the filtering work
		if (TRUE == FilterPacket_ReceiveHandler(pBuffer, HeaderBufferSize, pNdisPacket)) {
			NdisFreePacket(pNdisPacket);
			NdisFreeBuffer(pNdisBuffer);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		NdisFreePacket(pNdisPacket);
		NdisFreeBuffer(pNdisBuffer);
		NdisFreeMemory(pBuffer, 0, 0);
	}

	// call the original NDIS routine.
	__asm {
		pushad;
		push	PacketSize;
		push	LookaheadBufferSize;
		push	pLookaheadBuffer;
		push	HeaderBufferSize;
		push	pHeaderBuffer;
		push	MacReceiveContext;
		push	ProtocolBindingContext;
		mov		eax, ulFunAddr;
		call	eax;
		mov		status, eax;
		popad;
	}

	return status;
}
Beispiel #9
0
NDIS_STATUS
NdisuioReceive(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN NDIS_HANDLE                  MacReceiveContext,
    IN PVOID                        pHeaderBuffer,
    IN UINT                         HeaderBufferSize,
    IN PVOID                        pLookaheadBuffer,
    IN UINT                         LookaheadBufferSize,
    IN UINT                         PacketSize
    )
/*++

Routine Description:

    Our protocol receive handler called by NDIS, typically if we have
    a miniport below that doesn't indicate packets.

    We make a local packet/buffer copy of this data, queue it up, and
    kick off the read service routine.

Arguments:

    ProtocolBindingContext - pointer to open context
    MacReceiveContext - for use in NdisTransferData
    pHeaderBuffer - pointer to data header
    HeaderBufferSize - size of the above
    pLookaheadBuffer - pointer to buffer containing lookahead data
    LookaheadBufferSize - size of the above
    PacketSize - size of the entire packet, minus header size.

Return Value:

    NDIS_STATUS_NOT_ACCEPTED - if this packet is uninteresting
    NDIS_STATUS_SUCCESS - if we processed this successfully

--*/
{
    PNDISUIO_OPEN_CONTEXT   pOpenContext;
    NDIS_STATUS             Status;
    PNDISUIO_ETH_HEADER     pEthHeader;
    PNDIS_PACKET            pRcvPacket;
    PUCHAR                  pRcvData;
    UINT                    BytesTransferred;
    PNDIS_BUFFER            pOriginalNdisBuffer, pPartialNdisBuffer;
    PIRP					pIrp;
    PLIST_ENTRY				pIrpEntry;
    ULONG					BytesRemaining; // at pDst
	PPACKET_GROUP			pGroup;

	//ULONG                   pDst;
	
    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);
    pRcvPacket = NULL;
    pRcvData = NULL;
    Status = NDIS_STATUS_SUCCESS;

    DEBUGP(DL_LOUD, ("Receive: Open %p, LookaheadBufferSize %d, PacketSize %d\n",
		pOpenContext, LookaheadBufferSize, PacketSize));
    
	NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->ReceivedPackets, 1);

	do
    {
        if (HeaderBufferSize != sizeof(NDISUIO_ETH_HEADER))
        {
            Status = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        pEthHeader = (PNDISUIO_ETH_HEADER)pHeaderBuffer;

		NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);

		//
		// Someone is reading, and this is the first packet.
		//
		if (!NUIO_IS_LIST_EMPTY(&pOpenContext->PendedReads) &&
			NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		{
			//
			//  Get the first pended Read IRP
			//
			pIrpEntry = pOpenContext->PendedReads.Flink;
			pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
			
			//
			// We don't have to worry about the situation where the IRP is cancelled
			// after we remove it from the queue and before we reset the cancel
			// routine because the cancel routine has been coded to cancel an IRP
			// only if it's in the queue.
			//
			IoSetCancelRoutine(pIrp, NULL);

			NUIO_REMOVE_ENTRY_LIST(pIrpEntry);
			
			pOpenContext->PendedReadCount--;

			NUIO_RELEASE_LOCK(&pOpenContext->Lock);

			NUIO_DEREF_OPEN(pOpenContext);  // Service: dequeue rcv packet

			//
			//  Copy as much data as possible from the receive packet to
			//  the IRP MDL.
			//
#ifndef WIN9X
			pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
			//NUIO_ASSERT(pDst != NULL);  // since it was already mapped
#else
			pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
			BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);
			
			BytesRemaining -= sizeof(PACKET_GROUP);

			//
			//  copy the ethernet header into the actual readbuffer
			//
			NdisMoveMappedMemory(pGroup->Data, pHeaderBuffer, HeaderBufferSize);
			
			if (PacketSize == LookaheadBufferSize)
			{
				BytesTransferred = MIN(LookaheadBufferSize, BytesRemaining);

				NdisCopyLookaheadData(pGroup->Data + HeaderBufferSize,
					pLookaheadBuffer,
					BytesTransferred,
					pOpenContext->MacOptions);

				pGroup->Length = BytesTransferred + HeaderBufferSize;
				
				pIrp->IoStatus.Information = pGroup->Length + sizeof(PACKET_GROUP);
				pIrp->IoStatus.Status = STATUS_SUCCESS;				
		
				DEBUGP(DL_LOUD, ("Receive: %d bytes\n", pIrp->IoStatus.Information));
		
				IoCompleteRequest(pIrp, IO_NO_INCREMENT);
			}
			else
			{
				BytesTransferred = 0;

				NdisAllocatePacket(
					&Status,
					&pRcvPacket,
					pOpenContext->RecvBufferPool
					);
				
				if (Status != NDIS_STATUS_SUCCESS)
					goto ERROR;
				
				//
				//  Allocate an MDL to map the portion of the buffer following the
				//  header
				//
				pPartialNdisBuffer = IoAllocateMdl(pGroup->Data, BytesRemaining, FALSE, FALSE, NULL);
				
				if (pPartialNdisBuffer == NULL)
				{
					NdisFreePacket(pRcvPacket);
					Status = NDIS_STATUS_RESOURCES;
					goto ERROR;
				}
				
				//
				//  Build the mdl to point to the the portion of the buffer following
				//  the header
				//
				IoBuildPartialMdl(
					pIrp->MdlAddress,
					pPartialNdisBuffer,
					pGroup->Data + HeaderBufferSize,
					0);
				
				//
				//  Clear the next link in the new MDL
				//
				
				pPartialNdisBuffer->Next = NULL;
				
				//
				//  Get a pointer to the packet itself.
				//
				
				NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = pIrp;
				NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pPartialNdisBuffer;
				
				//
				//  Attach our partial MDL to the packet
				//
				
				NdisChainBufferAtFront(pRcvPacket, pPartialNdisBuffer);
				
				//
				//  Call the Mac to transfer the packet
				//
				
				NdisTransferData(
					&Status,
					pOpenContext->BindingHandle,
					MacReceiveContext,
					0,  // ByteOffset
					PacketSize,
					pRcvPacket,
					&BytesTransferred);

ERROR:					
				//
				//  If it didn't pend, call the completeion routine now
				//
				if (Status != NDIS_STATUS_PENDING)
				{
					NdisuioTransferDataComplete(
						(NDIS_HANDLE)pOpenContext,
						pRcvPacket,
						Status,
						BytesTransferred);
				}
			}

			break;
		}

		NUIO_RELEASE_LOCK(&pOpenContext->Lock);

		//
        //  Allocate resources for queueing this up.
        //
        pRcvPacket = ndisuioAllocateReceivePacket(
			pOpenContext,
			PacketSize + HeaderBufferSize,
			&pRcvData
			);

        if (pRcvPacket == NULL)
        {
            Status = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        NdisMoveMappedMemory(pRcvData, pHeaderBuffer, HeaderBufferSize);

        //
        //  Check if the entire packet is within the lookahead.
        //
        if (PacketSize == LookaheadBufferSize)
        {
            NdisCopyLookaheadData(pRcvData + HeaderBufferSize,
                                  pLookaheadBuffer,
                                  LookaheadBufferSize,
                                  pOpenContext->MacOptions);
            //
            //  Queue this up for receive processing, and
            //  try to complete some read IRPs.
            //
            ndisuioQueueReceivePacket(pOpenContext, pRcvPacket);
        }
        else
        {
            //
            //  Allocate an NDIS buffer to map the receive area
            //  at an offset "HeaderBufferSize" from the current
            //  start. This is so that NdisTransferData can copy
            //  in at the right point in the destination buffer.
            //

            NdisAllocateBuffer(
                &Status,
                &pPartialNdisBuffer,
                pOpenContext->RecvBufferPool,
                pRcvData + HeaderBufferSize,
                PacketSize);
            
            if (Status == NDIS_STATUS_SUCCESS)
            {
                //
                //  Unlink and save away the original NDIS Buffer
                //  that maps the full receive buffer.
                //
                NdisUnchainBufferAtFront(pRcvPacket, &pOriginalNdisBuffer);
                NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pOriginalNdisBuffer;
				NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = NULL;

                //
                //  Link in the partial buffer for NdisTransferData to
                //  operate on.
                //
                NdisChainBufferAtBack(pRcvPacket, pPartialNdisBuffer);

                DEBUGP(DL_LOUD, ("Receive: setting up for TransferData:"
                        " Pkt %p, OriginalBuf %p, PartialBuf %p\n",
                        pRcvPacket, pOriginalNdisBuffer, pPartialNdisBuffer));

                NdisTransferData(
                    &Status,
                    pOpenContext->BindingHandle,
                    MacReceiveContext,
                    0,  // ByteOffset
                    PacketSize,
                    pRcvPacket,
                    &BytesTransferred);
            }
            else
            {
                //
                //  Failure handled below in TransferDataComplete.
                //
                BytesTransferred = 0;
            }
    
            if (Status != NDIS_STATUS_PENDING)
            {
                NdisuioTransferDataComplete(
                    (NDIS_HANDLE)pOpenContext,
                    pRcvPacket,
                    Status,
                    BytesTransferred);
            }
        }
    } while (FALSE);

	if (Status != NDIS_STATUS_SUCCESS && Status != NDIS_STATUS_PENDING)
		NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->DroppedPackets, 1);

    return Status;
}