Annotation of sys/netinet/in4_cksum.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: in4_cksum.c,v 1.7 2003/06/02 23:28:13 millert Exp $ */
! 2: /* $KAME: in4_cksum.c,v 1.10 2001/11/30 10:06:15 itojun Exp $ */
! 3: /* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */
! 4:
! 5: /*
! 6: * Copyright (C) 1999 WIDE Project.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. Neither the name of the project nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: /*
! 35: * Copyright (c) 1988, 1992, 1993
! 36: * The Regents of the University of California. All rights reserved.
! 37: *
! 38: * Redistribution and use in source and binary forms, with or without
! 39: * modification, are permitted provided that the following conditions
! 40: * are met:
! 41: * 1. Redistributions of source code must retain the above copyright
! 42: * notice, this list of conditions and the following disclaimer.
! 43: * 2. Redistributions in binary form must reproduce the above copyright
! 44: * notice, this list of conditions and the following disclaimer in the
! 45: * documentation and/or other materials provided with the distribution.
! 46: * 3. Neither the name of the University nor the names of its contributors
! 47: * may be used to endorse or promote products derived from this software
! 48: * without specific prior written permission.
! 49: *
! 50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 60: * SUCH DAMAGE.
! 61: *
! 62: * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
! 63: */
! 64:
! 65: #include <sys/param.h>
! 66: #include <sys/mbuf.h>
! 67: #include <sys/systm.h>
! 68: #include <sys/socket.h>
! 69: #include <net/route.h>
! 70: #include <netinet/in.h>
! 71: #include <netinet/in_systm.h>
! 72: #include <netinet/ip.h>
! 73: #include <netinet/ip_var.h>
! 74:
! 75: /*
! 76: * Checksum routine for Internet Protocol family headers (Portable Version).
! 77: * This is only for IPv4 pseudo header checksum.
! 78: * No need to clear non-pseudo-header fields in IPv4 header.
! 79: * len is for actual payload size, and does not include IPv4 header and
! 80: * skipped header chain (off + len should be equal to the whole packet).
! 81: *
! 82: * This routine is very heavily used in the network
! 83: * code and should be modified for each CPU to be as fast as possible.
! 84: */
! 85:
! 86: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
! 87: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
! 88:
! 89: int
! 90: in4_cksum(m, nxt, off, len)
! 91: struct mbuf *m;
! 92: u_int8_t nxt;
! 93: int off, len;
! 94: {
! 95: u_int16_t *w;
! 96: int sum = 0;
! 97: int mlen = 0;
! 98: int byte_swapped = 0;
! 99: union {
! 100: struct ipovly ipov;
! 101: u_int16_t w[10];
! 102: } u;
! 103: union {
! 104: u_int8_t c[2];
! 105: u_int16_t s;
! 106: } s_util;
! 107: union {
! 108: u_int16_t s[2];
! 109: u_int32_t l;
! 110: } l_util;
! 111:
! 112: if (nxt != 0) {
! 113: /* pseudo header */
! 114: if (off < sizeof(struct ipovly))
! 115: panic("in4_cksum: offset too short");
! 116: if (m->m_len < sizeof(struct ip))
! 117: panic("in4_cksum: bad mbuf chain");
! 118: bzero(&u.ipov, sizeof(u.ipov));
! 119: u.ipov.ih_len = htons(len);
! 120: u.ipov.ih_pr = nxt;
! 121: u.ipov.ih_src = mtod(m, struct ip *)->ip_src;
! 122: u.ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
! 123: w = u.w;
! 124: /* assumes sizeof(ipov) == 20 */
! 125: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4];
! 126: sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9];
! 127: }
! 128:
! 129: /* skip unnecessary part */
! 130: while (m && off > 0) {
! 131: if (m->m_len > off)
! 132: break;
! 133: off -= m->m_len;
! 134: m = m->m_next;
! 135: }
! 136:
! 137: for (;m && len; m = m->m_next) {
! 138: if (m->m_len == 0)
! 139: continue;
! 140: w = (u_int16_t *)(mtod(m, caddr_t) + off);
! 141: if (mlen == -1) {
! 142: /*
! 143: * The first byte of this mbuf is the continuation
! 144: * of a word spanning between this mbuf and the
! 145: * last mbuf.
! 146: *
! 147: * s_util.c[0] is already saved when scanning previous
! 148: * mbuf.
! 149: */
! 150: s_util.c[1] = *(u_int8_t *)w;
! 151: sum += s_util.s;
! 152: w = (u_int16_t *)((u_int8_t *)w + 1);
! 153: mlen = m->m_len - off - 1;
! 154: len--;
! 155: } else
! 156: mlen = m->m_len - off;
! 157: off = 0;
! 158: if (len < mlen)
! 159: mlen = len;
! 160: len -= mlen;
! 161: /*
! 162: * Force to even boundary.
! 163: */
! 164: if ((1 & (long) w) && (mlen > 0)) {
! 165: REDUCE;
! 166: sum <<= 8;
! 167: s_util.c[0] = *(u_int8_t *)w;
! 168: w = (u_int16_t *)((int8_t *)w + 1);
! 169: mlen--;
! 170: byte_swapped = 1;
! 171: }
! 172: /*
! 173: * Unroll the loop to make overhead from
! 174: * branches &c small.
! 175: */
! 176: while ((mlen -= 32) >= 0) {
! 177: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 178: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
! 179: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
! 180: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
! 181: w += 16;
! 182: }
! 183: mlen += 32;
! 184: while ((mlen -= 8) >= 0) {
! 185: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 186: w += 4;
! 187: }
! 188: mlen += 8;
! 189: if (mlen == 0 && byte_swapped == 0)
! 190: continue;
! 191: REDUCE;
! 192: while ((mlen -= 2) >= 0) {
! 193: sum += *w++;
! 194: }
! 195: if (byte_swapped) {
! 196: REDUCE;
! 197: sum <<= 8;
! 198: byte_swapped = 0;
! 199: if (mlen == -1) {
! 200: s_util.c[1] = *(u_int8_t *)w;
! 201: sum += s_util.s;
! 202: mlen = 0;
! 203: } else
! 204: mlen = -1;
! 205: } else if (mlen == -1)
! 206: s_util.c[0] = *(u_int8_t *)w;
! 207: }
! 208: if (len)
! 209: printf("cksum4: out of data\n");
! 210: if (mlen == -1) {
! 211: /* The last mbuf has odd # of bytes. Follow the
! 212: standard (the odd byte may be shifted left by 8 bits
! 213: or not as determined by endian-ness of the machine) */
! 214: s_util.c[1] = 0;
! 215: sum += s_util.s;
! 216: }
! 217: REDUCE;
! 218: return (~sum & 0xffff);
! 219: }
CVSweb