aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--api/wintun.h4
-rw-r--r--driver/wintun.c14
3 files changed, 13 insertions, 7 deletions
diff --git a/README.md b/README.md
index af15235..1650266 100644
--- a/README.md
+++ b/README.md
@@ -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;