LCOV - code coverage report
Current view: top level - netinet6 - in6_cksum.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 108 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: in6_cksum.c,v 1.17 2015/06/08 22:19:28 krw 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           0 : in6_cksum(struct mbuf *m, u_int8_t nxt, u_int32_t off, u_int32_t len)
      89             : {
      90             :         u_int16_t *w;
      91             :         int sum = 0;
      92             :         int mlen = 0;
      93             :         int byte_swapped = 0;
      94             :         struct ip6_hdr *ip6;
      95             :         union {
      96             :                 u_int16_t phs[4];
      97             :                 struct {
      98             :                         u_int32_t       ph_len;
      99             :                         u_int8_t        ph_zero[3];
     100             :                         u_int8_t        ph_nxt;
     101             :                 } ph __packed;
     102             :         } uph;
     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             :         /* sanity check */
     113           0 :         if (m->m_pkthdr.len < off + len) {
     114           0 :                 panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)",
     115             :                         m->m_pkthdr.len, off, len);
     116             :         }
     117             : 
     118             :         /* Skip pseudo-header if nxt == 0. */
     119           0 :         if (nxt == 0)
     120             :                  goto skip_phdr;
     121             : 
     122             :         bzero(&uph, sizeof(uph));
     123             : 
     124             :         /*
     125             :          * First create IP6 pseudo header and calculate a summary.
     126             :          */
     127           0 :         ip6 = mtod(m, struct ip6_hdr *);
     128           0 :         w = (u_int16_t *)&ip6->ip6_src;
     129           0 :         uph.ph.ph_len = htonl(len);
     130           0 :         uph.ph.ph_nxt = nxt;
     131             : 
     132             :         /* IPv6 source address */
     133           0 :         sum += w[0];
     134           0 :         if (!IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
     135           0 :                 sum += w[1];
     136           0 :         sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
     137           0 :         sum += w[6]; sum += w[7];
     138             :         /* IPv6 destination address */
     139           0 :         sum += w[8];
     140           0 :         if (!IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
     141           0 :                 sum += w[9];
     142           0 :         sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13];
     143           0 :         sum += w[14]; sum += w[15];
     144             :         /* Payload length and upper layer identifier */
     145           0 :         sum += uph.phs[0];  sum += uph.phs[1];
     146           0 :         sum += uph.phs[2];  sum += uph.phs[3];
     147             : 
     148             : skip_phdr:
     149             :         /*
     150             :          * Secondly calculate a summary of the first mbuf excluding offset.
     151             :          */
     152           0 :         while (m != NULL && off > 0) {
     153           0 :                 if (m->m_len <= off)
     154           0 :                         off -= m->m_len;
     155             :                 else
     156             :                         break;
     157           0 :                 m = m->m_next;
     158             :         }
     159           0 :         w = (u_int16_t *)(mtod(m, u_char *) + off);
     160           0 :         mlen = m->m_len - off;
     161           0 :         if (len < mlen)
     162           0 :                 mlen = len;
     163           0 :         len -= mlen;
     164             :         /*
     165             :          * Force to even boundary.
     166             :          */
     167           0 :         if ((1 & (long) w) && (mlen > 0)) {
     168           0 :                 REDUCE;
     169           0 :                 sum <<= 8;
     170           0 :                 s_util.c[0] = *(u_char *)w;
     171           0 :                 w = (u_int16_t *)((char *)w + 1);
     172           0 :                 mlen--;
     173             :                 byte_swapped = 1;
     174           0 :         }
     175             :         /*
     176             :          * Unroll the loop to make overhead from
     177             :          * branches &c small.
     178             :          */
     179           0 :         while ((mlen -= 32) >= 0) {
     180           0 :                 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
     181           0 :                 sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
     182           0 :                 sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
     183           0 :                 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
     184           0 :                 w += 16;
     185             :         }
     186             :         mlen += 32;
     187           0 :         while ((mlen -= 8) >= 0) {
     188           0 :                 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
     189           0 :                 w += 4;
     190             :         }
     191             :         mlen += 8;
     192           0 :         if (mlen == 0 && byte_swapped == 0)
     193             :                 goto next;
     194           0 :         REDUCE;
     195           0 :         while ((mlen -= 2) >= 0) {
     196           0 :                 sum += *w++;
     197             :         }
     198           0 :         if (byte_swapped) {
     199           0 :                 REDUCE;
     200           0 :                 sum <<= 8;
     201             :                 byte_swapped = 0;
     202           0 :                 if (mlen == -1) {
     203           0 :                         s_util.c[1] = *(char *)w;
     204           0 :                         sum += s_util.s;
     205             :                         mlen = 0;
     206           0 :                 } else
     207             :                         mlen = -1;
     208           0 :         } else if (mlen == -1)
     209           0 :                 s_util.c[0] = *(char *)w;
     210             :  next:
     211           0 :         m = m->m_next;
     212             : 
     213             :         /*
     214             :          * Lastly calculate a summary of the rest of mbufs.
     215             :          */
     216             : 
     217           0 :         for (;m && len; m = m->m_next) {
     218           0 :                 if (m->m_len == 0)
     219             :                         continue;
     220           0 :                 w = mtod(m, u_int16_t *);
     221           0 :                 if (mlen == -1) {
     222             :                         /*
     223             :                          * The first byte of this mbuf is the continuation
     224             :                          * of a word spanning between this mbuf and the
     225             :                          * last mbuf.
     226             :                          *
     227             :                          * s_util.c[0] is already saved when scanning previous
     228             :                          * mbuf.
     229             :                          */
     230           0 :                         s_util.c[1] = *(char *)w;
     231           0 :                         sum += s_util.s;
     232           0 :                         w = (u_int16_t *)((char *)w + 1);
     233           0 :                         mlen = m->m_len - 1;
     234           0 :                         len--;
     235           0 :                 } else
     236             :                         mlen = m->m_len;
     237           0 :                 if (len < mlen)
     238           0 :                         mlen = len;
     239           0 :                 len -= mlen;
     240             :                 /*
     241             :                  * Force to even boundary.
     242             :                  */
     243           0 :                 if ((1 & (long) w) && (mlen > 0)) {
     244           0 :                         REDUCE;
     245           0 :                         sum <<= 8;
     246           0 :                         s_util.c[0] = *(u_char *)w;
     247           0 :                         w = (u_int16_t *)((char *)w + 1);
     248           0 :                         mlen--;
     249             :                         byte_swapped = 1;
     250           0 :                 }
     251             :                 /*
     252             :                  * Unroll the loop to make overhead from
     253             :                  * branches &c small.
     254             :                  */
     255           0 :                 while ((mlen -= 32) >= 0) {
     256           0 :                         sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
     257           0 :                         sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
     258           0 :                         sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
     259           0 :                         sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
     260           0 :                         w += 16;
     261             :                 }
     262             :                 mlen += 32;
     263           0 :                 while ((mlen -= 8) >= 0) {
     264           0 :                         sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
     265           0 :                         w += 4;
     266             :                 }
     267             :                 mlen += 8;
     268           0 :                 if (mlen == 0 && byte_swapped == 0)
     269             :                         continue;
     270           0 :                 REDUCE;
     271           0 :                 while ((mlen -= 2) >= 0) {
     272           0 :                         sum += *w++;
     273             :                 }
     274           0 :                 if (byte_swapped) {
     275           0 :                         REDUCE;
     276           0 :                         sum <<= 8;
     277             :                         byte_swapped = 0;
     278           0 :                         if (mlen == -1) {
     279           0 :                                 s_util.c[1] = *(char *)w;
     280           0 :                                 sum += s_util.s;
     281             :                                 mlen = 0;
     282           0 :                         } else
     283             :                                 mlen = -1;
     284           0 :                 } else if (mlen == -1)
     285           0 :                         s_util.c[0] = *(char *)w;
     286             :         }
     287           0 :         if (len)
     288           0 :                 panic("in6_cksum: out of data");
     289           0 :         if (mlen == -1) {
     290             :                 /* The last mbuf has odd # of bytes. Follow the
     291             :                    standard (the odd byte may be shifted left by 8 bits
     292             :                    or not as determined by endian-ness of the machine) */
     293             :                 s_util.c[1] = 0;
     294           0 :                 sum += s_util.s;
     295           0 :         }
     296           0 :         REDUCE;
     297           0 :         return (~sum & 0xffff);
     298             : }

Generated by: LCOV version 1.13