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)15 ULONG 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)27 ULONG 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)60 UDPv4ChecksumCalculate(
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