// Read the packet data from the transmit packet queue void NeoRead(void *buf) { NEO_QUEUE *q; UINT num; BOOL left; // Validate arguments if (buf == NULL) { return; } // Copy the packets one by one from the queue num = 0; left = TRUE; NeoLockPacketQueue(); { while (TRUE) { if (num >= NEO_MAX_PACKET_EXCHANGE) { if (ctx->PacketQueue == NULL) { left = FALSE; } break; } q = NeoGetNextQueue(); if (q == NULL) { left = FALSE; break; } NEO_SIZE_OF_PACKET(buf, num) = q->Size; NeoCopy(NEO_ADDR_OF_PACKET(buf, num), q->Buf, q->Size); num++; NeoFreeQueue(q); } } NeoUnlockPacketQueue(); NEO_NUM_PACKET(buf) = num; NEO_LEFT_FLAG(buf) = left; if (left == FALSE) { NeoReset(ctx->Event); } else { NeoSet(ctx->Event); } return; }
// Read the next sent packet from the driver bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size) { // Validate arguments if (v == NULL || buf == NULL || size == NULL) { return false; } if (v->Halt) { return false; } PROBE_STR("VLanGetNextPacket"); while (true) { if (v->CurrentPacketCount < NEO_NUM_PACKET(v->GetBuffer)) { // There are still packets that have been read already *size = NEO_SIZE_OF_PACKET(v->GetBuffer, v->CurrentPacketCount); *buf = MallocFast(*size); Copy(*buf, NEO_ADDR_OF_PACKET(v->GetBuffer, v->CurrentPacketCount), *size); // Increment the packet number v->CurrentPacketCount++; return true; } else { // Read the next packet from the driver if (VLanGetPacketsFromDriver(v) == false) { return false; } if (NEO_NUM_PACKET(v->GetBuffer) == 0) { // Packet is not received currently *buf = NULL; *size = 0; return true; } v->CurrentPacketCount = 0; } } }
// Write the next received packet to the driver bool VLanPutPacket(VLAN *v, void *buf, UINT size) { // Validate arguments if (v == NULL) { return false; } if (v->Halt) { return false; } if (size > MAX_PACKET_SIZE) { return false; } // First, examine whether the current buffer is full if ((NEO_NUM_PACKET(v->PutBuffer) >= NEO_MAX_PACKET_EXCHANGE) || (buf == NULL && NEO_NUM_PACKET(v->PutBuffer) != 0)) { #ifdef USE_PROBE { char tmp[MAX_SIZE]; snprintf(tmp, sizeof(tmp), "VLanPutPacket: NEO_NUM_PACKET(v->PutBuffer) = %u", NEO_NUM_PACKET(v->PutBuffer)); PROBE_DATA2(tmp, NULL, 0); } #endif // USE_PROBE // Write a packet to the driver if (VLanPutPacketsToDriver(v) == false) { return false; } NEO_NUM_PACKET(v->PutBuffer) = 0; } // Add the next packet to the buffer if (buf != NULL) { UINT i = NEO_NUM_PACKET(v->PutBuffer); NEO_NUM_PACKET(v->PutBuffer)++; NEO_SIZE_OF_PACKET(v->PutBuffer, i) = size; Copy(NEO_ADDR_OF_PACKET(v->PutBuffer, i), buf, size); Free(buf); } return true; }
// Process the received packet void NeoWrite(void *buf) { UINT num, i, size; UCHAR *packet_buf; NET_BUFFER_LIST *nbl_chain = NULL; NET_BUFFER_LIST *nbl_tail = NULL; UINT num_nbl_chain = 0; // Validate arguments if (buf == NULL) { return; } // Number of packets num = NEO_NUM_PACKET(buf); if (num > NEO_MAX_PACKET_EXCHANGE) { // Number of packets is too many return; } if (num == 0) { // No packet return; } if (ctx->Halting != FALSE) { // Stopping return; } if (ctx->Paused) { // Paused return; } if (ctx->Opened == FALSE) { // Not connected return; } for (i = 0;i < num;i++) { PACKET_BUFFER *p = ctx->PacketBuffer[i]; void *dst; NET_BUFFER_LIST *nbl = ctx->PacketBuffer[i]->NetBufferList; NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl); nbl->SourceHandle = ctx->NdisMiniport; NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; size = NEO_SIZE_OF_PACKET(buf, i); if (size > NEO_MAX_PACKET_SIZE) { size = NEO_MAX_PACKET_SIZE; } if (size < NEO_PACKET_HEADER_SIZE) { size = NEO_PACKET_HEADER_SIZE; } packet_buf = (UCHAR *)(NEO_ADDR_OF_PACKET(buf, i)); if (OK(NdisRetreatNetBufferDataStart(nb, size, 0, NULL))) { // Buffer copy dst = NdisGetDataBuffer(nb, size, NULL, 1, 0); if (dst != NULL) { NeoCopy(dst, packet_buf, size); if (nbl_chain == NULL) { nbl_chain = nbl; } if (nbl_tail != NULL) { NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl; } nbl_tail = nbl; num_nbl_chain++; } } nbl->Status = NDIS_STATUS_RESOURCES; ctx->Status.Int64BytesRecvTotal += (UINT64)size; if (packet_buf[0] & 0x40) { ctx->Status.Int64NumRecvBroadcast++; ctx->Status.Int64BytesRecvBroadcast += (UINT64)size; } else { ctx->Status.Int64NumRecvUnicast++; ctx->Status.Int64BytesRecvUnicast += (UINT64)size; } } if (nbl_chain == NULL) { return; } // Notify that it has received ctx->Status.NumPacketRecv += num_nbl_chain; NdisMIndicateReceiveNetBufferLists(ctx->NdisMiniport, nbl_chain, 0, num_nbl_chain, NDIS_RECEIVE_FLAGS_RESOURCES); if (true) { // Restore the packet buffer NET_BUFFER_LIST *nbl = nbl_chain; while (nbl != NULL) { NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl); if (nb != NULL) { UINT size = NET_BUFFER_DATA_LENGTH(nb); NdisAdvanceNetBufferDataStart(nb, size, false, NULL); } nbl = NET_BUFFER_LIST_NEXT_NBL(nbl); } } }
// Process the received packet void NeoWrite(void *buf) { UINT num, i, size; void *packet_buf; // Validate arguments if (buf == NULL) { return; } // Number of packets num = NEO_NUM_PACKET(buf); if (num > NEO_MAX_PACKET_EXCHANGE) { // Number of packets is too many return; } if (num == 0) { // No packet return; } if (ctx->Halting != FALSE) { // Halting return; } if (ctx->Opened == FALSE) { // Not connected return; } for (i = 0;i < num;i++) { PACKET_BUFFER *p = ctx->PacketBuffer[i]; size = NEO_SIZE_OF_PACKET(buf, i); if (size > NEO_MAX_PACKET_SIZE) { size = NEO_MAX_PACKET_SIZE; } if (size < NEO_PACKET_HEADER_SIZE) { size = NEO_PACKET_HEADER_SIZE; } packet_buf = NEO_ADDR_OF_PACKET(buf, i); // Buffer copy NeoCopy(p->Buf, packet_buf, size); if (g_is_win8 == false) { // Adjust the buffer size NdisAdjustBufferLength(p->NdisBuffer, size); // Set the packet information NDIS_SET_PACKET_STATUS(p->NdisPacket, NDIS_STATUS_RESOURCES); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); } else { NdisMEthIndicateReceive(ctx->NdisMiniport, ctx, p->Buf, NEO_PACKET_HEADER_SIZE, ((UCHAR *)p->Buf) + NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE); NdisMEthIndicateReceiveComplete(ctx->NdisMiniport); } } // Notify that packets have received ctx->Status.NumPacketRecv += num; if (g_is_win8 == false) { NdisMIndicateReceivePacket(ctx->NdisMiniport, ctx->PacketBufferArray, num); } }