diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | api/wintun.h | 4 | ||||
-rw-r--r-- | driver/wintun.c | 14 |
3 files changed, 13 insertions, 7 deletions
@@ -392,7 +392,7 @@ Allocates memory for a packet to send. After the memory is filled with packet da **Parameters** - *Session*: Wintun session handle obtained with WintunStartSession -- *PacketSize*: Exact packet size. Must be less or equal to WINTUN\_MAX\_IP\_PACKET\_SIZE. +- *PacketSize*: Upper estimate of packet size. Must be less or equal to WINTUN\_MAX\_IP\_PACKET\_SIZE. The exact size of the packet is determined from layer 3 IPv4 or IPv6 packet header on WintunSendPacket. IPv6 Jumbograms are not supported. **Returns** diff --git a/api/wintun.h b/api/wintun.h index b90ba82..b2395be 100644 --- a/api/wintun.h +++ b/api/wintun.h @@ -313,7 +313,9 @@ typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HAN * * @param Session Wintun session handle obtained with WintunStartSession * - * @param PacketSize Exact packet size. Must be less or equal to WINTUN_MAX_IP_PACKET_SIZE. + * @param PacketSize Upper estimate of packet size. Must be less or equal to WINTUN_MAX_IP_PACKET_SIZE. The exact + * size of the packet is determined from layer 3 IPv4 or IPv6 packet header on WintunSendPacket. + * IPv6 Jumbograms are not supported. * * @return Returns pointer to memory where to prepare layer 3 IPv4 or IPv6 packet for sending. If the function fails, * the return value is NULL. To get extended error information, call GetLastError. Possible errors include the diff --git a/driver/wintun.c b/driver/wintun.c index 4224642..b9a3bb8 100644 --- a/driver/wintun.c +++ b/driver/wintun.c @@ -532,15 +532,19 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) if (AlignedPacketSize > RingContent) break; + ULONG Layer3PacketSize; ULONG NblFlags; USHORT NblProto; const UCHAR *PacketData = Packet->Data + Ctx->Device.Receive.LeadPadding; - if (PacketSize >= 20 && PacketData[0] >> 4 == 4) + if (PacketSize >= 20 && PacketData[0] >> 4 == 4 && + (Layer3PacketSize = RtlUshortByteSwap(*(USHORT *)&PacketData[2])) >= 20 && Layer3PacketSize <= PacketSize) { NblFlags = NDIS_NBL_FLAGS_IS_IPV4; NblProto = HTONS(NDIS_ETH_TYPE_IPV4); } - else if (PacketSize >= 40 && PacketData[0] >> 4 == 6) + else if ( + PacketSize >= 40 && PacketData[0] >> 4 == 6 && + (Layer3PacketSize = 40ul + RtlUshortByteSwap(*(USHORT *)&PacketData[4])) <= PacketSize) { NblFlags = NDIS_NBL_FLAGS_IS_IPV6; NblProto = HTONS(NDIS_ETH_TYPE_IPV6); @@ -549,15 +553,15 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) break; RingHead = TUN_RING_WRAP(RingHead + AlignedPacketSize, RingCapacity); - MDL *Mdl = IoAllocateMdl(NULL, PacketSize, FALSE, FALSE, NULL); + MDL *Mdl = IoAllocateMdl(NULL, Layer3PacketSize, FALSE, FALSE, NULL); if (!Mdl) goto skipNbl; IoBuildPartialMdl( Ctx->Device.Receive.Mdl, Mdl, (UCHAR *)MmGetMdlVirtualAddress(Ctx->Device.Receive.Mdl) + (ULONG)(PacketData - (UCHAR *)Ring), - PacketSize); - NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(Ctx->NblPool, 0, 0, Mdl, 0, PacketSize); + Layer3PacketSize); + NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(Ctx->NblPool, 0, 0, Mdl, 0, Layer3PacketSize); if (!Nbl) goto cleanupMdl; Nbl->SourceHandle = Ctx->MiniportAdapterHandle; |