1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)in_cksum.c 8.1 (Berkeley) 06/11/93 17 * 18 * from: $Header: in_cksum.c,v 1.7 92/11/26 03:04:52 torek Exp $ 19 */ 20 21 #include <sys/param.h> 22 #include <sys/mbuf.h> 23 24 #include <netinet/in.h> 25 #include <netinet/in_systm.h> 26 27 /* 28 * Checksum routine for Internet Protocol family headers. 29 * This routine is very heavily used in the network 30 * code and should be modified for each CPU to be as fast as possible. 31 * In particular, it should not be this one. 32 */ 33 int 34 in_cksum(m, len) 35 register struct mbuf *m; 36 register int len; 37 { 38 register int sum = 0, i, oddbyte = 0, v = 0; 39 register u_char *cp; 40 41 /* we assume < 2^16 bytes being summed */ 42 while (len) { 43 while ((i = m->m_len) == 0) 44 m = m->m_next; 45 if (i > len) 46 i = len; 47 len -= i; 48 cp = mtod(m, u_char *); 49 if (oddbyte) { 50 sum += v + *cp++; 51 i--; 52 } 53 if (((int)cp & 1) == 0) { 54 while ((i -= 2) >= 0) { 55 sum += *(u_short *)cp; 56 cp += 2; 57 } 58 } else { 59 while ((i -= 2) >= 0) { 60 sum += *cp++ << 8; 61 sum += *cp++; 62 } 63 } 64 if ((oddbyte = i & 1) != 0) 65 v = *cp << 8; 66 m = m->m_next; 67 } 68 if (oddbyte) 69 sum += v; 70 sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */ 71 sum += sum >> 16; /* add potential last carry */ 72 return (0xffff & ~sum); 73 } 74