1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * 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 Laboratories. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)in_cksum.c 7.2 (Berkeley) 07/21/92 17 * 18 * from: $Header: in_cksum.c,v 1.6 92/06/17 05:22:04 torek Exp $ 19 */ 20 21 #include "param.h" 22 #include "mbuf.h" 23 #include "netinet/in.h" 24 #include "netinet/in_systm.h" 25 26 /* 27 * Checksum routine for Internet Protocol family headers. 28 * This routine is very heavily used in the network 29 * code and should be modified for each CPU to be as fast as possible. 30 * In particular, it should not be this one. 31 */ 32 int 33 in_cksum(m, len) 34 register struct mbuf *m; 35 register int len; 36 { 37 register int sum = 0, i, oddbyte = 0, v = 0; 38 register u_char *cp; 39 40 /* we assume < 2^16 bytes being summed */ 41 while (len) { 42 while ((i = m->m_len) == 0) 43 m = m->m_next; 44 if (i > len) 45 i = len; 46 len -= i; 47 cp = mtod(m, u_char *); 48 if (oddbyte) { 49 sum += v + *cp++; 50 i--; 51 } 52 if (((int)cp & 1) == 0) { 53 while ((i -= 2) >= 0) { 54 sum += *(u_short *)cp; 55 cp += 2; 56 } 57 } else { 58 while ((i -= 2) >= 0) { 59 sum += *cp++ << 8; 60 sum += *cp++; 61 } 62 } 63 if ((oddbyte = i & 1) != 0) 64 v = *cp << 8; 65 m = m->m_next; 66 } 67 if (oddbyte) 68 sum += v; 69 sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */ 70 sum += sum >> 16; /* add potential last carry */ 71 return (0xffff & ~sum); 72 } 73