191449f87Storek /*
2*304a8d6dSbostic * Copyright (c) 1992, 1993
3*304a8d6dSbostic * The Regents of the University of California. All rights reserved.
491449f87Storek *
591449f87Storek * This software was developed by the Computer Systems Engineering group
691449f87Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
791449f87Storek * contributed to Berkeley.
891449f87Storek *
983548bb1Sbostic * All advertising materials mentioning features or use of this software
1083548bb1Sbostic * must display the following acknowledgement:
1183548bb1Sbostic * This product includes software developed by the University of
12bf37ff33Storek * California, Lawrence Berkeley Laboratory.
1383548bb1Sbostic *
1491449f87Storek * %sccs.include.redist.c%
1591449f87Storek *
16*304a8d6dSbostic * @(#)in_cksum.c 8.1 (Berkeley) 06/11/93
1791449f87Storek *
18bf37ff33Storek * from: $Header: in_cksum.c,v 1.7 92/11/26 03:04:52 torek Exp $
1991449f87Storek */
2091449f87Storek
21a159b5e1Sbostic #include <sys/param.h>
22a159b5e1Sbostic #include <sys/mbuf.h>
23a159b5e1Sbostic
24a159b5e1Sbostic #include <netinet/in.h>
25a159b5e1Sbostic #include <netinet/in_systm.h>
2691449f87Storek
2791449f87Storek /*
2891449f87Storek * Checksum routine for Internet Protocol family headers.
2991449f87Storek * This routine is very heavily used in the network
3091449f87Storek * code and should be modified for each CPU to be as fast as possible.
3191449f87Storek * In particular, it should not be this one.
3291449f87Storek */
3391449f87Storek int
in_cksum(m,len)3491449f87Storek in_cksum(m, len)
3591449f87Storek register struct mbuf *m;
3691449f87Storek register int len;
3791449f87Storek {
3891449f87Storek register int sum = 0, i, oddbyte = 0, v = 0;
3991449f87Storek register u_char *cp;
4091449f87Storek
4191449f87Storek /* we assume < 2^16 bytes being summed */
4291449f87Storek while (len) {
4391449f87Storek while ((i = m->m_len) == 0)
4491449f87Storek m = m->m_next;
4591449f87Storek if (i > len)
4691449f87Storek i = len;
4791449f87Storek len -= i;
4891449f87Storek cp = mtod(m, u_char *);
4991449f87Storek if (oddbyte) {
5091449f87Storek sum += v + *cp++;
5191449f87Storek i--;
5291449f87Storek }
5391449f87Storek if (((int)cp & 1) == 0) {
5491449f87Storek while ((i -= 2) >= 0) {
5591449f87Storek sum += *(u_short *)cp;
5691449f87Storek cp += 2;
5791449f87Storek }
5891449f87Storek } else {
5991449f87Storek while ((i -= 2) >= 0) {
6091449f87Storek sum += *cp++ << 8;
6191449f87Storek sum += *cp++;
6291449f87Storek }
6391449f87Storek }
6491449f87Storek if ((oddbyte = i & 1) != 0)
6591449f87Storek v = *cp << 8;
6691449f87Storek m = m->m_next;
6791449f87Storek }
6891449f87Storek if (oddbyte)
6991449f87Storek sum += v;
7091449f87Storek sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
7191449f87Storek sum += sum >> 16; /* add potential last carry */
7291449f87Storek return (0xffff & ~sum);
7391449f87Storek }
74