ipx_cksum.c revision 139823
1139823Simp/*-
211819Sjulian * Copyright (c) 1995, Mike Mitchell
311819Sjulian * Copyright (c) 1982, 1992, 1993
411819Sjulian *	The Regents of the University of California.  All rights reserved.
511819Sjulian *
611819Sjulian * Redistribution and use in source and binary forms, with or without
711819Sjulian * modification, are permitted provided that the following conditions
811819Sjulian * are met:
911819Sjulian * 1. Redistributions of source code must retain the above copyright
1011819Sjulian *    notice, this list of conditions and the following disclaimer.
1111819Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1211819Sjulian *    notice, this list of conditions and the following disclaimer in the
1311819Sjulian *    documentation and/or other materials provided with the distribution.
1411819Sjulian * 3. All advertising materials mentioning features or use of this software
1511819Sjulian *    must display the following acknowledgement:
1611819Sjulian *	This product includes software developed by the University of
1711819Sjulian *	California, Berkeley and its contributors.
1811819Sjulian * 4. Neither the name of the University nor the names of its contributors
1911819Sjulian *    may be used to endorse or promote products derived from this software
2011819Sjulian *    without specific prior written permission.
2111819Sjulian *
2211819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2311819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2411819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2511819Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2611819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2711819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2811819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2911819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3011819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3111819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3211819Sjulian * SUCH DAMAGE.
3311819Sjulian *
3412057Sjulian *	@(#)ipx_cksum.c
3511819Sjulian */
3611819Sjulian
37116189Sobrien#include <sys/cdefs.h>
38116189Sobrien__FBSDID("$FreeBSD: head/sys/netipx/ipx_cksum.c 139823 2005-01-07 01:45:51Z imp $");
39116189Sobrien
4011819Sjulian#include <sys/param.h>
4111819Sjulian#include <sys/mbuf.h>
4250519Sjhay#include <sys/libkern.h>
4311819Sjulian
4450519Sjhay#include <netipx/ipx.h>
4525652Sjhay#include <netipx/ipx_var.h>
4611991Sjulian
4711819Sjulian
4850519Sjhay#define SUMADV	sum += *w++
4911819Sjulian
5011819Sjulianu_short
5150519Sjhayipx_cksum(struct mbuf *m, int len) {
5250519Sjhay	u_int32_t sum = 0;
53132779Skan	u_char *w;
5450519Sjhay	u_char oldtc;
5550519Sjhay	int mlen, words;
5650519Sjhay	struct ipx *ipx;
5711819Sjulian	union {
5850519Sjhay		u_char	b[2];
5950519Sjhay		u_short	w;
6050519Sjhay	} buf;
6111819Sjulian
6250519Sjhay	ipx = mtod(m, struct ipx*);
6350519Sjhay	oldtc = ipx->ipx_tc;
6450519Sjhay	ipx->ipx_tc = 0;
65132779Skan	w = (u_char *)&ipx->ipx_len;
6650519Sjhay	len -= 2;
6750519Sjhay	mlen = 2;
6850519Sjhay
6950519Sjhay	for(;;) {
7050519Sjhay		mlen = imin(m->m_len - mlen, len);
7150519Sjhay		words = mlen / 2;
7250519Sjhay		len -= mlen & ~1;
7350519Sjhay		while (words >= 16) {
7450519Sjhay			SUMADV;	SUMADV;	SUMADV;	SUMADV;
7550519Sjhay			SUMADV;	SUMADV;	SUMADV;	SUMADV;
7650519Sjhay			SUMADV;	SUMADV;	SUMADV;	SUMADV;
7750519Sjhay			SUMADV;	SUMADV;	SUMADV;	SUMADV;
7850519Sjhay			words -= 16;
7911819Sjulian		}
8050519Sjhay		while (words--)
8150519Sjhay			SUMADV;
8250519Sjhay		if (len == 0)
8350519Sjhay			break;
8450519Sjhay		mlen &= 1;
8550519Sjhay		if (mlen) {
86132779Skan			buf.b[0] = *w;
8750519Sjhay			if (--len == 0) {
8850519Sjhay				buf.b[1] = 0;
8950519Sjhay				sum += buf.w;
9050519Sjhay				break;
9150519Sjhay			}
9211819Sjulian		}
9350519Sjhay		m = m->m_next;
9450519Sjhay		if (m == NULL)
9550519Sjhay			break;
96132779Skan		w = mtod(m, u_char *);
9750519Sjhay		if (mlen) {
98132779Skan			buf.b[1] = *w;
9950519Sjhay			sum += buf.w;
100132779Skan			w++;
10150519Sjhay			if (--len == 0)
10250519Sjhay				break;
103139584Srwatson		}
10411819Sjulian	}
10550519Sjhay
10650519Sjhay	ipx->ipx_tc = oldtc;
10750519Sjhay
10850519Sjhay	sum = (sum & 0xffff) + (sum >> 16);
10950519Sjhay	if (sum >= 0x10000)
11050519Sjhay		sum++;
11150519Sjhay	if (sum)
11250519Sjhay		sum = ~sum;
11311819Sjulian	return (sum);
11411819Sjulian}
115