Пример #1
0
////////////////////////////////////////////////////
// 读取封包中的数据
void FltReadPacketData(PNDIS_PACKET pPacket, 
					   PUCHAR lpBufferIn, ULONG nNumberToRead, PUINT lpNumberOfRead)
{	
	PUCHAR pBuf;
	ULONG nBufferSize;
	PNDIS_BUFFER pBufferDes = NULL;
	
	
	// 检查参数
	if(pPacket == NULL || lpBufferIn == NULL || nNumberToRead == 0)
	{
		if(lpNumberOfRead != NULL)
		{
			*lpNumberOfRead = 0;
			return ;
		}
	}

	// 设置返回数据
	*lpNumberOfRead = 0;
	
	
	// 遍历封包中的缓冲区描述表,将数据复制到用户缓冲区
	pBufferDes = pPacket->Private.Head;
	while(pBufferDes != pPacket->Private.Tail && pBufferDes != NULL)
	{
		// 获取此缓冲区描述表的缓冲区信息
		NdisQueryBufferSafe(pBufferDes, &pBuf, &nBufferSize, NormalPagePriority);
		if(pBuf == NULL)
			return;
		
		if(nNumberToRead > nBufferSize) // 复制整个缓冲区
		{
			NdisMoveMemory(lpBufferIn + *lpNumberOfRead, pBuf, nBufferSize);
			nNumberToRead -= nBufferSize;
			*lpNumberOfRead += nBufferSize;
		}
		else							// 仅复制剩下的部分
		{
			NdisMoveMemory(lpBufferIn + *lpNumberOfRead, pBuf, nNumberToRead);
			*lpNumberOfRead += nNumberToRead;
			return;
		}
		// 下一个缓冲区描述表
		pBufferDes = pBufferDes->Next;
	}
}
/*----------------------------------------------------------------------------*/
VOID kalCopyFrame(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, OUT PUINT_8 pucDestBuffer)
{
	PNDIS_PACKET prNdisPacket;
	PNDIS_BUFFER prNdisBuffer, prNextNdisBuffer;
	UINT u4PacketLen;
	UINT u4BytesToCopy;
	PVOID pvMbuf;
	UINT u4MbufLength;
	UINT u4BytesCopied;

	ASSERT(pvPacket);

	prNdisPacket = (PNDIS_PACKET) pvPacket;
	NdisQueryPacket(prNdisPacket, NULL, NULL, &prNdisBuffer, &u4PacketLen);

	u4BytesToCopy = u4PacketLen;
	u4BytesCopied = 0;

	while (u4BytesToCopy != 0) {

#ifdef NDIS51_MINIPORT
		NdisQueryBufferSafe(prNdisBuffer, &pvMbuf, &u4MbufLength, HighPagePriority);
#else
		NdisQueryBuffer(prNdisBuffer, &pvMbuf, &u4MbufLength);
#endif				/* NDIS51_MINIPORT */

		if (pvMbuf == (PVOID) NULL) {
			ASSERT(pvMbuf);
			break;
		}

		NdisMoveMemory((PVOID) pucDestBuffer, pvMbuf, u4MbufLength);

		u4BytesToCopy -= u4MbufLength;
		u4BytesCopied += u4MbufLength;
		pucDestBuffer += u4MbufLength;

		NdisGetNextBuffer(prNdisBuffer, &prNextNdisBuffer);
		prNdisBuffer = prNextNdisBuffer;
	}

	ASSERT(u4BytesCopied == u4PacketLen);

	return;
}
Пример #3
0
int
filter_packet(int direction, int iface, PNDIS_PACKET packet)
{
	PNDIS_BUFFER buffer;
	UINT packet_len, buffer_len, hdr_len;
	int result;
	void *pointer;
	struct ether_hdr *ether_hdr;
	struct ip_hdr *ip_hdr;

	//lint -e506 -e613 -e774 -e831 -e550 
	NdisQueryPacket(packet, NULL, NULL, &buffer, &packet_len);

	if (packet_len < sizeof(struct ether_hdr)) {
		DBGOUT(("filter_packet: too small packet for ether_hdr! (%u)\n", packet_len));
		return FILTER_UNKNOWN;
	}

	/* process ether_hdr */

	NdisQueryBufferSafe(buffer, &ether_hdr, &buffer_len, LowPagePriority);

	if (buffer_len < sizeof(struct ether_hdr)) {
		DBGOUT(("filter_packet: too small buffer for ether_hdr! (%u)\n", buffer_len));
		return FILTER_UNKNOWN;
	}
	
	// go to the next header
	if (buffer_len > sizeof(struct ether_hdr)) {

		pointer = (char *)ether_hdr + sizeof(struct ether_hdr);

		buffer_len -= sizeof(struct ether_hdr);

	} else {
		// use next buffer in chain
		NdisGetNextBuffer(buffer, &buffer);
		NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority);
	}

	if (ether_hdr->ether_type == ETHERNET_TYPE_IP) {
		/* process ip_hdr */

		if (buffer_len < sizeof(struct ip_hdr)) {
			DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u)\n",	buffer_len));
			return FILTER_UNKNOWN;
		}

		ip_hdr = (struct ip_hdr *)pointer;
		hdr_len = ip_hdr->ip_hl * 4;

		if (buffer_len < hdr_len) {
			DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u vs. %u)\n", buffer_len, hdr_len));
			return FILTER_UNKNOWN;
		}

		// go to the next header
		if (buffer_len > hdr_len) {

			pointer = (char *)ip_hdr + hdr_len;
					
			buffer_len -= hdr_len;
			
		} else {
			// use next buffer in chain
			NdisGetNextBuffer(buffer, &buffer);
			NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority);
		}

		result = process_transp(direction, iface, ip_hdr->ip_p, ip_hdr, pointer, buffer_len);
		if (result != FILTER_ALLOW)
			return result;
	}

	// default behavior
	return FILTER_ALLOW;
}
Пример #4
0
VOID
LpxTransferDataComplete(
	IN NDIS_HANDLE   ProtocolBindingContext,
	IN PNDIS_PACKET  Packet,
	IN NDIS_STATUS   Status,
	IN UINT          BytesTransfered
	)
{
	PDEVICE_CONTEXT	pDeviceContext;
	PLPX_HEADER	lpxHeader;
	PNDIS_BUFFER	firstBuffer;	
	PUCHAR			packetData;
	UINT			packetDataLength;
	USHORT			lpxHeaderSize;


	UNREFERENCED_PARAMETER( BytesTransfered );

	pDeviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	if (Status != NDIS_STATUS_SUCCESS) {

		ASSERT( FALSE );
		DebugPrint( 1,  ("[LPX] LpxTransferDataComplete error %x\n", Status) );
		PacketFree( pDeviceContext, Packet );
		return;
	}

	if (RESERVED(Packet)->HeaderCopied == FALSE) {
	
		NdisQueryPacket( Packet, NULL, NULL, &firstBuffer, NULL );
		NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority );

		lpxHeader = (PLPX_HEADER)(packetData + RESERVED(Packet)->PacketRawDataOffset);

		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

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

		RESERVED(Packet)->PacketRawDataLength = RESERVED(Packet)->PacketRawDataOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK);
		RESERVED(Packet)->PacketRawDataOffset += lpxHeaderSize;
	}
	
	lpxHeaderSize = sizeof(LPX_HEADER);

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_SOURCE_ADDRESS)) {

		if (!FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) {
		
			RtlCopyMemory( RESERVED(Packet)->OptionSourceAddress,
						   RESERVED(Packet)->OptionDestinationAddress,
						   ETHERNET_ADDRESS_LENGTH );	
		}

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;

		ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.SourceAddress,
							   RESERVED(Packet)->OptionSourceAddress,
							   ETHERNET_ADDRESS_LENGTH) );
	}

	if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;

		ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.DestinationAddress,
							   RESERVED(Packet)->OptionDestinationAddress,
							   ETHERNET_ADDRESS_LENGTH) );
	}

