xref: /original-bsd/sys/hp300/hp300/in_cksum.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1988, 1990 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  * from: Utah $Hdr: in_cksum.c 1.1 90/07/09$
8  *
9  *	@(#)in_cksum.c	7.5 (Berkeley) 06/03/93
10  */
11 
12 /*
13  * in_cksum - checksum routine for the Internet Protocol family.
14  */
15 
16 #include <sys/param.h>
17 #include <sys/mbuf.h>
18 
19 extern int oc_cksum();
20 
21 /*
22  * Checksum routine for the Internet Protocol family.
23  *
24  * This isn't as bad as it looks.  For ip headers the "while" isn't
25  * executed and we just drop through to the return statement at the
26  * end.  For the usual tcp or udp packet (a single header mbuf
27  * chained onto a cluster of data, we make exactly one trip through
28  * the while (for the header mbuf) and never do the hairy code
29  * inside the "if".  If fact, if m_copydata & sb_compact are doing
30  * their job, we should never do the hairy code inside the "if".
31  */
32 in_cksum(m, len)
33 	register struct mbuf *m;
34 	register int len;
35 {
36 	register int sum = 0;
37 	register int i;
38 
39 	while (len > m->m_len) {
40 		sum = oc_cksum(mtod(m, u_char *), i = m->m_len, sum);
41 		m = m->m_next;
42 		len -= i;
43 		if (i & 1) {
44 			/*
45 			 * ouch - we ended on an odd byte with more
46 			 * to do.  This xfer is obviously not interested
47 			 * in performance so finish things slowly.
48 			 */
49 			register u_char *cp;
50 
51 			while (len > m->m_len) {
52 				cp = mtod(m, u_char *);
53 				if (i & 1) {
54 					i = m->m_len - 1;
55 					--len;
56 					sum += *cp++;
57 				} else
58 					i = m->m_len;
59 
60 				sum = oc_cksum(cp, i, sum);
61 				m = m->m_next;
62 				len -= i;
63 			}
64 			if (i & 1) {
65 				cp =  mtod(m, u_char *);
66 				sum += *cp++;
67 				return (0xffff & ~oc_cksum(cp, len - 1, sum));
68 			}
69 		}
70 	}
71 	return (0xffff & ~oc_cksum(mtod(m, u_char *), len, sum));
72 }
73