//===================================================== file = check32.c ======
//=  Program to compute a 32-bit checksum                                     =
//=============================================================================
//=  Notes: 1) Based on the C-code given in RFC 1071 (Computing the Internet  =
//=            Checksum by R. Braden, D. Borman, and C. Partridge, 1988).     =
//=         2) Uses a "trick" to detect overflows and then adds them          =
//=            in all at once                                                 =
//=---------------------------------------------------------------------------=
//=  Build:  bcc32 check32.c, gcc check32.c                                  =
//=---------------------------------------------------------------------------=
//=  History:  KJC (8/25/00) - Genesis (from checksum.c)                      =
//=============================================================================
//----- Include files ---------------------------------------------------------
#include <stdio.h>                  // Needed for printf()
#include <stdlib.h>                 // Needed for rand()

//----- Type defines ----------------------------------------------------------
typedef unsigned char      byte;    // Byte is a char
typedef unsigned short int word16;  // 16-bit word is a short int
typedef unsigned int       word32;  // 32-bit word is an int

//----- Defines ---------------------------------------------------------------
#define BUFFER_LEN       4096L      // Length of buffer

//----- Prototypes ------------------------------------------------------------
word32 checksum(byte *addr, word32 count);

//===== Main program ==========================================================
void main(void)
{
  byte        buff[BUFFER_LEN]; // Buffer of packet bytes
  word32      check;            // 32-bit checksum value
  word32      i;                // Loop counter

  // Load buffer with BUFFER_LEN random bytes
  for (i=0; i<BUFFER_LEN; i++)
    buff[i] = (byte) rand();

  // Compute and output checksum
  check = checksum(buff, BUFFER_LEN);
  printf("checksum = %08X \n", check);
}

//=============================================================================
//=  Compute a 32-bit checksum for "count" bytes beginning at location "addr" =
//=============================================================================
word32 checksum(byte *addr, word32 count)
{
  register word32 sum;          // Sum variable
  register word32 sumLast;      // Last sum
  register word32 overflow;     // Overflow sum

  // Main summing loop
  sum = sumLast = overflow = 0;
  while(count > 3)
  {
    sum = sum + *((word32 *) addr)++;
    count = count - 4;
    if (sum < sumLast) overflow++;
    sumLast = sum;
  }

  // Add left-over bytes, if any
  while (count > 0)
  {
    sum = sum + *((byte *) addr)++;
    count = count - 1;
    if (sum < sumLast) overflow++;
    sumLast = sum;
  }

  // Add overflows to sum
  sum = sum + overflow;

  // Return the complement as the 32-bit checksum
  return(~sum);
}