#endif

	if (NTOHS(RESERVED(Packet)->LpxHeader.PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize != 
		RESERVED(Packet)->PacketRawDataLength - RESERVED(Packet)->PacketRawDataOffset) {

		ASSERT( FALSE );
		PacketFree( pDeviceContext, Packet );
		return;
	}		

	ExInterlockedInsertTailList( &pDeviceContext->PacketInProgressList,
								 &(RESERVED(Packet)->ListEntry),
								 &pDeviceContext->PacketInProgressQSpinLock );
	return;
}
Пример #5
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;
}
Пример #6
0
VOID
PacketFree2 (
	IN PNDIS_PACKET		Packet
	)
{
	PLPX_RESERVED	reserved = RESERVED(Packet);
	PUCHAR			packetData;
	PNDIS_BUFFER	pNdisBuffer;
	UINT			uiLength;
	LONG			clone;
	LONG			BufferSeq;
	BOOLEAN			allocMiniport = FALSE;
	PLPX_RESERVED	externalReserved;


	DebugPrint( 3, ("PacketFree reserved->type = %d\n", reserved->Type) );
	ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );

	
	switch (reserved->Type) {

	case LPX_PACKET_TYPE_SEND:

		clone = InterlockedDecrement( &reserved->Cloned );
		
		if(clone >= 0) {
		
			return;
		}
	
		pNdisBuffer = NULL;
		BufferSeq = 0;
		NdisUnchainBufferAtFront( Packet, &pNdisBuffer );

		while (pNdisBuffer) {

			//
			//	Assuming the first data buffer comes from user application
			//			the others are created in LPX for padding, etc.
			//	Free the memory of the others.
			//
			
			if (BufferSeq == 0) {

#if DBG
				NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority );
				ASSERT( packetData == (PCHAR)&RESERVED(Packet)->EthernetHeader );
#endif

			} else if (BufferSeq == 1) {

				// UserBuffer

			} else if (BufferSeq == 2) {

				// Padding
					
				NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority );
				LpxFreeMemoryWithLpxTag( packetData );
			
			} else {

				ASSERT( FALSE );
			}

			NdisFreeBuffer( pNdisBuffer );

			pNdisBuffer = NULL;
			NdisUnchainBufferAtFront( Packet, &pNdisBuffer );
			BufferSeq ++;
		}
		
		if (reserved->IrpSp != NULL) {
			
			PIRP _Irp = IRP_SEND_IRP( reserved->IrpSp );

			ASSERT( reserved->NdisStatus == NDIS_STATUS_SUCCESS || reserved->NdisStatus == NDIS_STATUS_NOT_ACCEPTED || !NT_SUCCESS(reserved->NdisStatus) );

			if (!NT_SUCCESS(reserved->NdisStatus)) {

				_Irp->IoStatus.Status = reserved->NdisStatus;
			}

			//INC_IRP_RETRANSMITS( _Irp, reserved->Retransmits );

			LpxDereferenceSendIrp( "Destroy packet", reserved->IrpSp, RREF_PACKET );
		
		} else {
		
			DebugPrint( 3, ("[LPX] PacketFree: No IrpSp\n") ) ;
		}

		break;

	case LPX_PACKET_TYPE_RECEIVE:

		//
		// If the packet allocated by NIC miniport, break here.
		//
		if(RESERVED(Packet)->RecvFlags & LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT) {
			allocMiniport = TRUE;
			break;
		}

		pNdisBuffer = NULL;	

		NdisUnchainBufferAtFront( Packet, &pNdisBuffer );

