[BACK]Return to in6_cksum.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Annotation of src/sys/netinet6/in6_cksum.c, Revision 1.7

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

CVSweb <webmaster@jp.NetBSD.org>