xref: /original-bsd/usr.sbin/timed/timed/cksum.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1985, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)cksum.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 #ifdef sgi
13 #ident "$Revision: 1.3 $"
14 #endif
15 
16 #include <sys/types.h>
17 
18 /*
19  *			I N _ C K S U M
20  *
21  * Checksum routine for Internet Protocol family headers (C Version)
22  *
23  * There is no profit in a specialized version of the checksum
24  * function for any machine where int's are 32 bits and shorts are 16.
25  *
26  * All timed packets are smaller than 32K shorts, so there is no need to
27  * worry about carries except at the end.
28  */
29 int
30 in_cksum(addr, len)
31 	u_short *addr;
32 	int len;
33 {
34 	register int nleft = len;
35 	register u_short *w = addr;
36 	register u_short answer;
37 	register int sum = 0;
38 
39 	/*
40 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
41 	 *  we add sequential 16 bit words to it, and at the end, fold
42 	 *  back all the carry bits from the top 16 bits into the lower
43 	 *  16 bits.
44 	 */
45 	while( nleft > 1 )  {
46 		sum += *w++;
47 		nleft -= 2;
48 	}
49 
50 	/* mop up an odd byte, if necessary */
51 	if( nleft == 1 )
52 		sum += (*(u_char *)w) << 8;
53 
54 	/*
55 	 * add back carry outs from top 16 bits to low 16 bits
56 	 */
57 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
58 	sum += (sum >> 16);			/* add carry */
59 	answer = ~sum;				/* truncate to 16 bits */
60 	return (answer);
61 }
62