#if __LPX_STATISTICS__
		{
			LARGE_INTEGER systemTime;

			KeQuerySystemTime( &systemTime );

			RESERVED(Packet)->DeviceContext->NumberOfRecvPackets ++;
			RESERVED(Packet)->DeviceContext->FreeTimeOfRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart;
			RESERVED(Packet)->DeviceContext->BytesOfRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength;

			if (RESERVED(Packet)->PacketRawDataLength) {

				RESERVED(Packet)->DeviceContext->NumberOfLargeRecvPackets ++;
				RESERVED(Packet)->DeviceContext->FreeTimeOfLargeRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart;
				RESERVED(Packet)->DeviceContext->BytesOfLargeRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength;
			
			} else {

				RESERVED(Packet)->DeviceContext->NumberOfSmallRecvPackets ++;
				RESERVED(Packet)->DeviceContext->FreeTimeOfSmallRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart;
				RESERVED(Packet)->DeviceContext->BytesOfSmallRecvPackets.QuadPart += sizeof(LPX_HEADER);
			}
		}
#endif

		if (pNdisBuffer) {

			NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority );
			
			LpxFreeMemoryWithLpxTag( packetData );
			NdisFreeBuffer( pNdisBuffer );
		}

		break;
	default:
		ASSERT(FALSE);
		return;
	}

	//
	// Free external protocol reserved context.
	//

	externalReserved = ((PLPX_RESERVED)(Packet->ProtocolReserved))->ExternalReserved;
	if(externalReserved) {
		NdisFreeMemory(externalReserved, sizeof(LPX_RESERVED), 0);
	}

	ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS );
	if(allocMiniport) {
		//
		// Return the packet allocated by NIC miniport
		//
		NdisReturnPackets(&Packet, 1);
	} else {

		NdisFreePacket( Packet );

		InterlockedDecrement( &NumberOfAllockPackets );
		DebugPrint( 3, ("Packet REALLY Freed NumberOfAllockPackets = %d\n", NumberOfAllockPackets) );

	}

}
Пример #7
0
VOID
ReadPacket (
	PNDIS_PACKET pPacket,
	PUCHAR pBuffer,
	ULONG ulBufSize
	)
/*++

Routine Description:

	Retrieves the buffer from a buffer descriptor.


Arguments:

	Packet - Pointer to the buffer descriptor.

	pBuffer - Pointer to the buffer.

	ulBufSize - Size of the buffer.

Return Value:

	None.


Author:

	xiaonie

	2012/07/12


--*/
{
	PVOID			pVA;
	PNDIS_BUFFER	pFirstBuffer, pNextBuffer;
	ULONG			ulTotalLength;
	ULONG			ulLen;
	PVOID			pBuf = NULL;
	ULONG			ulCount = 0;

	NdisQueryPacket(pPacket, NULL, NULL, &pFirstBuffer, NULL);
	while (pFirstBuffer != NULL)
	{
		NdisQueryBufferSafe(pFirstBuffer, &pVA, &ulLen, NormalPagePriority);

		if(!pVA)
		{
			// memory not enough
			DbgPrint("pVA == NULL, insufficient memory!\r\n");
			break;
		}
		if (ulCount + ulLen > ulBufSize) {
			DbgPrint("ulCount + ulLen(%d) > ulBufSize(%d)\r\n", ulCount + ulLen, ulBufSize);
			break;
		}

		NdisMoveMemory(pBuffer + ulCount, pVA, ulLen);
		ulCount += ulLen;
		NdisGetNextBuffer(pFirstBuffer,  &pNextBuffer);
		pFirstBuffer = pNextBuffer;
	}

	DbgPrint("ReadPacket: ulBufSize == %d, ulCount == %d\n", ulBufSize, ulCount);

	return;
}
Пример #8
0
NTSTATUS
NdisuioDoFastRead(
    IN PNDISUIO_OPEN_CONTEXT        pOpenContext,
	IN PIRP							pIrp
    )
/*++

Routine Description:

    Utility routine to copy received data into user buffers and
    complete READ IRPs.

Arguments:

    pOpenContext - pointer to open context

Return Value:

    None

--*/
{
    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
	PPACKET_GROUP		pGroup;
	CCHAR				PriorityBoost = IO_NETWORK_INCREMENT;

    DEBUGP(DL_VERY_LOUD, ("FastRead: open %p/%x\n", pOpenContext, pOpenContext->Flags));

	if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		return STATUS_UNSUCCESSFUL;

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

	//
	//  Get the first queued receive packet
	//
	pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
	pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

	do
	{
        NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry);

        pOpenContext->RecvPktCount--;

        NUIO_RELEASE_LOCK(&pOpenContext->Lock);

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

        pNdisBuffer = pRcvPacket->Private.Head;

		pDst = pGroup->Data;

		BytesRemaining -= sizeof(PACKET_GROUP);
		
        while (BytesRemaining && (pNdisBuffer != NULL))
        {
#ifndef WIN9X
            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DEBUGP(DL_FATAL, ("FastRead: Open %p, QueryBuffer failed for buffer %p\n",
                            pOpenContext, pNdisBuffer));

				break;
            }
#else
            NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable);
#endif

            if (BytesAvailable)
            {
                ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining);

                NUIO_COPY_MEM(pDst, pSrc, BytesToCopy);
                BytesRemaining -= BytesToCopy;
                pDst += BytesToCopy;
            }

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

		ndisuioFreeReceivePacket(pOpenContext, pRcvPacket);

		pGroup->Length = pDst - pGroup->Data;
		pGroup = (PPACKET_GROUP)pDst;
		
		NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
		
		if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		{
			PriorityBoost = IO_NO_INCREMENT;
			break;
		}

		pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
		pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

		NdisQueryPacketLength(pRcvPacket, &BytesAvailable);
		if (BytesRemaining < BytesAvailable + sizeof(PACKET_GROUP))
			break;
	} while (TRUE);
	
	NUIO_RELEASE_LOCK(&pOpenContext->Lock);

	//
	//  Complete the IRP.
	//
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;
	
	DEBUGP(DL_INFO, ("FastRead: Open %p, IRP %p completed with %d bytes\n",
		pOpenContext, pIrp, pIrp->IoStatus.Information));
	
	IoCompleteRequest(pIrp, PriorityBoost);
	
	return STATUS_SUCCESS;
}
Пример #9
0
/*
 * Convert the ndis packet chain into an lbuf .
 */
