diff --git a/reactos/drivers/network/tcpip/include/checksum.h b/reactos/drivers/network/tcpip/include/checksum.h index 2157c50f797..3ee66aedb78 100644 --- a/reactos/drivers/network/tcpip/include/checksum.h +++ b/reactos/drivers/network/tcpip/include/checksum.h @@ -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))) diff --git a/reactos/lib/drivers/ip/network/checksum.c b/reactos/lib/drivers/ip/network/checksum.c index 7f11c1a74ae..18f81d934b6 100644 --- a/reactos/lib/drivers/ip/network/checksum.c +++ b/reactos/lib/drivers/ip/network/checksum.c @@ -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); +} + diff --git a/reactos/lib/drivers/ip/transport/udp/udp.c b/reactos/lib/drivers/ip/transport/udp/udp.c index 1f8bdf6d1f4..b6ad0d0db38 100644 --- a/reactos/lib/drivers/ip/transport/udp/udp.c +++ b/reactos/lib/drivers/ip/transport/udp/udp.c @@ -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);