xref: /netbsd/usr.sbin/timed/timed/cksum.c (revision b0d54466)
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