struct lbuf*
shared_txlb_convert(shared_info_t *sh, ND_PKT *p)
{
#ifndef NDIS60
	struct lbuf *lb;
	PNDIS_BUFFER b, next;
	uchar *bdata, *buf;
	uint blen, tot;
	struct lbfree *txlbfree;

	ASSERT(p);

	NdisQueryPacket(p, NULL, NULL, &b, &tot);

	ASSERT(b);
	ASSERT(tot <= LBDATASZ);

	if ((b == NULL) || (tot > LBDATASZ))
		return (NULL);

	txlbfree = &sh->txfree;
	/* txqueue free buffer count shouldn't go below threshold */
	if (txlbfree->count <= TXLB_FREEPOOL_THREHOLD(txlbfree->total))
		return (NULL);

	/* alloc lbuf */
	if ((lb = shared_lb_get(sh, txlbfree)) == NULL)
		return (NULL);

	/* Adjust for the head room requested */
	ASSERT(txlbfree->size > txlbfree->headroom);
	lb->data += txlbfree->headroom;

	/*
	 * In case of dongle, make sure the begining of the buffer is
	 * aligned at 32 bytes for DMA efficiency, after inserting
	 * header of 16 bytes later in DHD layer
	 */
	if (((uintptr)lb->data % 32) <= 16)
		lb->data += 16 - (uintptr)lb->data % 32;
	else
		lb->data -= (uintptr)lb->data % 32 - 16;

	buf = lb->data;

	while (b && tot) {
#if defined(NDIS51)
		NdisQueryBufferSafe(b, &bdata, &blen, NormalPagePriority);
#else
		NdisQueryBuffer(b, &bdata, &blen);
#endif /* defined (NDIS51) */

		blen = MIN(blen, tot);

		if (blen) {
			bcopy(bdata, buf, blen);
			lb->tail += blen;
			lb->len += blen;
			buf += blen;
			tot -= blen;
		}

		NdisGetNextBuffer(b, &next);
		b = next;
	}
	/* save a pointer to the ndis packet for later sendcomplete */
	lb->p = p;
	return (lb);

#else /* !NDIS60 */

	struct lbuf *lb;
	PNET_BUFFER nb;
	PMDL b, next;
	uint offset;
	uchar *bdata, *buf;
	uint blen, tot;
	struct lbfree *txlbfree;

	ASSERT(p);

	tot = 0;
	for (nb = NET_BUFFER_LIST_FIRST_NB(p); nb; nb = NET_BUFFER_NEXT_NB(nb))
		tot += NET_BUFFER_DATA_LENGTH(nb);

	nb = NET_BUFFER_LIST_FIRST_NB(p);
	if (nb == NULL)
		return (NULL);
	b = NET_BUFFER_CURRENT_MDL(nb);
	offset = NET_BUFFER_CURRENT_MDL_OFFSET(nb);

	ASSERT(b);
	ASSERT(tot <= LBDATASZ);

	if ((b == NULL) || (tot > LBDATASZ))
		return (NULL);

	txlbfree = &sh->txfree;
	/* txqueue free buffer count shouldn't go below threshold */
	if (txlbfree->count <= TXLB_FREEPOOL_THREHOLD(txlbfree->total))
		return (NULL);

	/* alloc lbuf */
	if ((lb = shared_lb_get(sh, txlbfree)) == NULL)
		return (NULL);

#if defined(NDIS60)
	/* Adjust for the head room requested */
	/* ASSERT(txlbfree->size > txlbfree->headroom); */
	lb->data += txlbfree->headroom;

	/*
	 * In case of dongle, make sure the begining of the buffer is
	 * aligned at 32 bytes for DMA efficiency, after inserting
	 * header of 16 bytes later in DHD layer
	 */
	if (((uintptr)lb->data % 32) <= 16)
		lb->data += 16 - (uintptr)lb->data % 32;
	else
		lb->data -= (uintptr)lb->data % 32 - 16;
#endif /* UNDER_CE && NDIS60 */

	buf = lb->data;

	while (b && tot) {
		NdisQueryMdl(b, &bdata, &blen, NormalPagePriority);

		if (bdata == NULL)
			goto next_mdl;

		if (blen > offset) {
			bdata += offset;
			blen -= offset;
		} else {
			offset -= blen;
			goto next_mdl;
		}

		blen = MIN(blen, tot);

		if (blen) {
			bcopy(bdata, buf, blen);
			lb->tail += blen;
			lb->len += blen;
			buf += blen;
			tot -= blen;
			offset = 0;
		}

	next_mdl:
		NdisGetNextMdl(b, &next);
		if (!next) {
			nb = NET_BUFFER_NEXT_NB(nb);
			if (nb) {
				next = NET_BUFFER_CURRENT_MDL(nb);
				offset = NET_BUFFER_CURRENT_MDL_OFFSET(nb);
			}
		}
		b = next;
	}

	/* save a pointer to the ndis packet for later sendcomplete */
	lb->p = p;

	return (lb);
#endif /* !NDIS60 */
}
Пример #10
0
VOID
ndisprotServiceReads(
    IN PNDISPROT_OPEN_CONTEXT        pOpenContext
    )
