// 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; }
// Read next packet UINT EthGetPacket(ETH *e, void **data) { BLOCK *b; bool flag = false; // Validate arguments if (e == NULL || data == NULL) { return INFINITE; } if (e->HasFatalError) { return INFINITE; } if (e->SuAdapter != NULL) { // Read packet with SeLow UINT size; if (SuGetNextPacket(e->SuAdapter, data, &size) == false) { // Error occurred e->HasFatalError = true; return INFINITE; } return size; } RETRY: // Check the presence of the packet in queue b = GetNext(e->PacketQueue); if (b != NULL) { UINT size; size = b->Size; *data = b->Buf; Free(b); if (e->PacketQueue->num_item == 0) { e->Empty = true; } return size; } if (e->Empty) { e->Empty = false; return 0; } if (flag == false) { // Try to get next packet PROBE_STR("EthGetPacket: PacketInitPacket"); wp->PacketInitPacket(e->Packet, e->Buffer, e->BufferSize); PROBE_STR("EthGetPacket: PacketReceivePacket"); if (wp->PacketReceivePacket(e->Adapter, e->Packet, false) == false) { // Failed return INFINITE; } else { UCHAR *buf; UINT total; UINT offset; buf = (UCHAR *)e->Packet->Buffer; total = e->Packet->ulBytesReceived; offset = 0; while (offset < total) { struct bpf_hdr *header; UINT packet_size; UCHAR *packet_data; header = (struct bpf_hdr *)(buf + offset); packet_size = header->bh_caplen; offset += header->bh_hdrlen; packet_data = buf + offset; offset = Packet_WORDALIGN(offset + packet_size); if (packet_size >= 14) { UCHAR *tmp; BLOCK *b; PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size); tmp = MallocFast(packet_size); Copy(tmp, packet_data, packet_size); b = NewBlock(tmp, packet_size, 0); InsertQueue(e->PacketQueue, b); } } flag = true; goto RETRY; } } // No more packet return 0; }
// Send multiple packets void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes) { UINT i, total_size; UCHAR *buf; UINT write_pointer; UINT err = 0; // Validate arguments if (e == NULL || num == 0 || datas == NULL || sizes == NULL) { return; } if (e->HasFatalError) { return; } if (e->SuAdapter != NULL) { bool ok = true; // Send packets with SeLow for (i = 0;i < num;i++) { UCHAR *data = datas[i]; UINT size = sizes[i]; if (ok) { // Actually, only enqueuing ok = SuPutPacket(e->SuAdapter, data, size); } if (ok == false) { // Free memory on write error Free(data); } } if (ok) { // Send all data in queue at once ok = SuPutPacket(e->SuAdapter, NULL, 0); } if (ok == false) { // Error occurred e->HasFatalError = true; } return; } if (IsWin32BridgeWithSee() == false) { if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64()) { e->LastSetSingleCpu = Tick64(); MsSetThreadSingleCpu(); } } // Calculate buffer size total_size = 0; for (i = 0;i < num;i++) { void *data = datas[i]; UINT size = sizes[i]; if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE) { total_size += size + sizeof(struct dump_bpf_hdr); } } buf = MallocFast(total_size * 100 / 75 + 1600); write_pointer = 0; // Enqueue for (i = 0;i < num;i++) { void *data = datas[i]; UINT size = sizes[i]; if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE) { struct dump_bpf_hdr *h; h = (struct dump_bpf_hdr *)(buf + write_pointer); Zero(h, sizeof(struct dump_bpf_hdr)); h->caplen = h->len = size; write_pointer += sizeof(struct dump_bpf_hdr); Copy(buf + write_pointer, data, size); write_pointer += size; PROBE_DATA2("EthPutPackets", data, size); } // Free original buffer Free(data); } // Send if (total_size != 0) { err = wp->PacketSendPackets(e->Adapter, buf, total_size, true); } Free(buf); if (err == 0x7FFFFFFF) { // Critical error (infinite loop) occurred on sending e->HasFatalError = true; } }