// Clear to zero by memory allocation void *NeoZeroMalloc(UINT size) { void *p = NeoMalloc(size); if (p == NULL) { // Memory allocation failure return NULL; } // Clear to zero NeoZero(p, size); return p; }
// Create a packet buffer PACKET_BUFFER *NeoNewPacketBuffer() { PACKET_BUFFER *p; NDIS_STATUS ret; // Memory allocation p = NeoZeroMalloc(sizeof(PACKET_BUFFER)); // Memory allocation for packet p->Buf = NeoMalloc(NEO_MAX_PACKET_SIZE); // Allocate the buffer pool NdisAllocateBufferPool(&ret, &p->BufferPool, 1); // Allocate the buffer NdisAllocateBuffer(&ret, &p->NdisBuffer, p->BufferPool, p->Buf, NEO_MAX_PACKET_SIZE); // Secure the packet pool NdisAllocatePacketPool(&ret, &p->PacketPool, 1, PROTOCOL_RESERVED_SIZE_IN_PACKET); // Secure the packet NdisAllocatePacket(&ret, &p->NdisPacket, p->PacketPool); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); // Attach the buffer to the packet NdisChainBufferAtFront(p->NdisPacket, p->NdisBuffer); return p; }
// Insert the queue void NeoInsertQueue(void *buf, UINT size) { NEO_QUEUE *p; // Validate arguments if (buf == NULL || size == 0) { return; } // Prevent the packet accumulation in large quantities in the queue if (ctx->NumPacketQueue > NEO_MAX_PACKET_QUEUED) { NeoFree(buf); return; } // Create a queue p = NeoMalloc(sizeof(NEO_QUEUE)); p->Next = NULL; p->Size = size; p->Buf = buf; // Append to the queue if (ctx->PacketQueue == NULL) { ctx->PacketQueue = p; } else { NEO_QUEUE *q = ctx->Tail; q->Next = p; } ctx->Tail = p; ctx->NumPacketQueue++; }
// 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); }
// 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); }