xref: /csrg-svn/sys/netns/ns_cksum.c (revision 25949)
1*25949Ssam /*	ns_cksum.c	1.1	86/01/23	*/
2*25949Ssam 
3*25949Ssam /*
4*25949Ssam  * ns_cksum.c - Xerox Internet Datagram protocol checksum
5*25949Ssam  */
6*25949Ssam #include "types.h"
7*25949Ssam #include "mbuf.h"
8*25949Ssam 
9*25949Ssam /*
10*25949Ssam  * Perform (slowly) the Xerox Internet checksum algorithm on a
11*25949Ssam  *	chain of mbufs.  This means we add all the 16-bits words,
12*25949Ssam  *	shifting the sum after each 16-bit add.  Ones-complement
13*25949Ssam  *	arithmetic is required, so we fold the carry bits after
14*25949Ssam  *	each 16-bit add as well.
15*25949Ssam  * If the result is the *no-checksum* value 0xffff, return zero instead.
16*25949Ssam  *
17*25949Ssam  * Chris Torek <chris@maryland>
18*25949Ssam  * James O'Toole <james@maryland>
19*25949Ssam  */
20*25949Ssam u_short
21*25949Ssam ns_cksum(m, len)
22*25949Ssam 	register struct mbuf *m;
23*25949Ssam 	register int len;
24*25949Ssam {
25*25949Ssam 	register int cksum = 0;
26*25949Ssam 	register int shift = 8;
27*25949Ssam 	register u_char *p;
28*25949Ssam 	register int mlen;
29*25949Ssam 
30*25949Ssam 	if (len & 1)
31*25949Ssam 		printf("ns_cksum: odd length\n");
32*25949Ssam 	while (m && len) {
33*25949Ssam 		p = mtod(m, u_char *);
34*25949Ssam 		mlen = m->m_len;
35*25949Ssam 		if ((len -= mlen) < 0)
36*25949Ssam 			mlen += len, len = 0;
37*25949Ssam 		while (--mlen >= 0) {
38*25949Ssam 			cksum += *p++ << shift;
39*25949Ssam 			if ((shift = 8 - shift) != 0) {
40*25949Ssam 				cksum <<= 1;
41*25949Ssam 				cksum = (cksum & 0xffff) + (cksum >> 16);
42*25949Ssam 			}
43*25949Ssam 		}
44*25949Ssam 		m = m->m_next;
45*25949Ssam 	}
46*25949Ssam #ifdef notdef
47*25949Ssam 	if (len)
48*25949Ssam 		printf("ns_cksum: out of data\n");
49*25949Ssam #endif
50*25949Ssam 	return (cksum == 0xffff ? 0 : cksum);
51*25949Ssam }
52