Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/network/tcpip/include/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef union _IP_HEADER {
#define IPv4_FRAGOFS_MASK 0x1FFF /* Fragment offset mask (host byte order) */
#define IPv4_MF_MASK 0x2000 /* More fragments (host byte order) */
#define IPv4_DF_MASK 0x4000 /* Don't fragment (host byte order) */
#define IPv4_MAX_PACKET_SIZE 65535
#define IPv4_MAX_HEADER_SIZE 60

/* Packet completion handler prototype */
Expand Down
60 changes: 51 additions & 9 deletions drivers/network/tcpip/ip/network/receive.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,25 @@ ReassembleDatagram(
TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));

if (IPDR->HeaderSize < sizeof(IPv4_HEADER) || IPDR->HeaderSize > IPv4_MAX_HEADER_SIZE || IPDR->DataSize > IPv4_MAX_PACKET_SIZE - IPDR->HeaderSize)
{
TI_DbgPrint(MIN_TRACE, ("Invalid reassembled datagram size.\n"));
return FALSE;
}

CurrentEntry = IPDR->FragmentListHead.Flink;
while (CurrentEntry != &IPDR->FragmentListHead)
{
Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
if (Fragment->Size > IPDR->DataSize || Fragment->Offset > IPDR->DataSize - Fragment->Size)
{
TI_DbgPrint(MIN_TRACE, ("Invalid fragment range in reassembled datagram.\n"));
return FALSE;
}

CurrentEntry = CurrentEntry->Flink;
}

IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize;
IPPacket->HeaderSize = IPDR->HeaderSize;

Expand Down Expand Up @@ -285,8 +304,10 @@ VOID ProcessFragment(
PIPDATAGRAM_REASSEMBLY IPDR;
PLIST_ENTRY CurrentEntry;
PIPDATAGRAM_HOLE Hole, NewHole;
USHORT FragFirst;
USHORT FragLast;
UINT FragFirst;
UINT FragLast;
UINT FragmentSize;
UINT FlagsFragOfs;
BOOLEAN MoreFragments;
PIPv4_HEADER IPv4Header;
IP_PACKET Datagram;
Expand All @@ -296,6 +317,24 @@ VOID ProcessFragment(
/* FIXME: Assume IPv4 */

IPv4Header = (PIPv4_HEADER)IPPacket->Header;
FlagsFragOfs = WN2H(IPv4Header->FlagsFragOfs);
FragFirst = (FlagsFragOfs & IPv4_FRAGOFS_MASK) << 3;
FragmentSize = IPPacket->TotalSize - IPPacket->HeaderSize;
MoreFragments = (FlagsFragOfs & IPv4_MF_MASK) > 0;

if (FragmentSize > IPv4_MAX_PACKET_SIZE - FragFirst)
{
TI_DbgPrint(MIN_TRACE, ("Discarding IPv4 fragment with invalid size (%u, %u).\n", FragFirst, FragmentSize));
return;
}

if (FragmentSize == 0 && (FragFirst != 0 || MoreFragments))
{
TI_DbgPrint(MIN_TRACE, ("Discarding empty IPv4 fragment (%u).\n", FragFirst));
return;
}

FragLast = FragmentSize ? FragFirst + FragmentSize - 1 : FragFirst;

/* Check if we already have an reassembly structure for this datagram */
IPDR = GetReassemblyInfo(IPPacket);
Expand Down Expand Up @@ -344,10 +383,6 @@ VOID ProcessFragment(
&ReassemblyListLock);
}

FragFirst = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_FRAGOFS_MASK) << 3;
FragLast = FragFirst + WN2H(IPv4Header->TotalLength);
MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;

CurrentEntry = IPDR->HoleListHead.Flink;
for (;;) {
if (CurrentEntry == &IPDR->HoleListHead)
Expand Down Expand Up @@ -429,7 +464,7 @@ VOID ProcessFragment(

TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));

Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
Fragment->Size = FragmentSize;
Fragment->Packet = IPPacket->NdisPacket;
Fragment->ReturnPacket = IPPacket->ReturnPacket;
Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize;
Expand All @@ -440,7 +475,7 @@ VOID ProcessFragment(

/* If this is the last fragment, compute and save the datagram data size */
if (!MoreFragments)
IPDR->DataSize = FragFirst + Fragment->Size;
IPDR->DataSize = FragFirst + FragmentSize;

/* Put the fragment in the list */
InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
Expand Down Expand Up @@ -580,7 +615,8 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
IPPacket->HeaderSize = (FirstByte & 0x0F) << 2;
TI_DbgPrint(DEBUG_IP, ("IPPacket->HeaderSize = %d\n", IPPacket->HeaderSize));

if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) {
if (IPPacket->HeaderSize < sizeof(IPv4_HEADER) || IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE)
{
TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n",
IPPacket->HeaderSize));
/* Discard packet */
Expand Down Expand Up @@ -620,6 +656,12 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
}

IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength);
if (IPPacket->TotalSize < IPPacket->HeaderSize)
{
TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect total size (%d).\n", IPPacket->TotalSize));
/* Discard packet */
return;
}

AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
Expand Down
33 changes: 23 additions & 10 deletions drivers/network/tcpip/ip/transport/udp/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ VOID UDPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
PADDRESS_FILE AddrFile;
PUDP_HEADER UDPHeader;
PIP_ADDRESS DstAddress, SrcAddress;
UINT DataSize, i;
UINT Checksum, DataSize, Length;
UINT PayloadSize;

TI_DbgPrint(MAX_TRACE, ("Called.\n"));

Expand All @@ -278,25 +279,37 @@ VOID UDPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)

UDPHeader = (PUDP_HEADER)IPPacket->Data;

/* Calculate and validate UDP checksum */
i = UDPv4ChecksumCalculate(IPv4Header,
(PUCHAR)UDPHeader,
WH2N(UDPHeader->Length));
if (i != DH2N(0x0000FFFF) && UDPHeader->Checksum != 0)
if (IPPacket->TotalSize < IPPacket->HeaderSize)
{
TI_DbgPrint(MIN_TRACE, ("Bad checksum on packet received.\n"));
TI_DbgPrint(MIN_TRACE, ("Incorrect or damaged UDP packet received.\n"));
return;
}

PayloadSize = IPPacket->TotalSize - IPPacket->HeaderSize;
if (PayloadSize < sizeof(UDP_HEADER))
{
/* Incorrect or damaged packet received, discard it */
TI_DbgPrint(MIN_TRACE, ("Incorrect or damaged UDP packet received.\n"));
return;
}

/* Sanity checks */
i = WH2N(UDPHeader->Length);
if ((i < sizeof(UDP_HEADER)) || (i > IPPacket->TotalSize - IPPacket->Position)) {
Length = WH2N(UDPHeader->Length);
if ((Length < sizeof(UDP_HEADER)) || (Length > PayloadSize))
{
/* Incorrect or damaged packet received, discard it */
TI_DbgPrint(MIN_TRACE, ("Incorrect or damaged UDP packet received.\n"));
return;
}
DataSize = Length - sizeof(UDP_HEADER);

DataSize = i - sizeof(UDP_HEADER);
/* Calculate and validate UDP checksum */
Checksum = UDPv4ChecksumCalculate(IPv4Header, (PUCHAR)UDPHeader, Length);
if (Checksum != DH2N(0x0000FFFF) && UDPHeader->Checksum != 0)
{
TI_DbgPrint(MIN_TRACE, ("Bad checksum on packet received.\n"));
return;
}

/* Go to UDP data area */
IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Data + sizeof(UDP_HEADER));
Expand Down
Loading