Home | History | Annotate | Line # | Download | only in netinet
in_cksum.c revision 1.14.8.2
      1  1.14.8.2  jdolecek /*	$NetBSD: in_cksum.c,v 1.14.8.2 2002/06/23 17:50:43 jdolecek Exp $	*/
      2       1.9       cgd 
      3       1.1       cgd /*
      4       1.8   mycroft  * Copyright (c) 1988, 1992, 1993
      5       1.8   mycroft  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15       1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16       1.1       cgd  *    must display the following acknowledgement:
     17       1.1       cgd  *	This product includes software developed by the University of
     18       1.1       cgd  *	California, Berkeley and its contributors.
     19       1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20       1.1       cgd  *    may be used to endorse or promote products derived from this software
     21       1.1       cgd  *    without specific prior written permission.
     22       1.1       cgd  *
     23       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33       1.1       cgd  * SUCH DAMAGE.
     34       1.1       cgd  *
     35       1.9       cgd  *	@(#)in_cksum.c	8.1 (Berkeley) 6/10/93
     36       1.1       cgd  */
     37  1.14.8.1   thorpej 
     38  1.14.8.1   thorpej #include <sys/cdefs.h>
     39  1.14.8.2  jdolecek __KERNEL_RCSID(0, "$NetBSD: in_cksum.c,v 1.14.8.2 2002/06/23 17:50:43 jdolecek Exp $");
     40       1.1       cgd 
     41       1.7   mycroft #include <sys/param.h>
     42       1.4   mycroft #include <sys/mbuf.h>
     43      1.11  jonathan #include <sys/systm.h>
     44      1.11  jonathan #include <netinet/in.h>
     45       1.1       cgd 
     46       1.1       cgd /*
     47       1.1       cgd  * Checksum routine for Internet Protocol family headers (Portable Version).
     48       1.1       cgd  *
     49       1.1       cgd  * This routine is very heavily used in the network
     50       1.1       cgd  * code and should be modified for each CPU to be as fast as possible.
     51       1.1       cgd  */
     52       1.1       cgd 
     53       1.8   mycroft #define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
     54       1.8   mycroft #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
     55       1.1       cgd 
     56       1.6   mycroft int
     57       1.7   mycroft in_cksum(m, len)
     58      1.14  augustss 	struct mbuf *m;
     59      1.14  augustss 	int len;
     60       1.1       cgd {
     61      1.14  augustss 	u_int16_t *w;
     62      1.14  augustss 	int sum = 0;
     63      1.14  augustss 	int mlen = 0;
     64       1.1       cgd 	int byte_swapped = 0;
     65       1.1       cgd 
     66       1.1       cgd 	union {
     67      1.10       cgd 		u_int8_t  c[2];
     68      1.10       cgd 		u_int16_t s;
     69       1.1       cgd 	} s_util;
     70       1.1       cgd 	union {
     71      1.10       cgd 		u_int16_t s[2];
     72      1.10       cgd 		u_int32_t l;
     73       1.1       cgd 	} l_util;
     74       1.1       cgd 
     75       1.1       cgd 	for (;m && len; m = m->m_next) {
     76       1.1       cgd 		if (m->m_len == 0)
     77       1.1       cgd 			continue;
     78      1.10       cgd 		w = mtod(m, u_int16_t *);
     79       1.1       cgd 		if (mlen == -1) {
     80       1.1       cgd 			/*
     81       1.1       cgd 			 * The first byte of this mbuf is the continuation
     82       1.1       cgd 			 * of a word spanning between this mbuf and the
     83       1.1       cgd 			 * last mbuf.
     84       1.1       cgd 			 *
     85  1.14.8.2  jdolecek 			 * s_util.c[0] is already saved when scanning previous
     86       1.1       cgd 			 * mbuf.
     87       1.1       cgd 			 */
     88      1.10       cgd 			s_util.c[1] = *(u_int8_t *)w;
     89       1.1       cgd 			sum += s_util.s;
     90      1.10       cgd 			w = (u_int16_t *)((u_int8_t *)w + 1);
     91       1.1       cgd 			mlen = m->m_len - 1;
     92       1.1       cgd 			len--;
     93       1.1       cgd 		} else
     94       1.1       cgd 			mlen = m->m_len;
     95       1.1       cgd 		if (len < mlen)
     96       1.1       cgd 			mlen = len;
     97       1.1       cgd 		len -= mlen;
     98       1.1       cgd 		/*
     99       1.1       cgd 		 * Force to even boundary.
    100       1.1       cgd 		 */
    101      1.10       cgd 		if ((1 & (long) w) && (mlen > 0)) {
    102       1.1       cgd 			REDUCE;
    103       1.1       cgd 			sum <<= 8;
    104      1.10       cgd 			s_util.c[0] = *(u_int8_t *)w;
    105      1.10       cgd 			w = (u_int16_t *)((int8_t *)w + 1);
    106       1.1       cgd 			mlen--;
    107       1.1       cgd 			byte_swapped = 1;
    108       1.1       cgd 		}
    109       1.1       cgd 		/*
    110       1.1       cgd 		 * Unroll the loop to make overhead from
    111       1.1       cgd 		 * branches &c small.
    112       1.1       cgd 		 */
    113       1.1       cgd 		while ((mlen -= 32) >= 0) {
    114       1.1       cgd 			sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
    115       1.1       cgd 			sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
    116       1.1       cgd 			sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
    117       1.1       cgd 			sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
    118       1.1       cgd 			w += 16;
    119       1.1       cgd 		}
    120       1.1       cgd 		mlen += 32;
    121       1.1       cgd 		while ((mlen -= 8) >= 0) {
    122       1.1       cgd 			sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
    123       1.1       cgd 			w += 4;
    124       1.1       cgd 		}
    125       1.1       cgd 		mlen += 8;
    126       1.1       cgd 		if (mlen == 0 && byte_swapped == 0)
    127       1.1       cgd 			continue;
    128       1.1       cgd 		REDUCE;
    129       1.1       cgd 		while ((mlen -= 2) >= 0) {
    130       1.1       cgd 			sum += *w++;
    131       1.1       cgd 		}
    132       1.1       cgd 		if (byte_swapped) {
    133       1.1       cgd 			REDUCE;
    134       1.1       cgd 			sum <<= 8;
    135       1.1       cgd 			byte_swapped = 0;
    136       1.1       cgd 			if (mlen == -1) {
    137      1.10       cgd 				s_util.c[1] = *(u_int8_t *)w;
    138       1.1       cgd 				sum += s_util.s;
    139       1.1       cgd 				mlen = 0;
    140       1.1       cgd 			} else
    141       1.1       cgd 				mlen = -1;
    142       1.1       cgd 		} else if (mlen == -1)
    143      1.10       cgd 			s_util.c[0] = *(u_int8_t *)w;
    144       1.1       cgd 	}
    145       1.1       cgd 	if (len)
    146      1.13  christos 		printf("cksum: out of data\n");
    147       1.1       cgd 	if (mlen == -1) {
    148       1.1       cgd 		/* The last mbuf has odd # of bytes. Follow the
    149       1.1       cgd 		   standard (the odd byte may be shifted left by 8 bits
    150       1.1       cgd 		   or not as determined by endian-ness of the machine) */
    151       1.1       cgd 		s_util.c[1] = 0;
    152       1.1       cgd 		sum += s_util.s;
    153       1.1       cgd 	}
    154       1.1       cgd 	REDUCE;
    155       1.1       cgd 	return (~sum & 0xffff);
    156       1.1       cgd }
    157