1 /*
2  * Copyright (c) 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)cksum.tahoe.c	2.2 (Berkeley) 12/23/87";
15 #endif /* not lint */
16 
17 #include <sys/types.h>
18 
19 /*
20  * Checksum routine for Internet Protocol family headers.
21  *
22  * This routine is very heavily used in the network
23  * code and should be modified for each CPU to be as fast as possible.
24  *
25  * This implementation is TAHOE version.
26  */
27 
28 #undef	ADDCARRY
29 #define ADDCARRY(sum) { \
30 	if (sum & 0xffff0000) {	\
31 		sum &= 0xffff; \
32 		sum++; \
33 	} \
34 }
35 
36 in_cksum(addr, len)
37 	register u_short *addr;
38 	register int len;
39 {
40 	union word {
41 		char	c[2];
42 		u_short	s;
43 	} u;
44 	register int sum = 0;
45 
46 	while (len > 0) {
47 		/*
48 		 * add by words.
49 		 */
50 		while ((len -= 2) >= 0) {
51 			if ((int)addr & 0x1) {
52 				/* word is not aligned */
53 				u.c[0] = *(char *)addr;
54 				u.c[1] = *((char *)addr+1);
55 				sum += u.s;
56 				addr++;
57 			} else
58 				sum += *addr++;
59 			ADDCARRY(sum);
60 		}
61 		if (len == -1)
62 			/*
63 			 * Odd number of bytes.
64 			 */
65 			u.c[0] = *(u_char *)addr;
66 	}
67 	if (len == -1) {
68 		/* The last mbuf has odd # of bytes. Follow the
69 		   standard (the odd byte is shifted left by 8 bits) */
70 		u.c[1] = 0;
71 		sum += u.s;
72 		ADDCARRY(sum);
73 	}
74 	return (~sum & 0xffff);
75 }
76