/*- * Copyright (c) 1985, 1993 The Regents of the University of California. * All rights reserved. * * %sccs.include.redist.c% */ #ifndef lint static char sccsid[] = "@(#)cksum.c 5.2 (Berkeley) 05/11/93"; #endif /* not lint */ #ifdef sgi #ident "$Revision: 1.3 $" #endif #include /* * I N _ C K S U M * * Checksum routine for Internet Protocol family headers (C Version) * * There is no profit in a specialized version of the checksum * function for any machine where int's are 32 bits and shorts are 16. * * All timed packets are smaller than 32K shorts, so there is no need to * worry about carries except at the end. */ int in_cksum(addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register u_short answer; register int sum = 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 ) sum += (*(u_char *)w) << 8; /* * 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); }