1 /*
2  * Copyright (c) 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)cksum.tahoe.c	2.4 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 
14 /*
15  * Checksum routine for Internet Protocol family headers.
16  *
17  * This routine is very heavily used in the network
18  * code and should be modified for each CPU to be as fast as possible.
19  *
20  * This implementation is TAHOE version.
21  */
22 
23 #undef	ADDCARRY
24 #define ADDCARRY(sum) { \
25 	if (sum & 0xffff0000) {	\
26 		sum &= 0xffff; \
27 		sum++; \
28 	} \
29 }
30 
31 in_cksum(addr, len)
32 	register u_short *addr;
33 	register int len;
34 {
35 	union word {
36 		char	c[2];
37 		u_short	s;
38 	} u;
39 	register int sum = 0;
40 
41 	while (len > 0) {
42 		/*
43 		 * add by words.
44 		 */
45 		while ((len -= 2) >= 0) {
46 			if ((int)addr & 0x1) {
47 				/* word is not aligned */
48 				u.c[0] = *(char *)addr;
49 				u.c[1] = *((char *)addr+1);
50 				sum += u.s;
51 				addr++;
52 			} else
53 				sum += *addr++;
54 			ADDCARRY(sum);
55 		}
56 		if (len == -1)
57 			/*
58 			 * Odd number of bytes.
59 			 */
60 			u.c[0] = *(u_char *)addr;
61 	}
62 	if (len == -1) {
63 		/* The last mbuf has odd # of bytes. Follow the
64 		   standard (the odd byte is shifted left by 8 bits) */
65 		u.c[1] = 0;
66 		sum += u.s;
67 		ADDCARRY(sum);
68 	}
69 	return (~sum & 0xffff);
70 }
71