Home | History | Annotate | Line # | Download | only in netinet6
in6_cksum.c revision 1.25
      1  1.25     yamt /*	$NetBSD: in6_cksum.c,v 1.25 2008/03/09 22:05:50 yamt Exp $	*/
      2   1.3  thorpej 
      3  1.23    joerg /*-
      4  1.23    joerg  * Copyright (c) 2008 Joerg Sonnenberger <joerg (at) NetBSD.org>.
      5   1.2   itojun  * All rights reserved.
      6   1.8   itojun  *
      7   1.2   itojun  * Redistribution and use in source and binary forms, with or without
      8   1.2   itojun  * modification, are permitted provided that the following conditions
      9   1.2   itojun  * are met:
     10   1.8   itojun  *
     11   1.2   itojun  * 1. Redistributions of source code must retain the above copyright
     12   1.2   itojun  *    notice, this list of conditions and the following disclaimer.
     13   1.2   itojun  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.23    joerg  *    notice, this list of conditions and the following disclaimer in
     15  1.23    joerg  *    the documentation and/or other materials provided with the
     16  1.23    joerg  *    distribution.
     17  1.23    joerg  *
     18  1.23    joerg  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  1.23    joerg  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  1.23    joerg  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     21  1.23    joerg  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
     22  1.23    joerg  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  1.23    joerg  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
     24  1.23    joerg  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  1.23    joerg  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     26  1.23    joerg  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     27  1.23    joerg  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     28  1.23    joerg  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29   1.2   itojun  * SUCH DAMAGE.
     30   1.2   itojun  */
     31  1.12    lukem 
     32  1.12    lukem #include <sys/cdefs.h>
     33  1.25     yamt __KERNEL_RCSID(0, "$NetBSD: in6_cksum.c,v 1.25 2008/03/09 22:05:50 yamt Exp $");
     34   1.2   itojun 
     35   1.2   itojun #include <sys/param.h>
     36   1.2   itojun #include <sys/mbuf.h>
     37   1.2   itojun #include <netinet/in.h>
     38   1.7   itojun #include <netinet/ip6.h>
     39   1.6   itojun 
     40   1.2   itojun /*
     41  1.23    joerg  * Checksum of the IPv6 pseudo header.
     42   1.2   itojun  *
     43  1.23    joerg  * off is supposed to be the skipped IPv6 header, len is the payload size.
     44   1.2   itojun  */
     45   1.2   itojun 
     46   1.2   itojun int
     47  1.23    joerg in6_cksum(struct mbuf *m, u_int8_t nxt, uint32_t off, uint32_t len)
     48   1.2   itojun {
     49   1.9   itojun 	union {
     50  1.23    joerg 		uint16_t words[16];
     51   1.9   itojun 		struct {
     52  1.23    joerg 			struct in6_addr ip6_src;
     53  1.23    joerg 			struct in6_addr ip6_dst;
     54  1.23    joerg 		} addrs;
     55  1.23    joerg 	} u;
     56  1.25     yamt 	const struct in6_addr *in6_src;
     57  1.25     yamt 	const struct in6_addr *in6_dst;
     58  1.25     yamt 	const struct ip6_hdr *ip6;
     59  1.23    joerg 	uint32_t sum;
     60  1.25     yamt 	const uint16_t *w;
     61  1.23    joerg 
     62  1.24    joerg 	if (__predict_false(off < sizeof(struct ip6_hdr)))
     63  1.23    joerg 		panic("in6_cksum: offset too short for IPv6 header");
     64  1.24    joerg 	if (__predict_false(m->m_len < sizeof(struct ip6_hdr)))
     65  1.23    joerg 		panic("in6_cksum: mbuf too short for IPv6 header");
     66   1.9   itojun 
     67  1.11  thorpej 	if (nxt == 0)
     68  1.23    joerg 		return cpu_in_cksum(m, len, off, 0);
     69   1.2   itojun 
     70   1.2   itojun 	/*
     71  1.23    joerg 	 * Compute the equivalent of:
     72  1.23    joerg 	 * struct ip6_hdr_pseudo ip6;
     73  1.23    joerg 	 *
     74  1.23    joerg 	 * bzero(sizeof(*ip6));
     75  1.23    joerg 	 * ip6.ip6ph_nxt = nxt;
     76  1.23    joerg 	 * ip6.ip6ph_len = htonl(len);
     77  1.23    joerg 	 * ipv6.ip6ph_src = mtod(m, struct ip6_hdr *)->ip6_src;
     78  1.23    joerg 	 * in6_clearscope(&ip6->ip6ph_src);
     79  1.23    joerg 	 * ipv6.ip6ph_dst = mtod(m, struct ip6_hdr *)->ip6_dst;
     80  1.23    joerg 	 * in6_clearscope(&ip6->ip6ph_dst);
     81  1.23    joerg 	 * sum = one_add(&ip6);
     82   1.2   itojun 	 */
     83   1.2   itojun 
     84  1.23    joerg #if BYTE_ORDER == LITTLE_ENDIAN
     85  1.23    joerg 	sum = ((len & 0xffff) + ((len >> 16) & 0xffff) + nxt) << 8;
     86  1.23    joerg #else
     87  1.23    joerg 	sum = (len & 0xffff) + ((len >> 16) & 0xffff) + nxt;
     88  1.23    joerg #endif
     89  1.25     yamt 	ip6 = mtod(m, const struct ip6_hdr *);
     90  1.25     yamt 	w = (const uint16_t *)(const void *)&ip6->ip6_src;
     91  1.23    joerg 	if (__predict_true((uintptr_t)w % 2 == 0)) {
     92  1.25     yamt 		in6_src = &ip6->ip6_src;
     93  1.25     yamt 		in6_dst = &ip6->ip6_dst;
     94  1.23    joerg 	} else {
     95  1.25     yamt 		memcpy(&u, &ip6->ip6_src, 32);
     96  1.23    joerg 		w = u.words;
     97  1.23    joerg 		in6_src = &u.addrs.ip6_src;
     98  1.23    joerg 		in6_dst = &u.addrs.ip6_dst;
     99  1.23    joerg 	}
    100  1.23    joerg 
    101  1.23    joerg 	sum += w[0];
    102  1.23    joerg 	if (!IN6_IS_SCOPE_LINKLOCAL(in6_src) &&
    103  1.23    joerg 	    !IN6_IS_ADDR_MC_INTFACELOCAL(in6_src))
    104  1.23    joerg 		sum += w[1];
    105  1.23    joerg 	sum += w[2];
    106  1.23    joerg 	sum += w[3];
    107  1.23    joerg 	sum += w[4];
    108  1.23    joerg 	sum += w[5];
    109  1.23    joerg 	sum += w[6];
    110  1.23    joerg 	sum += w[7];
    111  1.23    joerg 	w += 8;
    112  1.23    joerg 	sum += w[0];
    113  1.23    joerg 	if (!IN6_IS_SCOPE_LINKLOCAL(in6_dst) &&
    114  1.23    joerg 	    !IN6_IS_ADDR_MC_INTFACELOCAL(in6_dst))
    115  1.23    joerg 		sum += w[1];
    116  1.23    joerg 	sum += w[2];
    117  1.23    joerg 	sum += w[3];
    118  1.23    joerg 	sum += w[4];
    119  1.23    joerg 	sum += w[5];
    120  1.23    joerg 	sum += w[6];
    121  1.23    joerg 	sum += w[7];
    122   1.2   itojun 
    123  1.22    joerg 	return cpu_in_cksum(m, len, off, sum);
    124   1.2   itojun }
    125