Author: cgutman
Date: Tue Oct 20 07:24:37 2009
New Revision: 43637
URL:
http://svn.reactos.org/svn/reactos?rev=43637&view=rev
Log:
- 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
Modified:
trunk/reactos/drivers/network/tcpip/include/checksum.h
trunk/reactos/lib/drivers/ip/network/checksum.c
trunk/reactos/lib/drivers/ip/transport/udp/udp.c
Modified: trunk/reactos/drivers/network/tcpip/include/checksum.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/incl…
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/checksum.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/include/checksum.h [iso-8859-1] Tue Oct 20
07:24:37 2009
@@ -22,6 +22,12 @@
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)))
Modified: trunk/reactos/lib/drivers/ip/network/checksum.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/che…
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/checksum.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/checksum.c [iso-8859-1] Tue Oct 20 07:24:37 2009
@@ -55,3 +55,53 @@
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);
+}
+
Modified: trunk/reactos/lib/drivers/ip/transport/udp/udp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/u…
==============================================================================
--- trunk/reactos/lib/drivers/ip/transport/udp/udp.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/transport/udp/udp.c [iso-8859-1] Tue Oct 20 07:24:37
2009
@@ -19,6 +19,7 @@
PIP_ADDRESS LocalAddress,
USHORT LocalPort,
PIP_PACKET IPPacket,
+ PVOID Data,
UINT DataLength)
/*
* FUNCTION: Adds an IPv4 and UDP header to an IP packet
@@ -49,10 +50,20 @@
/* 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,
@@ -105,7 +116,7 @@
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 */
@@ -120,12 +131,6 @@
FreeNdisPacket(Packet->NdisPacket);
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"));
@@ -258,7 +263,15 @@
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);