/*++

Routine Description:

    Utility routine to copy received data into user buffers and
    complete READ IRPs.

Arguments:

    pOpenContext - pointer to open context

Return Value:

    None

--*/
{
    PIRP                pIrp = NULL;
    PLIST_ENTRY         pIrpEntry;
    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
    BOOLEAN             FoundPendingIrp;

    DEBUGP(DL_VERY_LOUD, ("ServiceReads: open %p/%x\n",
            pOpenContext, pOpenContext->Flags));

    NPROT_REF_OPEN(pOpenContext);  // temp ref - service reads

    NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

    while (!NPROT_IS_LIST_EMPTY(&pOpenContext->PendedReads) &&
           !NPROT_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
    {
        FoundPendingIrp = FALSE;
        //
        //  Get the first pended Read IRP
        //
        pIrpEntry = pOpenContext->PendedReads.Flink;
        while (pIrpEntry != &pOpenContext->PendedReads)
        {
            pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);

            //
            //  Check to see if it is being cancelled.
            //
            if (IoSetCancelRoutine(pIrp, NULL))
            {
                //
                //  It isn't being cancelled, and can't be cancelled henceforth.
                //
                NPROT_REMOVE_ENTRY_LIST(pIrpEntry);
                FoundPendingIrp = TRUE;
                break;

                //
                //  NOTE: we decrement PendedReadCount way below in the
                //  while loop, to avoid letting through a thread trying
                //  to unbind.
                //
            }
            else
            {
                //
                //  The IRP is being cancelled; let the cancel routine handle it.
                //
                DEBUGP(DL_INFO, ("ServiceReads: open %p, skipping cancelled IRP %p\n",
                        pOpenContext, pIrp));
                pIrpEntry = pIrpEntry->Flink;

            }
        }
        //
        // If no pending IRP
        //
        if (FoundPendingIrp == FALSE)
        {
            break;
        }
        //
        //  Get the first queued receive packet
        //
        pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
        NPROT_REMOVE_ENTRY_LIST(pRcvPacketEntry);

        pOpenContext->RecvPktCount --;

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

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

        pRcvPacket = NPROT_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

        //
        //  Copy as much data as possible from the receive packet to
        //  the IRP MDL.
        //
        pDst = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
        __analysis_assume(pDst);
        NPROT_ASSERT(pDst != NULL);  // since it was already mapped
        BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);

        pNdisBuffer = NDIS_PACKET_FIRST_NDIS_BUFFER(pRcvPacket);

        //
        // Copy the data in the received packet into the buffer provided by the client.
        // If the length of the receive packet is greater than length of the given buffer, 
        // we just copy as many bytes as we can. Once the buffer is full, we just discard 
        // the rest of the data, and complete the IRP sucessfully even we only did a partial copy.
        // 
        while (BytesRemaining && (pNdisBuffer != NULL))
        {
#ifndef WIN9X
            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DEBUGP(DL_FATAL,
                    ("ServiceReads: Open %p, QueryBuffer failed for buffer %p\n",
                            pOpenContext, pNdisBuffer));
                break;
            }
#else
            NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable);
