mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
105 lines
2.2 KiB
C
105 lines
2.2 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS TCP/IP protocol driver
|
|
* FILE: tcpip/checksum.c
|
|
* PURPOSE: Checksum routines
|
|
* NOTES: The checksum routine is from RFC 1071
|
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
* REVISIONS:
|
|
* CSH 01/08-2000 Created
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
ULONG ChecksumFold(
|
|
ULONG Sum)
|
|
{
|
|
/* Fold 32-bit sum to 16 bits */
|
|
while (Sum >> 16)
|
|
{
|
|
Sum = (Sum & 0xFFFF) + (Sum >> 16);
|
|
}
|
|
|
|
return Sum;
|
|
}
|
|
|
|
ULONG ChecksumCompute(
|
|
PVOID Data,
|
|
UINT Count,
|
|
ULONG Seed)
|
|
/*
|
|
* FUNCTION: Calculate checksum of a buffer
|
|
* ARGUMENTS:
|
|
* Data = Pointer to buffer with data
|
|
* Count = Number of bytes in buffer
|
|
* Seed = Previously calculated checksum (if any)
|
|
* RETURNS:
|
|
* Checksum of buffer
|
|
*/
|
|
{
|
|
register ULONG Sum = Seed;
|
|
|
|
while (Count > 1)
|
|
{
|
|
Sum += *(PUSHORT)Data;
|
|
Count -= 2;
|
|
Data = (PVOID)((ULONG_PTR) Data + 2);
|
|
}
|
|
|
|
/* Add left-over byte, if any */
|
|
if (Count > 0)
|
|
{
|
|
Sum += *(PUCHAR)Data;
|
|
}
|
|
|
|
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)
|
|
DataLength++;
|
|
|
|
/* Add from the UDP header and data */
|
|
for (i = 0; i < DataLength; i += 2)
|
|
{
|
|
TmpSum = ((PacketBuffer[i] << 8) & 0xFF00) +
|
|
((Pad && i == DataLength - 2) ? 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);
|
|
}
|
|
|