192b5cad9Scgd /*-
231bc9c50Slukem * Copyright (c) 1985, 1993 The Regents of the University of California.
331bc9c50Slukem * All rights reserved.
492b5cad9Scgd *
592b5cad9Scgd * Redistribution and use in source and binary forms, with or without
692b5cad9Scgd * modification, are permitted provided that the following conditions
792b5cad9Scgd * are met:
892b5cad9Scgd * 1. Redistributions of source code must retain the above copyright
992b5cad9Scgd * notice, this list of conditions and the following disclaimer.
1092b5cad9Scgd * 2. Redistributions in binary form must reproduce the above copyright
1192b5cad9Scgd * notice, this list of conditions and the following disclaimer in the
1292b5cad9Scgd * documentation and/or other materials provided with the distribution.
13326b2259Sagc * 3. Neither the name of the University nor the names of its contributors
1492b5cad9Scgd * may be used to endorse or promote products derived from this software
1592b5cad9Scgd * without specific prior written permission.
1692b5cad9Scgd *
1792b5cad9Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1892b5cad9Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1992b5cad9Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2092b5cad9Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2192b5cad9Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2292b5cad9Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2392b5cad9Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2492b5cad9Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2592b5cad9Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2692b5cad9Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2792b5cad9Scgd * SUCH DAMAGE.
2892b5cad9Scgd */
2992b5cad9Scgd
3031bc9c50Slukem #include <sys/cdefs.h>
3192b5cad9Scgd #ifndef lint
3231bc9c50Slukem #if 0
3331bc9c50Slukem static char sccsid[] = "@(#)cksum.c 5.2 (Berkeley) 5/11/93";
3431bc9c50Slukem #else
35*b0d54466Schristos __RCSID("$NetBSD: cksum.c,v 1.7 2007/05/17 00:36:31 christos Exp $");
3631bc9c50Slukem #endif
3792b5cad9Scgd #endif /* not lint */
3892b5cad9Scgd
3992b5cad9Scgd #include <sys/types.h>
4031bc9c50Slukem #include "globals.h"
4192b5cad9Scgd
4292b5cad9Scgd /*
4392b5cad9Scgd * I N _ C K S U M
4492b5cad9Scgd *
4592b5cad9Scgd * Checksum routine for Internet Protocol family headers (C Version)
4692b5cad9Scgd *
4792b5cad9Scgd * There is no profit in a specialized version of the checksum
4892b5cad9Scgd * function for any machine where int's are 32 bits and shorts are 16.
4992b5cad9Scgd *
5092b5cad9Scgd * All timed packets are smaller than 32K shorts, so there is no need to
5192b5cad9Scgd * worry about carries except at the end.
5292b5cad9Scgd */
5392b5cad9Scgd int
in_cksum(const void * data,int len)5407c9d403Scbiere in_cksum(const void *data, int len)
5592b5cad9Scgd {
5607c9d403Scbiere const u_char *addr = data;
579cdb3cafSperry int nleft = len;
5807c9d403Scbiere uint16_t answer;
599cdb3cafSperry int sum = 0;
6092b5cad9Scgd
6192b5cad9Scgd /*
6292b5cad9Scgd * Our algorithm is simple, using a 32 bit accumulator (sum),
6392b5cad9Scgd * we add sequential 16 bit words to it, and at the end, fold
6492b5cad9Scgd * back all the carry bits from the top 16 bits into the lower
6592b5cad9Scgd * 16 bits.
6692b5cad9Scgd */
6792b5cad9Scgd while (nleft > 1) {
6807c9d403Scbiere uint16_t w;
6907c9d403Scbiere
7007c9d403Scbiere memcpy(&w, addr, sizeof(w));
7107c9d403Scbiere sum += w;
7207c9d403Scbiere addr += 2;
7392b5cad9Scgd nleft -= 2;
7492b5cad9Scgd }
7592b5cad9Scgd
7692b5cad9Scgd /* mop up an odd byte, if necessary */
7792b5cad9Scgd if (nleft == 1)
7807c9d403Scbiere sum += *addr << 8;
7992b5cad9Scgd
8092b5cad9Scgd /*
8192b5cad9Scgd * add back carry outs from top 16 bits to low 16 bits
8292b5cad9Scgd */
8392b5cad9Scgd sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
8492b5cad9Scgd sum += (sum >> 16); /* add carry */
8592b5cad9Scgd answer = ~sum; /* truncate to 16 bits */
8692b5cad9Scgd return (answer);
8792b5cad9Scgd }
88