mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 05:58:13 +00:00
- Implement UDP checksum calculation
- Fixes issues with DHCP (and any other UDP traffic) over bridged networking on vbox and issues with other hardware that doesn't like a checksum of 0 - See bug #4754 svn path=/trunk/; revision=43637
This commit is contained in:
parent
6f08578e3c
commit
31ba6d7556
3 changed files with 78 additions and 9 deletions
|
@ -22,6 +22,12 @@ csum_partial(
|
|||
int len,
|
||||
unsigned int sum);
|
||||
|
||||
ULONG
|
||||
UDPv4ChecksumCalculate(
|
||||
PIPv4_HEADER IPHeader,
|
||||
PUCHAR PacketBuffer,
|
||||
ULONG DataLength);
|
||||
|
||||
#define IPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
|
||||
#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(csum_partial(Data, Count, Seed)))
|
||||
//#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
|
||||
|
|
|
@ -55,3 +55,53 @@ ULONG ChecksumCompute(
|
|||
|
||||
return Sum;
|
||||
}
|
||||
|
||||
ULONG
|
||||
UDPv4ChecksumCalculate(
|
||||
PIPv4_HEADER IPHeader,
|
||||
PUCHAR PacketBuffer,
|
||||
ULONG DataLength)
|
||||
{
|
||||
ULONG Sum = 0;
|
||||
USHORT TmpSum;
|
||||
ULONG i;
|
||||
BOOLEAN Pad;
|
||||
|
||||
/* Pad the data if needed */
|
||||
Pad = (DataLength & 1);
|
||||
if (Pad) {
|
||||
DbgPrint("Odd\n");
|
||||
DataLength++;
|
||||
} else DbgPrint("Even\n");
|
||||
|
||||
/* Add from the UDP header and data */
|
||||
for (i = 0; i < DataLength; i += 2)
|
||||
{
|
||||
TmpSum = ((PacketBuffer[i] << 8) & 0xFF00) +
|
||||
((Pad && i == DataLength - 1) ? 0 : (PacketBuffer[i+1] & 0x00FF));
|
||||
Sum += TmpSum;
|
||||
}
|
||||
|
||||
/* Add the source address */
|
||||
for (i = 0; i < sizeof(IPv4_RAW_ADDRESS); i += 2)
|
||||
{
|
||||
TmpSum = ((((PUCHAR)&IPHeader->SrcAddr)[i] << 8) & 0xFF00) +
|
||||
(((PUCHAR)&IPHeader->SrcAddr)[i+1] & 0x00FF);
|
||||
Sum += TmpSum;
|
||||
}
|
||||
|
||||
/* Add the destination address */
|
||||
for (i = 0; i < sizeof(IPv4_RAW_ADDRESS); i += 2)
|
||||
{
|
||||
TmpSum = ((((PUCHAR)&IPHeader->DstAddr)[i] << 8) & 0xFF00) +
|
||||
(((PUCHAR)&IPHeader->DstAddr)[i+1] & 0x00FF);
|
||||
Sum += TmpSum;
|
||||
}
|
||||
|
||||
/* Add the proto number and length */
|
||||
Sum += IPPROTO_UDP + (DataLength - (Pad ? 1 : 0));
|
||||
|
||||
/* Fold the checksum and return the one's complement */
|
||||
return ~ChecksumFold(Sum);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ NTSTATUS AddUDPHeaderIPv4(
|
|||
PIP_ADDRESS LocalAddress,
|
||||
USHORT LocalPort,
|
||||
PIP_PACKET IPPacket,
|
||||
PVOID Data,
|
||||
UINT DataLength)
|
||||
/*
|
||||
* FUNCTION: Adds an IPv4 and UDP header to an IP packet
|
||||
|
@ -49,11 +50,21 @@ NTSTATUS AddUDPHeaderIPv4(
|
|||
/* Port values are already big-endian values */
|
||||
UDPHeader->SourcePort = LocalPort;
|
||||
UDPHeader->DestPort = RemotePort;
|
||||
/* FIXME: Calculate UDP checksum and put it in UDP header */
|
||||
UDPHeader->Checksum = 0;
|
||||
/* Length of UDP header and data */
|
||||
UDPHeader->Length = WH2N(DataLength + sizeof(UDP_HEADER));
|
||||
|
||||
TI_DbgPrint(MID_TRACE, ("Copying data (hdr %x data %x (%d))\n",
|
||||
IPPacket->Header, IPPacket->Data,
|
||||
(PCHAR)IPPacket->Data - (PCHAR)IPPacket->Header));
|
||||
|
||||
RtlCopyMemory(IPPacket->Data, Data, DataLength);
|
||||
|
||||
UDPHeader->Checksum = UDPv4ChecksumCalculate((PIPv4_HEADER)IPPacket->Header,
|
||||
(PUCHAR)UDPHeader,
|
||||
DataLength + sizeof(UDP_HEADER));
|
||||
UDPHeader->Checksum = WH2N(UDPHeader->Checksum);
|
||||
|
||||
TI_DbgPrint(MID_TRACE, ("Packet: %d ip %d udp %d payload\n",
|
||||
(PCHAR)UDPHeader - (PCHAR)IPPacket->Header,
|
||||
(PCHAR)IPPacket->Data - (PCHAR)UDPHeader,
|
||||
|
@ -105,7 +116,7 @@ NTSTATUS BuildUDPPacket(
|
|||
switch (RemoteAddress->Type) {
|
||||
case IP_ADDRESS_V4:
|
||||
Status = AddUDPHeaderIPv4(RemoteAddress, RemotePort,
|
||||
LocalAddress, LocalPort, Packet, DataLen);
|
||||
LocalAddress, LocalPort, Packet, DataBuffer, DataLen);
|
||||
break;
|
||||
case IP_ADDRESS_V6:
|
||||
/* FIXME: Support IPv6 */
|
||||
|
@ -121,12 +132,6 @@ NTSTATUS BuildUDPPacket(
|
|||
return Status;
|
||||
}
|
||||
|
||||
TI_DbgPrint(MID_TRACE, ("Copying data (hdr %x data %x (%d))\n",
|
||||
Packet->Header, Packet->Data,
|
||||
(PCHAR)Packet->Data - (PCHAR)Packet->Header));
|
||||
|
||||
RtlCopyMemory( Packet->Data, DataBuffer, DataLen );
|
||||
|
||||
TI_DbgPrint(MID_TRACE, ("Displaying packet\n"));
|
||||
|
||||
DISPLAY_IP_PACKET(Packet);
|
||||
|
@ -258,7 +263,15 @@ VOID UDPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
|
|||
|
||||
UDPHeader = (PUDP_HEADER)IPPacket->Data;
|
||||
|
||||
/* FIXME: Calculate and validate UDP checksum */
|
||||
/* Calculate and validate UDP checksum */
|
||||
i = UDPv4ChecksumCalculate(IPv4Header,
|
||||
(PUCHAR)UDPHeader,
|
||||
WH2N(UDPHeader->Length));
|
||||
if (i != DH2N(0x0000FFFF))
|
||||
{
|
||||
TI_DbgPrint(MIN_TRACE, ("Bad checksum on packet received.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sanity checks */
|
||||
i = WH2N(UDPHeader->Length);
|
||||
|
|
Loading…
Reference in a new issue