#endif

            if (BytesAvailable)
            {
                ULONG       BytesToCopy = MIN(BytesAvailable, BytesRemaining);

                NPROT_COPY_MEM(pDst, pSrc, BytesToCopy);
                BytesRemaining -= BytesToCopy;
                pDst += BytesToCopy;
            }

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

        //
        //  Complete the IRP.
        //
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;

        DEBUGP(DL_INFO, ("ServiceReads: Open %p, IRP %p completed with %d bytes\n",
            pOpenContext, pIrp, pIrp->IoStatus.Information));

        IoCompleteRequest(pIrp, IO_NO_INCREMENT);

        //
        //  Free up the receive packet - back to the miniport if it
        //  belongs to it, else reclaim it (local copy).
        //
        if (NdisGetPoolFromPacket(pRcvPacket) != pOpenContext->RecvPacketPool)
        {
            NdisReturnPackets(&pRcvPacket, 1);
        }
        else
        {
            ndisprotFreeReceivePacket(pOpenContext, pRcvPacket);
        }

        NPROT_DEREF_OPEN(pOpenContext);    // took out pended Read

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
        pOpenContext->PendedReadCount--;

    }

    NPROT_RELEASE_LOCK(&pOpenContext->Lock);

    NPROT_DEREF_OPEN(pOpenContext);    // temp ref - service reads
}
Пример #11
0
BOOLEAN  
cdc_ncm_fill_tx_frame(PMP_ADAPTER Adapter,PNDIS_PACKET Packet,PTCB ptcb, NCMDWORD sign)
{
	PMP_USBPIPE  usbpipe = Adapter->UsbPipeForNIC;
	PUSB_CDC_NCM_NTH16  nth16;
	PUSB_CDC_NCM_NDP16 ndp16;
	USHORT n = 0, index, ndplen;
	UINT           PacketLength;  
	PNDIS_BUFFER   CurrentBuffer = NULL;
	PVOID          VirtualAddress = NULL;
	UINT           CurrentLength;
	BOOLEAN        bResult = TRUE;
	int            maxpacketsize;
	int max_datagrams;
	maxpacketsize=usbpipe->InterfaceData->Pipes[usbpipe->BulkPipeOutput].MaximumPacketSize;

	if (Packet == NULL) {
		return TRUE;
	}

	 max_datagrams=usbpipe->tx_max_datagrams;

	if (0==ptcb->ulSize) {

		/* fill out the initial 16-bit NTB header */
		nth16 = (PUSB_CDC_NCM_NTH16 )memset(tcb_put(ptcb, sizeof(USB_CDC_NCM_NTH16)), 0, sizeof(USB_CDC_NCM_NTH16));
		nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
		nth16->wHeaderLength = cpu_to_le16(sizeof(USB_CDC_NCM_NTH16));
		nth16->wSequence = cpu_to_le16(usbpipe->tx_seq++);

		/* count total number of frames in this NTB */
		ptcb->NumofOrgSendPacket= 0;
	}

	NdisQueryPacket(Packet,
		NULL,
		NULL,
		&CurrentBuffer,
		&PacketLength);

    n = ptcb->NumofOrgSendPacket;

	if(n>=max_datagrams)
	{
		ptcb->bRead2Send=1;
	}
	while(n<max_datagrams) {

		/* get the appropriate NDP for this skb */
		ndp16 = cdc_ncm_ndp(Adapter, ptcb, sign, PacketLength + usbpipe->tx_modulus + usbpipe->tx_remainder);

		/* align beginning of next frame */
		cdc_ncm_align_tail(ptcb,  usbpipe->tx_modulus, usbpipe->tx_remainder, usbpipe->tx_max);

		/* check if we had enough room left for both NDP and frame */
		if (NULL==ndp16 || ptcb->ulSize + PacketLength > usbpipe->tx_max) {
			if (n == 0) {
				ptcb->bRead2Send=0;
			} else {
				ptcb->bRead2Send = 1;
			}
			bResult=FALSE;
			break;
		}

		/* calculate frame number withing this NDP */
		ndplen = le16_to_cpu(ndp16->wLength);
		index = (ndplen - sizeof(USB_CDC_NCM_NDP16)) / sizeof(USB_CDC_NCM_DPE16);

		/* OK, add this Packet */
		ndp16->dpe16[index].wDatagramLength = cpu_to_le16((USHORT)PacketLength);
		ndp16->dpe16[index].wDatagramIndex = cpu_to_le16((USHORT)ptcb->ulSize);
		ndp16->wLength = cpu_to_le16(ndplen + sizeof(USB_CDC_NCM_DPE16));

		while(CurrentBuffer)
		{
			NdisQueryBufferSafe(
				CurrentBuffer,
				&VirtualAddress,
				&CurrentLength,
				NormalPagePriority);

			ASSERT(NULL!=VirtualAddress);

			CurrentLength = min(CurrentLength, PacketLength);         

			if(CurrentLength)
			{
				// Copy the data.
				NdisMoveMemory(tcb_put(ptcb, CurrentLength), VirtualAddress, CurrentLength);
				PacketLength -= CurrentLength;            
			}
			NdisGetNextBuffer(
				CurrentBuffer,
				&CurrentBuffer);
		}
		if(PacketLength){
			NdisZeroMemory(tcb_put(ptcb, PacketLength), PacketLength);
		    PacketLength=0;
		}


		InsertTailList(
			&ptcb->ListOrgSendPacket, 
			(PLIST_ENTRY)&Packet->MiniportReserved[0]);

		ptcb->NumofOrgSendPacket++;

		/* send now if this NDP is full */
		if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
			ptcb->bRead2Send = 1;
			break;
		}
		break;
	}

	/* If collected data size is less or equal CDC_NCM_MIN_TX_PKT
	* bytes, we send buffers as it is. If we get more data, it
	* would be more efficient for USB HS mobile device with DMA
	* engine to receive a full size NTB, than canceling DMA
	* transfer and receiving a short packet.
	*
	* This optimization support is pointless if we end up sending
	* a ZLP after full sized NTBs.
	*/
	if (ptcb->bRead2Send==1&&(ptcb->ulSize%maxpacketsize== 0))
		memset(tcb_put(ptcb, 1), 0, 1);/* force short packet */

	/* set final frame length */
	nth16 = (PUSB_CDC_NCM_NTH16 )ptcb->pData;
	nth16->wBlockLength = cpu_to_le16((USHORT)ptcb->ulSize);

	return bResult;
}
Пример #12
0
VOID
PacketFree(
    IN PNDIS_PACKET	Packet
)
{
    PLPX_RESERVED	reserved = RESERVED(Packet);
    PUCHAR			packetData;
    PNDIS_BUFFER	pNdisBuffer;
    UINT			uiLength;
    LONG			clone ;

    DebugPrint(3, ("PacketFree reserved->type = %d\n", reserved->Type));

    switch(reserved->Type) {

    case SEND_TYPE:

        clone = InterlockedDecrement(&reserved->Cloned);
        if(clone >= 0) {
            return;
        }

        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        if(pNdisBuffer) {

            NdisQueryBufferSafe(
                pNdisBuffer,
                &packetData,
                &uiLength,
                HighPagePriority
            );

            NdisFreeMemory(packetData);
            NdisFreeBuffer(pNdisBuffer);
        }
        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        while(pNdisBuffer) {
            NdisFreeBuffer(pNdisBuffer);
            pNdisBuffer = NULL;
            NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        }
        if(reserved->IrpSp != NULL) {
            LpxDereferenceSendIrp(reserved->IrpSp);
        } else {
            DebugPrint(2, ("[LPX] PacketFree: No IrpSp\n")) ;
        }
        break;

    case RECEIVE_TYPE:

        if(reserved->LpxSmpHeader)
            //ExFreePool(reserved->LpxSmpHeader);
            NdisFreeMemory(reserved->LpxSmpHeader);

        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        if(pNdisBuffer) {
            NdisQueryBufferSafe(
                pNdisBuffer,
                &packetData,
                &uiLength,
                HighPagePriority
            );

            NdisFreeMemory(packetData);
            NdisFreeBuffer(pNdisBuffer);
        }
        reserved->PacketDataOffset = 0;

        break;

    }

    NdisFreePacket(Packet);

    InterlockedDecrement(&NumberOfPackets);

    DebugPrint(2, ("Packet REALLY Freed Numberofpackets = %d\n", NumberOfPackets));
}
Пример #13
0
struct Send_Packet_Data*
Packet2PacketData(PNDIS_PACKET Packet) {

	UINT buffer_count;
	PNDIS_BUFFER buffer;
	UINT packet_len;
	UINT offset;
	PVOID addr;
	UINT len;
	struct Send_Packet_Data* packet_data;
	packet_data = NULL;
	
	NdisQueryPacket(Packet,
		NULL,
		&buffer_count,
		&buffer,
		&packet_len);
	if (!buffer_count ||
		!buffer)
		goto error_exit;

	if (buffer_count > 1) {
		packet_data = PreparePacketData(buffer_count,
			packet_len);
		if (!packet_data)
			goto error_exit;
		
		offset = 0;
		while(1) {
			NdisQueryBufferSafe(buffer,
				&addr,
				&len,
				NormalPagePriority);
			if (!addr ||
				!len)
				goto error_exit;
		
			RtlCopyMemory(packet_data->m_data+offset, 
				addr, 
				len);
			offset += len;
		
			NdisGetNextBuffer(buffer, 
				&buffer);
			if (!buffer)
				break;
		}
		packet_data->m_ndis_packet = Packet;
		packet_data->m_len = packet_len;
	}
	else {
		packet_data = PreparePacketData(buffer_count,
			0);
		if (!packet_data)
			goto error_exit;

		NdisQueryBufferSafe(buffer,
			&addr,
			&len,
			NormalPagePriority);
		if (!addr ||
			!len)
			goto error_exit;
		
		packet_data->m_ndis_packet = Packet;
		packet_data->m_len = packet_len;		
		packet_data->m_data = addr;
	}

	packet_data->m_mdl = IoAllocateMdl(packet_data->m_data,
		packet_data->m_len,
		FALSE,
		FALSE,
		NULL);
	if (!packet_data->m_mdl)
		goto error_exit;

	try {
		MmProbeAndLockPages(packet_data->m_mdl,
			KernelMode,
			IoReadAccess);
		packet_data->m_locked = 1;
	}
	except(EXCEPTION_EXECUTE_HANDLER) {
		packet_data->m_locked = 0;
	}

	packet_data->m_addr = MmMapLockedPagesSpecifyCache(packet_data->m_mdl,
		UserMode,
		MmCached,
		NULL,
		FALSE,
		NormalPagePriority);
	if (!packet_data->m_addr)
		goto error_exit;

	packet_data->m_map_process = PsGetCurrentProcessId();

	return packet_data;
	
error_exit:
	DbgPrint("Packet2PacketData failed, force to complete the lost packet\n");
	free_send_packet_data(packet_data);
	return NULL;
}
Пример #14
0
INT
PacketReceivePacket(
	IN    NDIS_HANDLE         ProtocolBindingContext,
	IN    PNDIS_PACKET        Packet
)
{
	UINT                bytesTransfered = 0;
	POPEN_INSTANCE      open;
	PIRP                irp;
	PNDIS_PACKET        myPacket;
	PLIST_ENTRY         packetListEntry;
	ULONG               bufferLength;
	PPACKET_RESERVED    reserved;
	PIO_STACK_LOCATION  irpSp;
	PMDL                mdl;
	PVOID               startAddress;
	NTSTATUS           status;

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

	open = (POPEN_INSTANCE)ProtocolBindingContext;

	packetListEntry = ExInterlockedRemoveHeadList(
											&open->RcvList,
											&open->RcvQSpinLock
											);

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

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

	irp = RESERVED(myPacket)->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);

	// Following block of code locks the destination packet
	// MDLs in a safe manner. This is a temporary workaround
	// for NdisCopyFromPacketToPacket that currently doesn't use
	// safe functions to lock pages of MDL. This is required to
	// prevent system from bugchecking under low memory resources.
	//
	{
		PVOID           virtualAddress;
		PNDIS_BUFFER    firstBuffer, nextBuffer;
		ULONG           totalLength;

		NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
		while( firstBuffer ) {
			NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority );
			if(!virtualAddress) {
				status = STATUS_INSUFFICIENT_RESOURCES;
				goto CleanExit;
			}
			NdisGetNextBuffer(firstBuffer,  &nextBuffer);
			firstBuffer = nextBuffer;
		}
	}

	NdisChainBufferAtFront( myPacket, irp->MdlAddress );
	bufferLength=irpSp->Parameters.Read.Length;
	NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0,  &bytesTransfered );

