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/inclu... ============================================================================== --- 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/chec... ============================================================================== --- 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/ud... ============================================================================== --- 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);