1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS TCP/IP protocol driver 4 * FILE: tcpip/checksum.c 5 * PURPOSE: Checksum routines 6 * NOTES: The checksum routine is from RFC 1071 7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 8 * REVISIONS: 9 * CSH 01/08-2000 Created 10 */ 11 12 #include "precomp.h" 13 14 ChecksumFold(ULONG Sum)15ULONG ChecksumFold( 16 ULONG Sum) 17 { 18 /* Fold 32-bit sum to 16 bits */ 19 while (Sum >> 16) 20 { 21 Sum = (Sum & 0xFFFF) + (Sum >> 16); 22 } 23 24 return Sum; 25 } 26 ChecksumCompute(PVOID Data,UINT Count,ULONG Seed)27ULONG ChecksumCompute( 28 PVOID Data, 29 UINT Count, 30 ULONG Seed) 31 /* 32 * FUNCTION: Calculate checksum of a buffer 33 * ARGUMENTS: 34 * Data = Pointer to buffer with data 35 * Count = Number of bytes in buffer 36 * Seed = Previously calculated checksum (if any) 37 * RETURNS: 38 * Checksum of buffer 39 */ 40 { 41 register ULONG Sum = Seed; 42 43 while (Count > 1) 44 { 45 Sum += *(PUSHORT)Data; 46 Count -= 2; 47 Data = (PVOID)((ULONG_PTR) Data + 2); 48 } 49 50 /* Add left-over byte, if any */ 51 if (Count > 0) 52 { 53 Sum += *(PUCHAR)Data; 54 } 55 56 return Sum; 57 } 58 59 ULONG UDPv4ChecksumCalculate(PIPv4_HEADER IPHeader,PUCHAR PacketBuffer,ULONG DataLength)60UDPv4ChecksumCalculate( 61 PIPv4_HEADER IPHeader, 62 PUCHAR PacketBuffer, 63 ULONG DataLength) 64 { 65 ULONG Sum = 0; 66 USHORT TmpSum; 67 ULONG i; 68 BOOLEAN Pad; 69 70 /* Pad the data if needed */ 71 Pad = (DataLength & 1); 72 if (Pad) 73 DataLength++; 74 75 /* Add from the UDP header and data */ 76 for (i = 0; i < DataLength; i += 2) 77 { 78 TmpSum = ((PacketBuffer[i] << 8) & 0xFF00) + 79 ((Pad && i == DataLength - 2) ? 0 : (PacketBuffer[i+1] & 0x00FF)); 80 Sum += TmpSum; 81 } 82 83 /* Add the source address */ 84 for (i = 0; i < sizeof(IPv4_RAW_ADDRESS); i += 2) 85 { 86 TmpSum = ((((PUCHAR)&IPHeader->SrcAddr)[i] << 8) & 0xFF00) + 87 (((PUCHAR)&IPHeader->SrcAddr)[i+1] & 0x00FF); 88 Sum += TmpSum; 89 } 90 91 /* Add the destination address */ 92 for (i = 0; i < sizeof(IPv4_RAW_ADDRESS); i += 2) 93 { 94 TmpSum = ((((PUCHAR)&IPHeader->DstAddr)[i] << 8) & 0xFF00) + 95 (((PUCHAR)&IPHeader->DstAddr)[i+1] & 0x00FF); 96 Sum += TmpSum; 97 } 98 99 /* Add the proto number and length */ 100 Sum += IPPROTO_UDP + (DataLength - (Pad ? 1 : 0)); 101 102 /* Fold the checksum and return the one's complement */ 103 return ~ChecksumFold(Sum); 104 } 105 106