Exemplo n.º 1
0
// Packet send handler
void NeoNdisSendPackets(NDIS_HANDLE MiniportAdapterContext,
						NDIS_PACKET **PacketArray,
						UINT NumberOfPackets)
{
	UCHAR *Buf,*BufCopy;
	PNDIS_BUFFER Buffer;
	UCHAR *Tmp;
	UINT PacketLength;
	UINT CurrentLength;
	UINT i;

	if (ctx == NULL)
	{
		return;
	}

	// Update the connection state
	NeoCheckConnectState();

	if (NumberOfPackets == 0)
	{
		// The number of packets is 0
		return;
	}

	if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE)
	{
		// Device is stopped
		return;
	}

	// Operation of the packet queue
	NeoLockPacketQueue();
	{
		if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE)
		{
			// Device is stopped
			NeoUnlockPacketQueue();
			return;
		}

		// Place the packet in the queue in order
		for (i = 0;i < NumberOfPackets;i++)
		{
			// Get a packet
			NdisQueryPacket(PacketArray[i], NULL, NULL, &Buffer, &PacketLength);

			// Extract the packet.
			// Memory allocated here is used for the queue and is released at the time of releasing the queue.
			Buf = NeoMalloc(PacketLength);
			BufCopy = Buf;
			while (Buffer)
			{
				NdisQueryBuffer(Buffer, &Tmp, &CurrentLength);
				if (CurrentLength == 0)
				{
					// Complete
					break;
				}
				NeoCopy(BufCopy, Tmp, CurrentLength);
				BufCopy += CurrentLength;
				NdisGetNextBuffer(Buffer, &Buffer);
			}
			// Process this packet
			if (PacketLength > NEO_MIN_PACKET_SIZE)
			{
				if (PacketLength > NEO_MAX_PACKET_SIZE)
				{
					// Packet is too large
					NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE);

					if (g_is_win8)
					{
						NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_FAILURE);
					}

					ctx->Status.NumPacketSendError++;
					NeoFree(Buf);
				}
				else
				{
					// Insert the packet into the queue
					NeoInsertQueue(Buf, PacketLength);
					NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);

					if (g_is_win8)
					{
						NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS);
					}

					ctx->Status.NumPacketSend++;
				}
			}
			else
			{
				// Release if the packet doesn't contain data
				NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);

				if (g_is_win8)
				{
					NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS);
				}

				NeoFree(Buf);
			}
		}
	}
	NeoUnlockPacketQueue();

	// Reception event
	NeoSet(ctx->Event);
}
Exemplo n.º 2
0
// Packet send handler
void NeoNdisSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext,
							   NET_BUFFER_LIST *NetBufferLists,
							   NDIS_PORT_NUMBER PortNumber,
							   ULONG SendFlags)
{
	if (ctx == NULL)
	{
		return;
	}

	// Update the connection state
	NeoCheckConnectState();

	if (NeoNdisSendPacketsHaltCheck(NetBufferLists) == FALSE)
	{
		// Device is stopped
		return;
	}

	// Operation of the packet queue
	NeoLockPacketQueue();
	{
		NET_BUFFER_LIST *nbl;
		if (NeoNdisSendPacketsHaltCheck(NetBufferLists) == FALSE)
		{
			// Device is stopped
			NeoUnlockPacketQueue();
			return;
		}

		nbl = NetBufferLists;

		while (nbl != NULL)
		{
			NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);

			while (nb != NULL)
			{
				UINT size = NET_BUFFER_DATA_LENGTH(nb);

				if (size >= NEO_MIN_PACKET_SIZE && size <= NEO_MAX_PACKET_SIZE)
				{
					UCHAR *buf = NeoMalloc(size);
					void *ptr;

					ptr = NdisGetDataBuffer(nb, size, buf, 1, 0);

					if (ptr == NULL)
					{
						ctx->Status.NumPacketSendError++;
						ctx->Status.Int64NumSendError++;
						NeoFree(buf);
					}
					else
					{
						if (ptr != buf)
						{
							NeoCopy(buf, ptr, size);
						}

						NeoInsertQueue(buf, size);
						ctx->Status.NumPacketSend++;

						if (buf[0] & 0x40)
						{
							ctx->Status.Int64NumSendBroadcast++;
							ctx->Status.Int64BytesSendBroadcast += (UINT64)size;
						}
						else
						{
							ctx->Status.Int64NumSendUnicast++;
							ctx->Status.Int64BytesSendUnicast += (UINT64)size;
						}

						ctx->Status.Int64BytesSendTotal += (UINT64)size;
					}
				}
				else
				{
					ctx->Status.NumPacketSendError++;
					ctx->Status.Int64NumSendError++;
				}

				nb = NET_BUFFER_NEXT_NB(nb);
			}

			nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
		}
	}

	NeoUnlockPacketQueue();

	// Notify the transmission completion
	NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, NDIS_STATUS_SUCCESS);

	// Reception event
	NeoSet(ctx->Event);
}