Annotation of sys/netinet6/in6_cksum.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: in6_cksum.c,v 1.14 2006/11/17 01:11:23 itojun Exp $ */
! 2: /* $KAME: in6_cksum.c,v 1.10 2000/12/03 00:53:59 itojun Exp $ */
! 3:
! 4: /*
! 5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. Neither the name of the project nor the names of its contributors
! 17: * may be used to endorse or promote products derived from this software
! 18: * without specific prior written permission.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 30: * SUCH DAMAGE.
! 31: */
! 32:
! 33: /*
! 34: * Copyright (c) 1988, 1992, 1993
! 35: * The Regents of the University of California. All rights reserved.
! 36: *
! 37: * Redistribution and use in source and binary forms, with or without
! 38: * modification, are permitted provided that the following conditions
! 39: * are met:
! 40: * 1. Redistributions of source code must retain the above copyright
! 41: * notice, this list of conditions and the following disclaimer.
! 42: * 2. Redistributions in binary form must reproduce the above copyright
! 43: * notice, this list of conditions and the following disclaimer in the
! 44: * documentation and/or other materials provided with the distribution.
! 45: * 3. Neither the name of the University nor the names of its contributors
! 46: * may be used to endorse or promote products derived from this software
! 47: * without specific prior written permission.
! 48: *
! 49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 59: * SUCH DAMAGE.
! 60: *
! 61: * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
! 62: */
! 63:
! 64: #include <sys/param.h>
! 65: #include <sys/mbuf.h>
! 66: #include <sys/systm.h>
! 67: #include <netinet/in.h>
! 68: #include <netinet/ip6.h>
! 69:
! 70: /*
! 71: * Checksum routine for Internet Protocol family headers (Portable Version).
! 72: *
! 73: * This routine is very heavily used in the network
! 74: * code and should be modified for each CPU to be as fast as possible.
! 75: */
! 76:
! 77: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
! 78: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
! 79:
! 80: /*
! 81: * m MUST contain a continuous IP6 header.
! 82: * off is a offset where TCP/UDP/ICMP6 header starts.
! 83: * len is a total length of a transport segment.
! 84: * (e.g. TCP header + TCP payload)
! 85: */
! 86:
! 87: int
! 88: in6_cksum(m, nxt, off, len)
! 89: struct mbuf *m;
! 90: u_int8_t nxt;
! 91: u_int32_t off, len;
! 92: {
! 93: u_int16_t *w;
! 94: int sum = 0;
! 95: int mlen = 0;
! 96: int byte_swapped = 0;
! 97: struct ip6_hdr *ip6;
! 98: union {
! 99: u_int16_t phs[4];
! 100: struct {
! 101: u_int32_t ph_len;
! 102: u_int8_t ph_zero[3];
! 103: u_int8_t ph_nxt;
! 104: } ph __packed;
! 105: } uph;
! 106: union {
! 107: u_int8_t c[2];
! 108: u_int16_t s;
! 109: } s_util;
! 110: union {
! 111: u_int16_t s[2];
! 112: u_int32_t l;
! 113: } l_util;
! 114:
! 115: /* sanity check */
! 116: if (m->m_pkthdr.len < off + len) {
! 117: panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)",
! 118: m->m_pkthdr.len, off, len);
! 119: }
! 120:
! 121: bzero(&uph, sizeof(uph));
! 122:
! 123: /*
! 124: * First create IP6 pseudo header and calculate a summary.
! 125: */
! 126: ip6 = mtod(m, struct ip6_hdr *);
! 127: w = (u_int16_t *)&ip6->ip6_src;
! 128: uph.ph.ph_len = htonl(len);
! 129: uph.ph.ph_nxt = nxt;
! 130:
! 131: /* IPv6 source address */
! 132: sum += w[0];
! 133: if (!IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
! 134: sum += w[1];
! 135: sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
! 136: sum += w[6]; sum += w[7];
! 137: /* IPv6 destination address */
! 138: sum += w[8];
! 139: if (!IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
! 140: sum += w[9];
! 141: sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13];
! 142: sum += w[14]; sum += w[15];
! 143: /* Payload length and upper layer identifier */
! 144: sum += uph.phs[0]; sum += uph.phs[1];
! 145: sum += uph.phs[2]; sum += uph.phs[3];
! 146:
! 147: /*
! 148: * Secondly calculate a summary of the first mbuf excluding offset.
! 149: */
! 150: while (m != NULL && off > 0) {
! 151: if (m->m_len <= off)
! 152: off -= m->m_len;
! 153: else
! 154: break;
! 155: m = m->m_next;
! 156: }
! 157: w = (u_int16_t *)(mtod(m, u_char *) + off);
! 158: mlen = m->m_len - off;
! 159: if (len < mlen)
! 160: mlen = len;
! 161: len -= mlen;
! 162: /*
! 163: * Force to even boundary.
! 164: */
! 165: if ((1 & (long) w) && (mlen > 0)) {
! 166: REDUCE;
! 167: sum <<= 8;
! 168: s_util.c[0] = *(u_char *)w;
! 169: w = (u_int16_t *)((char *)w + 1);
! 170: mlen--;
! 171: byte_swapped = 1;
! 172: }
! 173: /*
! 174: * Unroll the loop to make overhead from
! 175: * branches &c small.
! 176: */
! 177: while ((mlen -= 32) >= 0) {
! 178: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 179: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
! 180: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
! 181: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
! 182: w += 16;
! 183: }
! 184: mlen += 32;
! 185: while ((mlen -= 8) >= 0) {
! 186: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 187: w += 4;
! 188: }
! 189: mlen += 8;
! 190: if (mlen == 0 && byte_swapped == 0)
! 191: goto next;
! 192: REDUCE;
! 193: while ((mlen -= 2) >= 0) {
! 194: sum += *w++;
! 195: }
! 196: if (byte_swapped) {
! 197: REDUCE;
! 198: sum <<= 8;
! 199: byte_swapped = 0;
! 200: if (mlen == -1) {
! 201: s_util.c[1] = *(char *)w;
! 202: sum += s_util.s;
! 203: mlen = 0;
! 204: } else
! 205: mlen = -1;
! 206: } else if (mlen == -1)
! 207: s_util.c[0] = *(char *)w;
! 208: next:
! 209: m = m->m_next;
! 210:
! 211: /*
! 212: * Lastly calculate a summary of the rest of mbufs.
! 213: */
! 214:
! 215: for (;m && len; m = m->m_next) {
! 216: if (m->m_len == 0)
! 217: continue;
! 218: w = mtod(m, u_int16_t *);
! 219: if (mlen == -1) {
! 220: /*
! 221: * The first byte of this mbuf is the continuation
! 222: * of a word spanning between this mbuf and the
! 223: * last mbuf.
! 224: *
! 225: * s_util.c[0] is already saved when scanning previous
! 226: * mbuf.
! 227: */
! 228: s_util.c[1] = *(char *)w;
! 229: sum += s_util.s;
! 230: w = (u_int16_t *)((char *)w + 1);
! 231: mlen = m->m_len - 1;
! 232: len--;
! 233: } else
! 234: mlen = m->m_len;
! 235: if (len < mlen)
! 236: mlen = len;
! 237: len -= mlen;
! 238: /*
! 239: * Force to even boundary.
! 240: */
! 241: if ((1 & (long) w) && (mlen > 0)) {
! 242: REDUCE;
! 243: sum <<= 8;
! 244: s_util.c[0] = *(u_char *)w;
! 245: w = (u_int16_t *)((char *)w + 1);
! 246: mlen--;
! 247: byte_swapped = 1;
! 248: }
! 249: /*
! 250: * Unroll the loop to make overhead from
! 251: * branches &c small.
! 252: */
! 253: while ((mlen -= 32) >= 0) {
! 254: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 255: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
! 256: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
! 257: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
! 258: w += 16;
! 259: }
! 260: mlen += 32;
! 261: while ((mlen -= 8) >= 0) {
! 262: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 263: w += 4;
! 264: }
! 265: mlen += 8;
! 266: if (mlen == 0 && byte_swapped == 0)
! 267: continue;
! 268: REDUCE;
! 269: while ((mlen -= 2) >= 0) {
! 270: sum += *w++;
! 271: }
! 272: if (byte_swapped) {
! 273: REDUCE;
! 274: sum <<= 8;
! 275: byte_swapped = 0;
! 276: if (mlen == -1) {
! 277: s_util.c[1] = *(char *)w;
! 278: sum += s_util.s;
! 279: mlen = 0;
! 280: } else
! 281: mlen = -1;
! 282: } else if (mlen == -1)
! 283: s_util.c[0] = *(char *)w;
! 284: }
! 285: if (len)
! 286: panic("in6_cksum: out of data");
! 287: if (mlen == -1) {
! 288: /* The last mbuf has odd # of bytes. Follow the
! 289: standard (the odd byte may be shifted left by 8 bits
! 290: or not as determined by endian-ness of the machine) */
! 291: s_util.c[1] = 0;
! 292: sum += s_util.s;
! 293: }
! 294: REDUCE;
! 295: return (~sum & 0xffff);
! 296: }
CVSweb