/************************************************************************/
/*	Routing Protocol Simulator	Release 1.0	1994/3/17	*/
/*                                              1.21    1997/2/10       */
/*									*/
/*		module 	: protocol procedure				*/
/*		file	: cksum.c					*/
/*									*/
/*   Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,	*/
/*   Ltd. All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*									*/
/************************************************************************/
static char copyright[]=
  "@(#)Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,Ltd.\n All rights researved.\n";

#define MODX 4102

/*
 * in_cksum()
 * Checksum routine for Internet Protocol family headers (C Version)
 */
in_cksum(addr, len)
        unsigned short *addr;
        int len;
{
        register int nleft = len;
        register unsigned short *w = addr;
        register int sum = 0;
        unsigned short answer = 0;

        /*
         * Our algorithm is simple, using a 32 bit accumulator (sum), we add
         * sequential 16 bit words to it, and at the end, fold back all the
         * carry bits from the top 16 bits into the lower 16 bits.
         */
        while (nleft > 1)  {
                sum += *w++;
                nleft -= 2;
	      }

        /* mop up an odd byte, if necessary */
        if (nleft == 1) {
                *(unsigned char *)(&answer) = *(unsigned char *)w ;
                sum += answer;
	      }

        /* add back carry outs from top 16 bits to low 16 bits */
        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;                          /* truncate to 16 bits */
        return(answer);
      }


/*
 * encodecc()
 * Fletcher checksum algorithm
 */
     encodecc( mess,len,k )
     unsigned char mess[] ;    /* the TPDU to be checksummed */
     int      len,
              k;               /* position of first checksum octet
                                  as an offset from mess[0]  */
{ int ip,
           iq,
           ir,
           c0,
           c1;
       unsigned char *p,*p1,*p2,*p3 ;

       p = mess ; p3 = mess + len ;

       if ( k > 0) { mess[k-1] = 0x00 ; mess[k] = 0x00 ; }
            /* insert zeros for checksum octets */

       c0 = 0 ; c1 = 0  ; p1 = mess ;
       while (p1 < p3)    /* outer sum accumulation loop */
	 {
        p2 = p1 + MODX ; if (p2 > p3) p2 = p3 ;
        for (p = p1 ; p < p2 ; p++) /*  inner sum accumulation loop */
	  { c0 = c0 + (*p) ; c1 = c1 + c0 ;
	  }
        c0 = c0%255 ; c1 = c1%255 ; p1 = p2 ;
            /* adjust accumulated sums to mod 255 */
      }
        ip = (c1 << 8) + c0 ;     /* concatenate c1 and c0 */

        if (k > 0)
	  {     /* compute and insert checksum octets */

         iq = ((len-k)*c0 - c1)%255 ; if (iq <= 0) iq = iq + 255 ;
         mess[k-1] = iq ;
         ir = (510 - c0 - iq) ;
         if (ir > 255) ir = ir - 255 ; mess[k] = ir ;
       }
       return(ip) ;
}