CleanExit:
	NdisFreePacket(myPacket);
	irp->IoStatus.Status = status;
	irp->IoStatus.Information = bytesTransfered;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	// DebugPrint(("BytesTransfered:%d\n", bytesTransfered));
	IoDecrement(open);
	return 0;
}
VOID
PtSendComplete(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN  PNDIS_PACKET		Packet,
	IN  NDIS_STATUS			Status
	)
/*++

Routine Description:

	Called by NDIS when the miniport below had completed a send. We should
	complete the corresponding upper-edge send this represents.

Arguments:

	ProtocolBindingContext	- Points to ADAPT structure
	Packet - Low level packet being completed
	Status - status of send

Return Value:

	None

--*/
{
	//-------------------------------------------------------------------------
	PNDIS_BUFFER    packet_buffer;
	PUCHAR          send_buffer = NULL;
    ULONG           send_buffer_length; 
	//-------------------------------------------------------------------------
	PADAPT			pAdapt =(PADAPT)ProtocolBindingContext;
	PNDIS_PACKET	Pkt;
	NDIS_HANDLE		PoolHandle;

#ifdef NDIS51
	//
	// Packet stacking:
	//
	// Determine if the packet we are completing is the one we allocated. If so, then
	// get the original packet from the reserved area and completed it and free the
	// allocated packet. If this is the packet that was sent down to us, then just
	// complete it
	//
	PoolHandle = NdisGetPoolFromPacket(Packet);
	if (PoolHandle != pAdapt->SendPacketPoolHandle)
	{
		//
		// We had passed down a packet belonging to the protocol above us.
		//
		// DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet));

		NdisMSendComplete(pAdapt->MiniportHandle,
						  Packet,
						  Status);
	}
	else
#endif // NDIS51
	{
		PSEND_RSVD		SendRsvd;

		SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
		Pkt = SendRsvd->OriginalPkt;
		//-------------------WestChamber-----------------------------------
		 if (!Pkt) {		//our packet			 
			//get buffer
			NdisUnchainBufferAtFront(Packet, &packet_buffer);
			if (packet_buffer) {
               NdisQueryBufferSafe(packet_buffer, (PVOID *)&send_buffer, &send_buffer_length, HighPagePriority); 
			   if (send_buffer && send_buffer_length) {
				//got buffer, free it.
                   NdisFreeMemory(send_buffer, send_buffer_length, 0);
               }
               NdisFreeBuffer(packet_buffer);
           }
			//free packet
            NdisDprFreePacket(Packet);
			return;
		}
		 //-------------------WestChamber----------------------------------
	
#ifndef WIN9X
		NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
#endif
		NdisDprFreePacket(Packet);

		NdisMSendComplete(pAdapt->MiniportHandle,
								 Pkt,
								 Status);
	}
}   	
Пример #16
0
/* We've received a csum_blank packet, but we don't want to let
   Windows see it like.  Calculate the checksum and dump it in the
   packet.  This only works for TCP and UDP on IPv4; on anything else
   it's a no-op. */
