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); }
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; }
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); }
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; }
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 }
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; }
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; }
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; }
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; }