static VOID
FixupChecksum(PNDIS_PACKET packet)
{
    PNDIS_BUFFER pbuf;
    PNDIS_BUFFER pbuf_next;
    UINT bufLength;
    UINT len;
    struct ethhdr *eh;
    struct iphdr *ih;
    uint32_t csum_accumulator;
    uint32_t *ptr;
    uint16_t *csum_field;

    NdisQueryPacket(packet, NULL, NULL, &pbuf, NULL);
    NdisQueryBufferSafe(pbuf, &eh, &bufLength, NormalPagePriority);
    if (!eh || bufLength < sizeof(*eh))
        return;
    if (eh->proto != TPID_IPV4) {
        static BOOLEAN warned;
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation on non-IP ethernet prototocol %x!\n", eh->proto));
            warned = TRUE;
        }
        return;
    }
    ih = (struct iphdr *)(eh + 1);
    bufLength -= sizeof(*eh);
    if (bufLength < sizeof(*ih) ||
        bufLength < (UINT)(ih->len_version & 0x0f) * 4)
        return;
    ptr = (uint32_t *)((ULONG_PTR)ih + (ih->len_version & 0x0f)*4);
    len = ntohs(ih->tot_len) - (ih->len_version & 0x0f) * 4;

    bufLength -= (ih->len_version & 0x0f) * 4;
    if (bufLength > len)
        bufLength = len;

    if (ih->proto == IPPROTO_UDP) {
        if (bufLength < sizeof(struct udphdr))
            return;
        csum_field = &((struct udphdr *)ptr)->checksum;
    } else if (ih->proto == IPPROTO_TCP) {
        if (bufLength < sizeof(struct tcphdr))
            return;
        csum_field = &((struct tcphdr *)ptr)->checksum;
    } else {
        static BOOLEAN warned;
        /* Uh oh: don't know what this protocol is, so can't do
           checksum calculation for it. */
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation for unknown protocol %d!\n",
                          ih->proto));
            warned = TRUE;
        }
        return;
    }

    if (ih->proto == IPPROTO_TCP) {
        struct tcp_pseudo_header tph;
        uint16_t csum;

        tph.saddr = ih->src;
        tph.daddr = ih->dest;
        tph.mbz = 0;
        tph.ptcl = IPPROTO_TCP;
        tph.length = htons((uint16_t)len);

        csum_accumulator = acc_ip_csum(&tph, sizeof(tph), 0);
        csum = fold_ip_csum(csum_accumulator);

        if (*csum_field != csum)
            TraceWarning(("invlid pseudo header checksum: expected %04x, found %04x\n", csum, *csum_field));

        *csum_field = csum;
    }

    csum_accumulator = acc_ip_csum(ptr, bufLength, 0);
    len -= bufLength;

    while (len) {
        NdisGetNextBuffer(pbuf, &pbuf_next);
        if (pbuf_next == NULL)
            break;
        pbuf = pbuf_next;
        NdisQueryBufferSafe(pbuf, &ptr, &bufLength, NormalPagePriority);

        /* The buffer is already mapped into our RX buffer pool, so we
           should always be able to get a virtual address for it. */
        XM_ASSERT(ptr != NULL);

        if (bufLength > len)
            bufLength = len;

        csum_accumulator = acc_ip_csum(ptr, bufLength, csum_accumulator);
        len -= bufLength;
    }

    *csum_field = ~fold_ip_csum(csum_accumulator);
}
Пример #17
0
BOOLEAN PickPacketFromList(PADAPT pAdapt,PIRP Irp)
{
	PIO_STACK_LOCATION IrpStack;
	ULONG PacketLenTotal=0;

    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
	PUCHAR              pDstFormer;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
	ULONG               BytesToCopy;


    NdisAcquireSpinLock(&PacketListLock);

    if(!IsListEmpty(&PacketList))
    {
        //
        //  Get the first queued receive packet
        //
        pRcvPacketEntry = PacketList.Flink;
        RemoveEntryList(pRcvPacketEntry);

        PacketCount--;

        NdisReleaseSpinLock(&PacketListLock);


        pRcvPacket = SECLAB_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

        //
        //  Copy as much data as possible from the receive packet to
        //  the IRP MDL.
        //
        pDst = (PUCHAR)ExAllocatePool(NonPagedPool,MY_MTU);
        
		if(pDst==NULL)
		{
			DbgPrint("Can not allocate enough pool");
			DbgBreakPoint();
		}
        pDstFormer=pDst;

		IrpStack = IoGetCurrentIrpStackLocation(Irp);
	    BytesRemaining = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

        pNdisBuffer = pRcvPacket->Private.Head;

        while (BytesRemaining && (pNdisBuffer != NULL))
        {

            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DbgPrint("PickPacketFromList: QueryBuffer failed for buffer");
                break;
            }

            if (BytesAvailable)
            {
                BytesToCopy = MIN(BytesAvailable, BytesRemaining);

                NdisMoveMemory(pDstFormer, pSrc, BytesToCopy);
                BytesRemaining -= BytesToCopy;
                pDstFormer += BytesToCopy;
				PacketLenTotal += BytesToCopy;
            }

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

        //
        //  Complete the IRP.
        //
		RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, pDst, PacketLenTotal);
	    IoSetCancelRoutine(Irp,NULL);
	    CompleteIrp(Irp,STATUS_SUCCESS,PacketLenTotal);

		ExFreePool(pDst);
        //
        //  Free up the receive packet - back to the miniport if it
        //  belongs to it, else reclaim it (local copy).
        //
        if (NdisGetPoolFromPacket(pRcvPacket) != pAdapt->RecvPacketPoolHandle)
        {
            NdisReturnPackets(&pRcvPacket, 1);
        }
        else
        {
            SecLabFreeReceivePacket(pAdapt, pRcvPacket);
        }

    }
	else
	{
		NdisReleaseSpinLock(&PacketListLock);
		return FALSE;
	}
   
	return TRUE;
}